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.
 
 
 

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