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.
 
 
 

188 line
4.8 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 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 <ctype.h>
  17. #include "core.h"
  18. using namespace std;
  19. namespace lol
  20. {
  21. /*
  22. * Map implementation class
  23. */
  24. class MapData
  25. {
  26. friend class Map;
  27. static int const MAX_TILESETS = 128;
  28. private:
  29. TileSet *tilesets[MAX_TILESETS];
  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_TILESETS];
  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. static int error = 1;
  79. if (error && !(error = 0))
  80. Log::Error("tilesets no longer work this way\n");
  81. //code = (data->tilesets[n] << 16) | (id - gids[n]);
  82. break;
  83. }
  84. }
  85. }
  86. int x = ntiles % data->width;
  87. int y = data->height - 1 - (ntiles / data->width);
  88. tiles[y * data->width + x] = code;
  89. ntiles++;
  90. while (isdigit(*parser))
  91. parser++;
  92. if (*parser == ',')
  93. parser++;
  94. if (!isdigit(*parser))
  95. break;
  96. }
  97. if (ntiles == data->width * data->height)
  98. {
  99. Layer *l = new Layer(data->width, data->height,
  100. level, orientation, tiles);
  101. data->layers[data->nlayers] = l;
  102. data->nlayers++;
  103. tiles = NULL;
  104. //Log::Debug("new layer %ix%i\n", data->width, data->height);
  105. }
  106. }
  107. else if (sscanf(tmp, " <tileset firstgid=\"%i\"", &i) == 1)
  108. {
  109. /* This is a tileset description. Remember its first gid value. */
  110. gids[data->ntilers] = i;
  111. }
  112. else if (sscanf(tmp, " <image source=\"%[^\"]\"", str) == 1)
  113. {
  114. /* This is a tileset image file. Associate it with firstgid. */
  115. data->tilesets[data->ntilers] = Tiler::Register(str, ivec2(32),
  116. ivec2(0));
  117. data->ntilers++;
  118. //Log::Debug("new tiler %s\n", str);
  119. }
  120. else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" "
  121. "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5)
  122. {
  123. /* This is a layer description. Prepare to read the data. */
  124. data->layers = (Layer **)realloc(data->layers,
  125. sizeof(Layer **) * (data->nlayers + 1));
  126. orientation = toupper(a) == 'V' ? 1 : 0;
  127. level = i * 32;
  128. data->width = j;
  129. data->height = k;
  130. tiles = (uint32_t *)malloc(j * k * sizeof(uint32_t));
  131. ntiles = 0;
  132. }
  133. }
  134. fclose(fp);
  135. }
  136. Map::~Map()
  137. {
  138. for (int i = 0; i < data->ntilers; i++)
  139. Tiler::Deregister(data->tilesets[i]);
  140. for (int i = 0; i < data->nlayers; i++)
  141. delete data->layers[i];
  142. free(data->layers);
  143. delete data;
  144. }
  145. void Map::Render(int x, int y, int z)
  146. {
  147. for (int i = 0; i < data->nlayers; i++)
  148. data->layers[i]->Render(x, y, z);
  149. }
  150. int Map::GetWidth()
  151. {
  152. return data->width * 32;
  153. }
  154. int Map::GetHeight()
  155. {
  156. return data->height * 32;
  157. }
  158. } /* namespace lol */