yupplemayham/YuppleMayham/src/gameplay/map.cpp

125 lines
No EOL
3.7 KiB
C++

#include "gameplay/map.h"
#include "gameplay/camera.h"
#include "graphics/shader.h"
#include "graphics/texture.h"
#include "utility/xmlloader.h"
#include "utility/resourcemanager.h"
#include "utility/logger.h"
#include <glm/gtc/matrix_transform.hpp>
Map::Map(std::shared_ptr<MapData> mapData, const unsigned shaderID, std::shared_ptr<ResourceManager> resourceManager) :
mapData(mapData),
tileIds(mapData->tiles)
{
this->shaderID = shaderID;
for (auto& tileSet : mapData->tileSets)
tileSetData.push_back(resourceManager->loadTileSet(tileSet.path));
if (!tileSetData.empty())
{
std::vector<const char*> buffer;
for (int layer = 0; layer < tileIds.size(); layer++)
{
buffer.clear();
for (auto& set : tileSetData)
buffer.push_back(set->file.c_str());
if (!buffer.empty())
instanceHandles.push_back(std::make_shared<TileTextureInstance>(buffer));
}
loadMap();
createCollisionMap();
}
}
#include <glm/ext.hpp>
void Map::loadMap()
{
tileData.resize(tileIds.size());
for (int layer = 0; layer < tileIds.size(); layer++)
{
for (int y = 0; y < tileIds[layer].size(); y++)
{
for (int x = 0; x < tileIds[layer][y].size(); x++)
{
glm::mat4 modelMatrix =
glm::translate(glm::mat4(1.f), glm::vec3(x * mapData->tileSize, y * mapData->tileSize, 0.0f)) *
glm::scale(glm::mat4(1.f), glm::vec3(mapData->tileSize, mapData->tileSize, 1.0f));
int textureIndex = static_cast<int>(getTileSetIndex(tileIds[layer][y][x]));
glm::vec2 originalSize = (textureIndex != -1) ?
glm::vec2(tileSetData[textureIndex]->width, tileSetData[textureIndex]->height) :
glm::vec2(0.0f);
int tilesPerRow = (textureIndex != -1) ? tileSetData[textureIndex]->columns : 0;
int startID = (textureIndex != -1) ? mapData->tileSets[textureIndex].startID : 0;
int tileIndex = tileIds[layer][y][x];
tileData[layer].push_back({modelMatrix, originalSize, tileIndex, textureIndex, tilesPerRow, startID});
}
}
instanceHandles[layer]->updateInstanceData(tileData[layer]);
}
glm::vec2 canvasSize = glm::vec2(instanceHandles[0]->getTextureArray()->getWidth(), instanceHandles[0]->getTextureArray()->getHeight());
editUniformOnce("uCanvasSize", canvasSize);
}
void Map::createCollisionMap()
{
// Match collisionMap to map size
collisionMap.resize(tileIds[0].size());
for (int y = 0; y < tileIds[0].size(); ++y)
{
collisionMap[y].resize(tileIds[0][y].size(), 0);
}
for (int layer = 0; layer < tileIds.size(); layer++)
{
for (int y = 0; y < tileIds[layer].size(); y++)
{
for (int x = 0; x < tileIds[layer][y].size(); x++)
{
int id = tileIds[layer][y][x];
size_t tileSetIndex = getTileSetIndex(id);
if (tileSetIndex == -1)
collisionMap[y][x] = 0;
else
{
int startID = mapData->tileSets[tileSetIndex].startID;
auto& tile = tileSetData[tileSetIndex]->tiles[id - startID];
if (!tile->walkable)
collisionMap[y][x] = 1;
}
}
}
}
}
void Map::draw()
{
for (int layer = 0; layer < instanceHandles.size(); layer++)
{
instanceHandles[layer]->draw();
}
}
/*
Use this function to get the tileSetIndex from a tile ID.
the index of the tileSet is the same index as the texture index used in the instanceHandle
returns tileSetIndex of the tile id passed. Unless the id is either 0 or
the returned tileSetIndex is out of bounds, returns -1
*/
size_t Map::getTileSetIndex(int id) const
{
// work from the bottom, break if ID > startID
// If we get a textureIndex of -1 then we are on an empty tile
size_t tileSetIndex = mapData->tileSets.size() - 1;
for (; tileSetIndex != -1; --tileSetIndex)
{
if (id >= mapData->tileSets[tileSetIndex].startID)
break;
}
return (tileSetIndex >= mapData->tileSets.size()) ? -1 : tileSetIndex;
}