You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

168 lines
4.1 KiB

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