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.
 
 
 

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