1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#include "map_layer.h"
#include "TextureMap.h"
#include <tmxlite/Layer.hpp>
#include <tmxlite/TileLayer.hpp>
MapLayer::MapLayer() {}
MapLayer::~MapLayer() { m_subsets.clear(); }
bool MapLayer::create(const tmx::Map & map, std::uint32_t layerIndex,
const std::vector<TextureMap *> & textures) {
const auto & layers = map.getLayers();
assert(layers[layerIndex]->getType() == tmx::Layer::Type::Tile);
const auto & layer = layers[layerIndex]->getLayerAs<tmx::TileLayer>();
const auto mapSize = map.getTileCount();
const auto mapTileSize = map.getTileSize();
const auto & tileSets = map.getTilesets();
const auto tintColour = layer.getTintColour();
const SDL_Colour vertColour
= {tintColour.r, tintColour.g, tintColour.b, tintColour.a};
for (auto i = 0u; i < tileSets.size(); ++i) {
//check tile ID to see if it falls within the current tile set
const auto & ts = tileSets[i];
const auto & tileIDs = layer.getTiles();
const auto texSize = textures[i]->getSize();
const auto tileCountX = texSize.x / mapTileSize.x;
const auto tileCountY = texSize.y / mapTileSize.y;
const float uNorm = static_cast<float>(mapTileSize.x) / texSize.x;
const float vNorm = static_cast<float>(mapTileSize.y) / texSize.y;
std::vector<SDL_Vertex> verts;
for (auto y = 0u; y < mapSize.y; ++y) {
for (auto x = 0u; x < mapSize.x; ++x) {
const auto idx = y * mapSize.x + x;
if (idx < tileIDs.size() && tileIDs[idx].ID >= ts.getFirstGID()
&& tileIDs[idx].ID
< (ts.getFirstGID() + ts.getTileCount())) {
//tex coords
auto idIndex = (tileIDs[idx].ID - ts.getFirstGID());
float u = static_cast<float>(idIndex % tileCountX);
float v = static_cast<float>(idIndex / tileCountY);
u *= mapTileSize
.x; //TODO we should be using the tile set size, as this may be different from the map's grid size
v *= mapTileSize.y;
//normalise the UV
u /= textures[i]->getSize().x;
v /= textures[i]->getSize().y;
//vert pos
const float tilePosX
= static_cast<float>(x) * mapTileSize.x;
const float tilePosY
= (static_cast<float>(y) * mapTileSize.y);
//push back to vert array
SDL_Vertex vert
= {{tilePosX, tilePosY}, vertColour, {u, v}};
verts.emplace_back(vert);
vert = {{tilePosX + mapTileSize.x, tilePosY},
vertColour,
{u + uNorm, v}};
verts.emplace_back(vert);
vert = {{tilePosX, tilePosY + mapTileSize.y},
vertColour,
{u, v + vNorm}};
verts.emplace_back(vert);
vert = {{tilePosX, tilePosY + mapTileSize.y},
vertColour,
{u, v + vNorm}};
verts.emplace_back(vert);
vert = {{tilePosX + mapTileSize.x, tilePosY},
vertColour,
{u + uNorm, v}};
verts.emplace_back(vert);
vert
= {{tilePosX + mapTileSize.x, tilePosY + mapTileSize.y},
vertColour,
{u + uNorm, v + vNorm}};
verts.emplace_back(vert);
}
}
}
if (!verts.empty()) {
m_subsets.emplace_back();
m_subsets.back().texture = *textures[i];
m_subsets.back().vertexData.swap(verts);
}
}
return true;
}
void MapLayer::draw(SDL_Renderer * renderer) const {
assert(renderer);
for (const auto & s : m_subsets) {
SDL_RenderGeometry(renderer, s.texture, s.vertexData.data(),
static_cast<std::int32_t>(s.vertexData.size()),
nullptr, 0);
}
}
|