2
0

TileSet.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #include "Base.h"
  2. #include "TileSet.h"
  3. #include "Matrix.h"
  4. #include "Scene.h"
  5. namespace gameplay
  6. {
  7. TileSet::TileSet() : Drawable(),
  8. _tiles(NULL), _tileWidth(0), _tileHeight(0),
  9. _rowCount(0), _columnCount(0), _width(0), _height(0),
  10. _opacity(1.0f), _color(Vector4::one()), _batch(NULL)
  11. {
  12. }
  13. TileSet::~TileSet()
  14. {
  15. SAFE_DELETE_ARRAY(_tiles);
  16. SAFE_DELETE(_batch);
  17. }
  18. TileSet& TileSet::operator=(const TileSet& set)
  19. {
  20. return *this;
  21. }
  22. TileSet* TileSet::create(const char* imagePath,
  23. float tileWidth, float tileHeight,
  24. unsigned int rowCount, unsigned int columnCount)
  25. {
  26. GP_ASSERT(imagePath);
  27. GP_ASSERT(tileWidth > 0 && tileHeight > 0);
  28. GP_ASSERT(rowCount > 0 && columnCount > 0);
  29. SpriteBatch* batch = SpriteBatch::create(imagePath);
  30. batch->getSampler()->setWrapMode(Texture::CLAMP, Texture::CLAMP);
  31. batch->getSampler()->setFilterMode(Texture::Filter::NEAREST, Texture::Filter::NEAREST);
  32. batch->getStateBlock()->setDepthWrite(false);
  33. batch->getStateBlock()->setDepthTest(true);
  34. TileSet* tileset = new TileSet();
  35. tileset->_batch = batch;
  36. tileset->_tiles = new Vector2[rowCount * columnCount];
  37. memset(tileset->_tiles, -1, sizeof(float) * rowCount * columnCount * 2);
  38. tileset->_tileWidth = tileWidth;
  39. tileset->_tileHeight = tileHeight;
  40. tileset->_rowCount = rowCount;
  41. tileset->_columnCount = columnCount;
  42. tileset->_width = tileWidth * columnCount;
  43. tileset->_height = tileHeight * rowCount;
  44. return tileset;
  45. }
  46. TileSet* TileSet::create(Properties* properties)
  47. {
  48. // Check if the Properties is valid and has a valid namespace.
  49. if (!properties || strcmp(properties->getNamespace(), "tileset") != 0)
  50. {
  51. GP_ERROR("Properties object must be non-null and have namespace equal to 'tileset'.");
  52. return NULL;
  53. }
  54. // Get image path.
  55. const char* imagePath = properties->getString("path");
  56. if (imagePath == NULL || strlen(imagePath) == 0)
  57. {
  58. GP_ERROR("TileSet is missing required image file path.");
  59. return NULL;
  60. }
  61. // Get set size
  62. int rows = properties->getInt("rows");
  63. if (rows <= 0)
  64. {
  65. GP_ERROR("TileSet row count must be greater then zero.");
  66. return NULL;
  67. }
  68. int columns = properties->getInt("columns");
  69. if (columns <= 0)
  70. {
  71. GP_ERROR("TileSet column count must be greater then zero.");
  72. return NULL;
  73. }
  74. // Get tile size
  75. float tileWidth = properties->getFloat("tileWidth");
  76. if (tileWidth <= 0)
  77. {
  78. GP_ERROR("TileSet tile width must be greater then zero.");
  79. return NULL;
  80. }
  81. float tileHeight = properties->getFloat("tileHeight");
  82. if (tileHeight <= 0)
  83. {
  84. GP_ERROR("TileSet tile height must be greater then zero.");
  85. return NULL;
  86. }
  87. // Create tile set
  88. TileSet* set = TileSet::create(imagePath, tileWidth, tileHeight, rows, columns);
  89. // Get color
  90. if (properties->exists("color"))
  91. {
  92. Vector4 color;
  93. switch (properties->getType("color"))
  94. {
  95. case Properties::VECTOR3:
  96. color.w = 1.0f;
  97. properties->getVector3("color", (Vector3*)&color);
  98. break;
  99. case Properties::VECTOR4:
  100. properties->getVector4("color", &color);
  101. break;
  102. case Properties::STRING:
  103. default:
  104. properties->getColor("color", &color);
  105. break;
  106. }
  107. set->setColor(color);
  108. }
  109. // Get opacity
  110. if (properties->exists("opacity"))
  111. {
  112. set->setOpacity(properties->getFloat("opacity"));
  113. }
  114. // Get tile sources
  115. properties->rewind();
  116. Properties* tileProperties = NULL;
  117. while ((tileProperties = properties->getNextNamespace()))
  118. {
  119. if (strcmp(tileProperties->getNamespace(), "tile") == 0)
  120. {
  121. Vector2 cell;
  122. Vector2 source;
  123. if (tileProperties->getVector2("cell", &cell) && tileProperties->getVector2("source", &source) &&
  124. (cell.x > 0 && cell.y > 0 && cell.x < set->_columnCount && cell.y < set->_rowCount))
  125. {
  126. set->_tiles[(int)cell.y * set->_columnCount + (int)cell.x] = source;
  127. }
  128. }
  129. }
  130. return set;
  131. }
  132. void TileSet::setTileSource(unsigned int column, unsigned int row, const Vector2& source)
  133. {
  134. GP_ASSERT(column < _columnCount);
  135. GP_ASSERT(row < _rowCount);
  136. _tiles[row * _columnCount + column] = source;
  137. }
  138. void TileSet::getTileSource(unsigned int column, unsigned int row, Vector2* source)
  139. {
  140. GP_ASSERT(column < _columnCount);
  141. GP_ASSERT(row < _rowCount);
  142. GP_ASSERT(source);
  143. source->x = _tiles[row * _columnCount + column].x;
  144. source->y = _tiles[row * _columnCount + column].y;
  145. }
  146. float TileSet::getTileWidth() const
  147. {
  148. return _tileWidth;
  149. }
  150. float TileSet::getTileHeight() const
  151. {
  152. return _tileHeight;
  153. }
  154. unsigned int TileSet::getRowCount() const
  155. {
  156. return _rowCount;
  157. }
  158. unsigned int TileSet::getColumnCount() const
  159. {
  160. return _columnCount;
  161. }
  162. float TileSet::getWidth() const
  163. {
  164. return _width;
  165. }
  166. float TileSet::getHeight() const
  167. {
  168. return _height;
  169. }
  170. void TileSet::setOpacity(float opacity)
  171. {
  172. _opacity = opacity;
  173. }
  174. float TileSet::getOpacity() const
  175. {
  176. return _opacity;
  177. }
  178. void TileSet::setColor(const Vector4& color)
  179. {
  180. _color = color;
  181. }
  182. const Vector4& TileSet::getColor() const
  183. {
  184. return _color;
  185. }
  186. unsigned int TileSet::draw(bool wireframe)
  187. {
  188. // Apply scene camera projection and translation offsets
  189. Vector3 position = Vector3::zero();
  190. if (_node && _node->getScene())
  191. {
  192. Camera* activeCamera = _node->getScene()->getActiveCamera();
  193. if (activeCamera)
  194. {
  195. Node* cameraNode = _node->getScene()->getActiveCamera()->getNode();
  196. if (cameraNode)
  197. {
  198. // Scene projection
  199. Matrix projectionMatrix;
  200. projectionMatrix = _node->getProjectionMatrix();
  201. _batch->setProjectionMatrix(projectionMatrix);
  202. position.x -= cameraNode->getTranslationWorld().x;
  203. position.y -= cameraNode->getTranslationWorld().y;
  204. }
  205. }
  206. // Apply node translation offsets
  207. Vector3 translation = _node->getTranslationWorld();
  208. position.x += translation.x;
  209. position.y += translation.y;
  210. position.z += translation.z;
  211. }
  212. // Draw each cell in the tile set
  213. position.y += _tileHeight * (_rowCount - 1);
  214. float xStart = position.x;
  215. _batch->start();
  216. for (unsigned int row = 0; row < _rowCount; row++)
  217. {
  218. for (unsigned int col = 0; col < _columnCount; col++)
  219. {
  220. Vector2 scale = Vector2(_tileWidth, _tileHeight);
  221. // Negative values are skipped to allow blank tiles
  222. if (_tiles[row * _columnCount + col].x >= 0 &&
  223. _tiles[row * _columnCount + col].y >= 0)
  224. {
  225. Rectangle source = Rectangle(_tiles[row * _columnCount + col].x,
  226. _tiles[row * _columnCount + col].y, _tileWidth, _tileHeight);
  227. _batch->draw(position, source, scale, Vector4(_color.x, _color.y, _color.z, _color.w * _opacity),
  228. Vector2(0.5f, 0.5f), 0);
  229. }
  230. position.x += _tileWidth;
  231. }
  232. position.x = xStart;
  233. position.y -= _tileHeight;
  234. }
  235. _batch->finish();
  236. return 1;
  237. }
  238. Drawable* TileSet::clone(NodeCloneContext& context)
  239. {
  240. TileSet* tilesetClone = new TileSet();
  241. // Clone properties
  242. tilesetClone->_tiles = new Vector2[tilesetClone->_rowCount * tilesetClone->_columnCount];
  243. memset(tilesetClone->_tiles, -1, sizeof(float) * tilesetClone->_rowCount * tilesetClone->_columnCount * 2);
  244. memcpy(tilesetClone->_tiles, _tiles, sizeof(Vector2) * tilesetClone->_rowCount * tilesetClone->_columnCount);
  245. tilesetClone->_tileWidth = _tileWidth;
  246. tilesetClone->_tileHeight = _tileHeight;
  247. tilesetClone->_rowCount = _rowCount;
  248. tilesetClone->_columnCount = _columnCount;
  249. tilesetClone->_width = _tileWidth * _columnCount;
  250. tilesetClone->_height = _tileHeight * _rowCount;
  251. tilesetClone->_opacity = _opacity;
  252. tilesetClone->_color = _color;
  253. tilesetClone->_batch = _batch;
  254. return tilesetClone;
  255. }
  256. }