184 行
4.6 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstdio>
  14. #include <cstring>
  15. #include <cstdlib>
  16. #include <cmath>
  17. #include <ctype.h>
  18. #include "core.h"
  19. namespace lol
  20. {
  21. /*
  22. * Map implementation class
  23. */
  24. class MapData
  25. {
  26. friend class Map;
  27. static int const MAX_TILERS = 128;
  28. private:
  29. int tilers[MAX_TILERS];
  30. int ntilers;
  31. Layer **layers;
  32. int nlayers;
  33. int width, height;
  34. };
  35. /*
  36. * Public Map class
  37. */
  38. Map::Map(char const *path)
  39. : data(new MapData())
  40. {
  41. data->ntilers = 0;
  42. data->layers = NULL;
  43. data->nlayers = 0;
  44. data->width = 0;
  45. data->height = 0;
  46. char tmp[BUFSIZ];
  47. int gids[MapData::MAX_TILERS];
  48. uint32_t *tiles = NULL;
  49. int level = 0, orientation = 0, ntiles = 0;
  50. FILE *fp = fopen(path, "r");
  51. if (!fp)
  52. return;
  53. while (!feof(fp))
  54. {
  55. char str[1024];
  56. int i, j, k;
  57. char a, b;
  58. /* Read a line, then decide what to do with it. */
  59. fgets(tmp, BUFSIZ, fp);
  60. if (tiles && !strchr(tmp, '<'))
  61. {
  62. /* We are in the process of reading layer data. Only stop
  63. * when we have read the expected number of tiles. */
  64. char const *parser = tmp;
  65. while (ntiles < data->width * data->height)
  66. {
  67. uint32_t code = 0;
  68. int id = atoi(parser);
  69. if (id)
  70. {
  71. for (int n = 0; n < data->ntilers; n++)
  72. {
  73. if (id < gids[n])
  74. continue;
  75. if (n == data->ntilers - 1
  76. || id < gids[n + 1])
  77. {
  78. code = (data->tilers[n] << 16) | (id - gids[n]);
  79. break;
  80. }
  81. }
  82. }
  83. int x = ntiles % data->width;
  84. int y = data->height - 1 - (ntiles / data->width);
  85. tiles[y * data->width + x] = code;
  86. ntiles++;
  87. while (isdigit(*parser))
  88. parser++;
  89. if (*parser == ',')
  90. parser++;
  91. if (!isdigit(*parser))
  92. break;
  93. }
  94. if (ntiles == data->width * data->height)
  95. {
  96. Layer *l = new Layer(data->width, data->height,
  97. level, orientation, tiles);
  98. data->layers[data->nlayers] = l;
  99. data->nlayers++;
  100. tiles = NULL;
  101. //Log::Debug("new layer %ix%i\n", data->width, data->height);
  102. }
  103. }
  104. else if (sscanf(tmp, " <tileset firstgid=\"%i\"", &i) == 1)
  105. {
  106. /* This is a tileset description. Remember its first gid value. */
  107. gids[data->ntilers] = i;
  108. }
  109. else if (sscanf(tmp, " <image source=\"%[^\"]\"", str) == 1)
  110. {
  111. /* This is a tileset image file. Associate it with firstgid. */
  112. data->tilers[data->ntilers] = Tiler::Register(str, 32, 0,
  113. sqrtf(2));
  114. data->ntilers++;
  115. //Log::Debug("new tiler %s\n", str);
  116. }
  117. else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" "
  118. "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5)
  119. {
  120. /* This is a layer description. Prepare to read the data. */
  121. data->layers = (Layer **)realloc(data->layers,
  122. sizeof(Layer **) * (data->nlayers + 1));
  123. orientation = toupper(a) == 'V' ? 1 : 0;
  124. level = i * 32;
  125. data->width = j;
  126. data->height = k;
  127. tiles = (uint32_t *)malloc(j * k * sizeof(uint32_t));
  128. ntiles = 0;
  129. }
  130. }
  131. fclose(fp);
  132. }
  133. Map::~Map()
  134. {
  135. for (int i = 0; i < data->ntilers; i++)
  136. Tiler::Deregister(data->tilers[i]);
  137. for (int i = 0; i < data->nlayers; i++)
  138. delete data->layers[i];
  139. free(data->layers);
  140. delete data;
  141. }
  142. void Map::Render(int x, int y, int z)
  143. {
  144. for (int i = 0; i < data->nlayers; i++)
  145. data->layers[i]->Render(x, y, z);
  146. }
  147. int Map::GetWidth()
  148. {
  149. return data->width * 32;
  150. }
  151. int Map::GetHeight()
  152. {
  153. return data->height * 32;
  154. }
  155. } /* namespace lol */