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.
 
 
 

189 lines
4.9 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. using namespace std;
  20. namespace lol
  21. {
  22. /*
  23. * Map implementation class
  24. */
  25. class MapData
  26. {
  27. friend class Map;
  28. static int const MAX_TILESETS = 128;
  29. private:
  30. TileSet *tilesets[MAX_TILESETS];
  31. int ntilers;
  32. Layer **layers;
  33. int nlayers;
  34. int width, height;
  35. };
  36. /*
  37. * Public Map class
  38. */
  39. Map::Map(char const *path)
  40. : data(new MapData())
  41. {
  42. data->ntilers = 0;
  43. data->layers = NULL;
  44. data->nlayers = 0;
  45. data->width = 0;
  46. data->height = 0;
  47. char tmp[BUFSIZ];
  48. int gids[MapData::MAX_TILESETS];
  49. uint32_t *tiles = NULL;
  50. int level = 0, orientation = 0, ntiles = 0;
  51. FILE *fp = fopen(path, "r");
  52. if (!fp)
  53. return;
  54. while (!feof(fp))
  55. {
  56. char str[1024];
  57. int i, j, k;
  58. char a, b;
  59. /* Read a line, then decide what to do with it. */
  60. fgets(tmp, BUFSIZ, fp);
  61. if (tiles && !strchr(tmp, '<'))
  62. {
  63. /* We are in the process of reading layer data. Only stop
  64. * when we have read the expected number of tiles. */
  65. char const *parser = tmp;
  66. while (ntiles < data->width * data->height)
  67. {
  68. uint32_t code = 0;
  69. int id = atoi(parser);
  70. if (id)
  71. {
  72. for (int n = 0; n < data->ntilers; n++)
  73. {
  74. if (id < gids[n])
  75. continue;
  76. if (n == data->ntilers - 1
  77. || id < gids[n + 1])
  78. {
  79. static int error = 1;
  80. if (error && !(error = 0))
  81. Log::Error("tilesets no longer work this way\n");
  82. //code = (data->tilesets[n] << 16) | (id - gids[n]);
  83. break;
  84. }
  85. }
  86. }
  87. int x = ntiles % data->width;
  88. int y = data->height - 1 - (ntiles / data->width);
  89. tiles[y * data->width + x] = code;
  90. ntiles++;
  91. while (isdigit(*parser))
  92. parser++;
  93. if (*parser == ',')
  94. parser++;
  95. if (!isdigit(*parser))
  96. break;
  97. }
  98. if (ntiles == data->width * data->height)
  99. {
  100. Layer *l = new Layer(data->width, data->height,
  101. level, orientation, tiles);
  102. data->layers[data->nlayers] = l;
  103. data->nlayers++;
  104. tiles = NULL;
  105. //Log::Debug("new layer %ix%i\n", data->width, data->height);
  106. }
  107. }
  108. else if (sscanf(tmp, " <tileset firstgid=\"%i\"", &i) == 1)
  109. {
  110. /* This is a tileset description. Remember its first gid value. */
  111. gids[data->ntilers] = i;
  112. }
  113. else if (sscanf(tmp, " <image source=\"%[^\"]\"", str) == 1)
  114. {
  115. /* This is a tileset image file. Associate it with firstgid. */
  116. data->tilesets[data->ntilers] = Tiler::Register(str, 32, 0,
  117. sqrtf(2));
  118. data->ntilers++;
  119. //Log::Debug("new tiler %s\n", str);
  120. }
  121. else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" "
  122. "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5)
  123. {
  124. /* This is a layer description. Prepare to read the data. */
  125. data->layers = (Layer **)realloc(data->layers,
  126. sizeof(Layer **) * (data->nlayers + 1));
  127. orientation = toupper(a) == 'V' ? 1 : 0;
  128. level = i * 32;
  129. data->width = j;
  130. data->height = k;
  131. tiles = (uint32_t *)malloc(j * k * sizeof(uint32_t));
  132. ntiles = 0;
  133. }
  134. }
  135. fclose(fp);
  136. }
  137. Map::~Map()
  138. {
  139. for (int i = 0; i < data->ntilers; i++)
  140. Tiler::Deregister(data->tilesets[i]);
  141. for (int i = 0; i < data->nlayers; i++)
  142. delete data->layers[i];
  143. free(data->layers);
  144. delete data;
  145. }
  146. void Map::Render(int x, int y, int z)
  147. {
  148. for (int i = 0; i < data->nlayers; i++)
  149. data->layers[i]->Render(x, y, z);
  150. }
  151. int Map::GetWidth()
  152. {
  153. return data->width * 32;
  154. }
  155. int Map::GetHeight()
  156. {
  157. return data->height * 32;
  158. }
  159. } /* namespace lol */