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.
 
 
 

234 line
5.4 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 <cstdlib>
  14. #include <cmath>
  15. #ifdef WIN32
  16. # define WIN32_LEAN_AND_MEAN
  17. # include <windows.h>
  18. #endif
  19. #if defined __APPLE__ && defined __MACH__
  20. # include <OpenGL/gl.h>
  21. #else
  22. # define GL_GLEXT_PROTOTYPES
  23. # include <GL/gl.h>
  24. #endif
  25. #include <SDL.h>
  26. #include <SDL_image.h>
  27. #include "core.h"
  28. /*
  29. * TileSet implementation class
  30. */
  31. class TileSetData
  32. {
  33. friend class TileSet;
  34. private:
  35. char *name, *path;
  36. int *tiles, ntiles;
  37. int2 size, count;
  38. float dilate, tx, ty;
  39. SDL_Surface *img;
  40. GLuint texture;
  41. };
  42. /*
  43. * Public TileSet class
  44. */
  45. TileSet::TileSet(char const *path, int2 size, int2 count, float dilate)
  46. : data(new TileSetData())
  47. {
  48. data->name = (char *)malloc(10 + strlen(path) + 1);
  49. data->path = data->name + 10;
  50. sprintf(data->name, "<tileset> %s", path);
  51. data->tiles = NULL;
  52. data->img = NULL;
  53. data->texture = 0;
  54. for (char const *name = path; *name; name++)
  55. if ((data->img = IMG_Load(name)))
  56. break;
  57. if (!data->img)
  58. {
  59. #if !FINAL_RELEASE
  60. fprintf(stderr, "ERROR: could not load %s\n", path);
  61. #endif
  62. SDL_Quit();
  63. exit(1);
  64. }
  65. if (count.i > 0 && count.j > 0)
  66. {
  67. data->count = count;
  68. data->size = int2(data->img->w, data->img->h) / count;
  69. }
  70. else
  71. {
  72. if (size.x <= 0 || size.y <= 0)
  73. size = 32;
  74. data->count.i = data->img->w > size.i ? data->img->w / size.i : 1;
  75. data->count.j = data->img->h > size.j ? data->img->h / size.j : 1;
  76. data->size = size;
  77. }
  78. data->dilate = dilate;
  79. data->ntiles = data->count.i * data->count.j;
  80. data->tx = (float)data->size.x / PotUp(data->img->w);
  81. data->ty = (float)data->size.y / PotUp(data->img->h);
  82. drawgroup = DRAWGROUP_BEFORE;
  83. }
  84. TileSet::~TileSet()
  85. {
  86. free(data->tiles);
  87. free(data->name);
  88. delete data;
  89. }
  90. void TileSet::TickDraw(float deltams)
  91. {
  92. Entity::TickDraw(deltams);
  93. if (IsDestroying())
  94. {
  95. if (data->img)
  96. SDL_FreeSurface(data->img);
  97. else
  98. glDeleteTextures(1, &data->texture);
  99. }
  100. else if (data->img)
  101. {
  102. GLuint format = data->img->format->Amask ? GL_RGBA : GL_RGB;
  103. int planes = data->img->format->Amask ? 4 : 3;
  104. int w = PotUp(data->img->w);
  105. int h = PotUp(data->img->h);
  106. uint8_t *pixels = (uint8_t *)data->img->pixels;
  107. if (w != data->img->w || h != data->img->h)
  108. {
  109. uint8_t *tmp = (uint8_t *)malloc(planes * w * h);
  110. for (int line = 0; line < data->img->h; line++)
  111. memcpy(tmp + planes * w * line,
  112. pixels + planes * data->img->w * line,
  113. planes * data->img->w);
  114. pixels = tmp;
  115. }
  116. glGenTextures(1, &data->texture);
  117. glBindTexture(GL_TEXTURE_2D, data->texture);
  118. glTexImage2D(GL_TEXTURE_2D, 0, planes, w, h, 0,
  119. format, GL_UNSIGNED_BYTE, pixels);
  120. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  121. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  122. if (pixels != data->img->pixels)
  123. free(pixels);
  124. SDL_FreeSurface(data->img);
  125. data->img = NULL;
  126. }
  127. }
  128. char const *TileSet::GetName()
  129. {
  130. return data->name;
  131. }
  132. int2 TileSet::GetSize() const
  133. {
  134. return data->size;
  135. }
  136. int2 TileSet::GetCount() const
  137. {
  138. return data->count;
  139. }
  140. void TileSet::Bind()
  141. {
  142. if (!data->img)
  143. glBindTexture(GL_TEXTURE_2D, data->texture);
  144. }
  145. void TileSet::BlitTile(uint32_t id, int x, int y, int z, int o,
  146. float *vertex, float *texture)
  147. {
  148. float tx = data->tx * ((id & 0xffff) % data->count.i);
  149. float ty = data->ty * ((id & 0xffff) / data->count.i);
  150. float dilate = data->dilate;
  151. int dx = data->size.x;
  152. int dy = o ? 0 : data->size.y;
  153. int dz = o ? data->size.y : 0;
  154. if (!data->img)
  155. {
  156. float tmp[10];
  157. *vertex++ = tmp[0] = x;
  158. *vertex++ = tmp[1] = dilate * (y + dy);
  159. *vertex++ = tmp[2] = dilate * (z + dz);
  160. *texture++ = tmp[3] = tx;
  161. *texture++ = tmp[4] = ty;
  162. *vertex++ = x + dx;
  163. *vertex++ = dilate * (y + dy);
  164. *vertex++ = dilate * (z + dz);
  165. *texture++ = tx + data->tx;
  166. *texture++ = ty;
  167. *vertex++ = tmp[5] = x + dx;
  168. *vertex++ = tmp[6] = dilate * y;
  169. *vertex++ = tmp[7] = dilate * z;
  170. *texture++ = tmp[8] = tx + data->tx;
  171. *texture++ = tmp[9] = ty + data->ty;
  172. *vertex++ = tmp[0];
  173. *vertex++ = tmp[1];
  174. *vertex++ = tmp[2];
  175. *texture++ = tmp[3];
  176. *texture++ = tmp[4];
  177. *vertex++ = tmp[5];
  178. *vertex++ = tmp[6];
  179. *vertex++ = tmp[7];
  180. *texture++ = tmp[8];
  181. *texture++ = tmp[9];
  182. *vertex++ = x;
  183. *vertex++ = dilate * y;
  184. *vertex++ = dilate * z;
  185. *texture++ = tx;
  186. *texture++ = ty + data->ty;
  187. }
  188. else
  189. {
  190. memset(vertex, 0, 3 * sizeof(float));
  191. memset(texture, 0, 2 * sizeof(float));
  192. }
  193. }