From 9e346a719df5da7840170a3550f77c9bf5d87d80 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Fri, 15 Nov 2024 22:25:43 +0100 Subject: [PATCH 1/4] Reimplemented collision still missing documentation --- include/Map.h | 9 +++++++-- src/Map.cpp | 47 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/include/Map.h b/include/Map.h index 92b8179..ab784bb 100644 --- a/include/Map.h +++ b/include/Map.h @@ -1,8 +1,11 @@ #pragma once +#include +#include #include #include #include +#include class GameInternal; class Map @@ -32,5 +35,7 @@ public: */ static void loadMapTmx(const char* path); private: - static void addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath); -}; + static void addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath, bool hasCollision); + template + static std::optional getLayerProperty(const std::vector& properties, std::string propertyName) { return std::nullopt; }; +}; \ No newline at end of file diff --git a/src/Map.cpp b/src/Map.cpp index 1653c72..0fb735b 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include +#include "ColliderComponent.h" #include "Constants.h" #include "GameInternal.h" #include "SpriteComponent.h" @@ -81,6 +83,31 @@ void Map::addTile(unsigned long id, int x, int y, GameInternal* game, const std: tile.addGroup((size_t)Entity::GroupLabel::MAPTILES); } + +template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) { + auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; + }); + + if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Boolean) { + return zIndexIterator->getBoolValue(); + } + + return std::nullopt; +} + +template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) { + auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; + }); + + if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Int) { + return zIndexIterator->getIntValue(); + } + + return std::nullopt; +} + void Map::loadMapTmx(const char* path) { tmx::Map map; @@ -105,16 +132,11 @@ void Map::loadMapTmx(const char* path) if (layer->getType() == tmx::Layer::Type::Tile) { auto& tileLayer = layer->getLayerAs(); - int zIndex = 0; - const std::vector& properties = layer->getProperties(); - auto zIndexIterator = std::find_if(properties.begin(), properties.end(), [](const tmx::Property& property) { - return property.getName() == "zIndex"; - }); + int zIndex = getLayerProperty(properties, "zIndex").value_or(0); + bool collision = getLayerProperty(properties, "collision").value_or(false); - if (zIndexIterator != properties.end() && std::is_nothrow_convertiblegetType()), int>::value) { - zIndex = zIndexIterator->getIntValue(); - } + printf("z-index: %d, collision: %d\n", zIndex, collision); const auto& tiles = tileLayer.getTiles(); @@ -151,7 +173,7 @@ void Map::loadMapTmx(const char* path) const float tilePosX = static_cast(x) * mapTileSize.x; const float tilePosY = (static_cast(y) * mapTileSize.y); - Map::addTile(tilePosX, tilePosY, mapTileSize, u, v, zIndex, texturePaths.at(i).c_str()); + Map::addTile(tilePosX, tilePosY, mapTileSize, u, v, zIndex, texturePaths.at(i).c_str(), collision); } } if (layer->getType() == tmx::Layer::Type::Object) { @@ -162,10 +184,15 @@ void Map::loadMapTmx(const char* path) } } -void Map::addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath) +void Map::addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath, bool hasCollision) { auto& tile(VEGO_Game().manager.addEntity()); tile.addComponent(x, y, mapTileSize.x, mapTileSize.y, 1); tile.addComponent(texturePath, v, u, zIndex); // why does uv need to be reversed? + + if (hasCollision) { + tile.addComponent("hello I am a collider of a tile!"); + tile.addGroup((size_t)Entity::GroupLabel::MAPTILES); + } } \ No newline at end of file From 7f4b1df8338a32188f4339dc5ccc47643c6fbc8a Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sat, 16 Nov 2024 19:31:44 +0100 Subject: [PATCH 2/4] Restructured code --- CMakeLists.txt | 2 +- include/Map.h | 49 ++++++--- src/GameInternal.cpp | 2 - src/Map.cpp | 250 ++++++++++++++++++++----------------------- 4 files changed, 151 insertions(+), 152 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 602370b..e222a1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.15) project(engine) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(ENGINE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/include/Map.h b/include/Map.h index ab784bb..ed9af33 100644 --- a/include/Map.h +++ b/include/Map.h @@ -1,5 +1,8 @@ #pragma once +#include "tmxlite/Map.hpp" +#include "tmxlite/TileLayer.hpp" +#include #include #include #include @@ -11,31 +14,45 @@ class GameInternal; class Map { public: - Map() = default; - ~Map() = default; + Map(const char* path); - /*! - * - * \brief - * This loads a map - * - * \param path The path to the map file - * \return Boolean for success - * - */ - [[deprecated("ID based text files are not supported anymore, use .txm maps instead")]] - static void loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map>* textureDict /* backreference */); - [[deprecated]] - static void addTile(unsigned long id, int x, int y, GameInternal* game, const std::map>* textureDict); + //[[deprecated("ID based text files are not supported anymore, use .tmx maps instead")]] + //static void loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map>* textureDict /* backreference */); + //[[deprecated]] + //static void addTile(unsigned long id, int x, int y, GameInternal* game, const std::map>* textureDict); /*! * \brief Loads a .tmx map * \param path Path to the `.tmx` map file * */ - static void loadMapTmx(const char* path); + + void generateTiles(); private: + // required for initialisation + struct MapData { + const std::vector* tileSets; + const std::vector* mapLayers; + const tmx::Vector2u* mapSize; + const tmx::Vector2u* mapTileSize; + const std::vector* texturePaths; + }; + + struct TileSetData { + const char* texturePath{}; + tmx::Vector2i textureSize; + uint32_t tileCount{}; + tmx::Vector2u tileCount2D; + uint32_t firstGID{}; + }; + + tmx::Map map; + Map::MapData mapData; + std::vector> tileConstructors; + + void loadTileLayer(const tmx::TileLayer& layer); static void addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath, bool hasCollision); + template static std::optional getLayerProperty(const std::vector& properties, std::string propertyName) { return std::nullopt; }; }; \ No newline at end of file diff --git a/src/GameInternal.cpp b/src/GameInternal.cpp index c5ba507..e32bb00 100644 --- a/src/GameInternal.cpp +++ b/src/GameInternal.cpp @@ -133,8 +133,6 @@ void GameInternal::init(const char* title, int xpos, int ypos, int width, int he if (this->isRunning() == false) return; - map = new Map(); - // loading sounds // assets->addSoundEffect("throw_egg", "assets/sound/throw_egg.wav"); // assets->addSoundEffect("steps", "assets/sound/steps.wav"); diff --git a/src/Map.cpp b/src/Map.cpp index 0fb735b..975b83b 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -2,10 +2,14 @@ #include #include +#include #include +#include #include #include #include +#include +#include #include #include #include @@ -28,171 +32,151 @@ #include "VEGO.h" #include "tmxlite/Types.hpp" -void Map::loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map>* textureDict /* backreference */) -{ - std::string tileIDstr; - char singleChar = 0; - std::ifstream mapFile; - mapFile.open(path); - - if (!mapFile.is_open()) { - SDL_SetError("Error loading map: Couldn't open map file!"); - std::cout << "ERROR: Map couldnt be loaded! " << SDL_GetError() << std::endl; - SDL_ClearError(); - } - - int x = 0, y = 0; // needed outside for-loop for error handling - for (; !mapFile.eof(); mapFile.get(singleChar)) - { - if (singleChar == ',' || singleChar == '\n') { - if (tileIDstr.empty()) - continue; - Map::addTile(std::stoi(tileIDstr), x * TILE_SIZE, y * TILE_SIZE, game, textureDict); - tileIDstr.clear(); - x++; - if (singleChar == '\n') { - if (x != sizeX) { - SDL_SetError("Error loading map: specified x size doesn't match map file!"); - std::cout << "ERROR: Map couldnt be loaded! " << SDL_GetError() << std::endl; - SDL_ClearError(); - } - x = 0; - y++; - continue; - } - continue; - } - if (!std::isdigit(singleChar)) continue; - tileIDstr += singleChar; - } - if (y != sizeY) { - SDL_SetError("Error loading map: specified y size doesn't match map file!"); - std::cout << "ERROR: Map couldnt be loaded! " << SDL_GetError() << std::endl; - SDL_ClearError(); - } - - mapFile.close(); -} - -void Map::addTile(unsigned long id, int x, int y, GameInternal* game, const std::map>* textureDict) // tile entity -{ - auto& tile(game->manager.addEntity()); - tile.addComponent(x, y, TILE_SIZE, TILE_SIZE, id, textureDict); - - if(tile.getComponent().hasCollision()) tile.addComponent(tile.getComponent().getName().data()); - tile.addGroup((size_t)Entity::GroupLabel::MAPTILES); -} - - template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) { - auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { - return property.getName().compare(propertyName) == 0; - }); +auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; +}); - if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Boolean) { - return zIndexIterator->getBoolValue(); - } +if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Boolean) { + return zIndexIterator->getBoolValue(); +} - return std::nullopt; +return std::nullopt; } template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) { - auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { - return property.getName().compare(propertyName) == 0; - }); +auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; +}); - if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Int) { - return zIndexIterator->getIntValue(); - } - - return std::nullopt; +if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Int) { + return zIndexIterator->getIntValue(); } -void Map::loadMapTmx(const char* path) +return std::nullopt; +} + +Map::Map(const char* path) { - tmx::Map map; - if (!map.load(path)) { + if (!this->map.load(path)) { // TODO: log to console + // TODO: error handling } - const std::vector& tileSets = map.getTilesets(); - - const std::vector& mapLayers = map.getLayers(); - const auto mapSize = map.getTileCount(); - const auto mapTileSize = map.getTileSize(); - std::vector texturePaths = {}; - for (auto tileSet : tileSets) { + for (auto tileSet : map.getTilesets()) { texturePaths.emplace_back(tileSet.getImagePath()); } - for (auto& layer : mapLayers) { + this->mapData = { + &map.getTilesets(), + &map.getLayers(), + &map.getTileCount(), + &map.getTileSize(), + &texturePaths + }; + + + for (auto& layer : *this->mapData.mapLayers) { if (layer->getType() == tmx::Layer::Type::Tile) { - auto& tileLayer = layer->getLayerAs(); - - const std::vector& properties = layer->getProperties(); - int zIndex = getLayerProperty(properties, "zIndex").value_or(0); - bool collision = getLayerProperty(properties, "collision").value_or(false); - - printf("z-index: %d, collision: %d\n", zIndex, collision); - - const auto& tiles = tileLayer.getTiles(); - - for (auto i = 0u; i < tileSets.size(); i++) { - auto tilesetTexture = VEGO_Game().textureManager->loadTexture(texturePaths.at(i).c_str()); - tmx::Vector2i textureSize; - SDL_QueryTexture(tilesetTexture, nullptr, nullptr, &(textureSize.x), &(textureSize.y)); - - const auto tileCountX = textureSize.x / mapTileSize.x; - const auto tileCountY = textureSize.y / mapTileSize.y; - - for (auto idx = 0ul; idx < mapSize.x * mapSize.y; idx++) { - - if (idx >= tiles.size() || tiles[idx].ID < tileSets.at(i).getFirstGID() - || tiles[idx].ID >= (tileSets.at(i).getFirstGID() + tileSets.at(i).getTileCount())) { - continue; - } - - const auto x = idx % mapSize.x; - const auto y = idx / mapSize.x; - - auto idIndex = (tiles[idx].ID - tileSets.at(i).getFirstGID()); - - int u = idIndex % tileCountX; - int v = 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 /= textureSize.x; - v /= textureSize.y; - - //vert pos - const float tilePosX = static_cast(x) * mapTileSize.x; - const float tilePosY = (static_cast(y) * mapTileSize.y); - - Map::addTile(tilePosX, tilePosY, mapTileSize, u, v, zIndex, texturePaths.at(i).c_str(), collision); - } - } - if (layer->getType() == tmx::Layer::Type::Object) { - // spawn objects - continue; - } + loadTileLayer(layer->getLayerAs()); + continue; + } + if (layer->getType() == tmx::Layer::Type::Object) { + // spawn objects + continue; } } } +void Map::loadTileLayer(const tmx::TileLayer& layer) +{ + const std::vector& properties = layer.getProperties(); + int zIndex = getLayerProperty(properties, "zIndex").value_or(0); + bool collision = getLayerProperty(properties, "collision").value_or(false); + + const auto& tiles = layer.getTiles(); + + auto tileConstructorRange = std::views::iota(0) + | std::views::take(this->mapData.tileSets->size()) + | std::views::transform([&](uint16_t i) { + const char* texturePath = this->mapData.texturePaths->at(i).c_str(); + + tmx::Vector2i textureSize; + SDL_QueryTexture( + VEGO_Game().textureManager->loadTexture(texturePath), + nullptr, + nullptr, + &(textureSize.x), + &(textureSize.y) + ); + + tmx::Vector2u tileCount2D = { textureSize.x / this->mapData.mapTileSize->x, textureSize.y / this->mapData.mapTileSize->y }; + + uint32_t tileCount = this->mapData.tileSets->at(i).getTileCount(); + uint32_t firstGID = this->mapData.tileSets->at(i).getFirstGID(); + + return TileSetData { texturePath, textureSize, tileCount, tileCount2D, firstGID }; + }) + | std::views::transform([=, this](const TileSetData& data) { + return std::views::iota(0) + | std::views::take(this->mapData.mapSize->x * this->mapData.mapSize->y) + | std::views::filter([=](uint16_t idx) { + return + idx < tiles.size() + && tiles[idx].ID >= data.firstGID + && tiles[idx].ID < (data.firstGID + data.tileCount); + }) + | std::views::transform([=, this](uint16_t idx) { + const auto x = idx % this->mapData.mapSize->x; + const auto y = idx / this->mapData.mapSize->x; + + const auto idIndex = (tiles[idx].ID - data.firstGID); + + uint32_t u = idIndex % data.tileCount2D.x; + uint32_t v = idIndex / data.tileCount2D.y; + u *= this->mapData.mapTileSize->x; // TODO: we should be using the tile set size, as this may be different from the map's grid size + v *= this->mapData.mapTileSize->y; + + // normalise the UV + u /= data.textureSize.x; + v /= data.textureSize.y; + + // vert pos + const float tilePosX = static_cast(x) * this->mapData.mapTileSize->x; + const float tilePosY = (static_cast(y) * this->mapData.mapTileSize->y); + + return std::function( + [tilePosX, tilePosY, capture0 = *this->mapData.mapTileSize, u, v, zIndex, capture1 = data.texturePath, collision] { + Map::addTile(tilePosX, tilePosY, capture0, u, v, zIndex, capture1, collision); + } + ); + }); + }) + | std::views::join + | std::ranges::to(); + + this->tileConstructors.insert(this->tileConstructors.end(), tileConstructorRange.begin(), tileConstructorRange.end()); +} + void Map::addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath, bool hasCollision) { auto& tile(VEGO_Game().manager.addEntity()); tile.addComponent(x, y, mapTileSize.x, mapTileSize.y, 1); - tile.addComponent(texturePath, v, u, zIndex); // why does uv need to be reversed? + tile.addComponent("assets/grassy-river-tiles.png" /*texturePath*/, v, u, zIndex); // why does uv need to be reversed? if (hasCollision) { tile.addComponent("hello I am a collider of a tile!"); tile.addGroup((size_t)Entity::GroupLabel::MAPTILES); } +} + +void Map::generateTiles() +{ + std::ranges::for_each(this->tileConstructors, [](auto& function) { + function(); + }); } \ No newline at end of file From 70260c01bbaf70755ecffeb7c7f9b55190056367 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 17 Nov 2024 12:39:14 +0100 Subject: [PATCH 3/4] structural improvements & code comments --- include/Map.h | 72 ++++++++++++++++++++++++++++++++------------------- src/Map.cpp | 42 +++++++----------------------- 2 files changed, 55 insertions(+), 59 deletions(-) diff --git a/include/Map.h b/include/Map.h index ed9af33..3a6019a 100644 --- a/include/Map.h +++ b/include/Map.h @@ -1,50 +1,44 @@ #pragma once -#include "tmxlite/Map.hpp" -#include "tmxlite/TileLayer.hpp" #include -#include #include -#include -#include #include #include +#include +#include +#include +#include + class GameInternal; class Map { public: - Map(const char* path); - - //[[deprecated("ID based text files are not supported anymore, use .tmx maps instead")]] - //static void loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map>* textureDict /* backreference */); - //[[deprecated]] - //static void addTile(unsigned long id, int x, int y, GameInternal* game, const std::map>* textureDict); - /*! * \brief Loads a .tmx map + * \details Loads a `.tmx` file and extracts all relevant data. Any entities (including tiles) are only spawned once * \param path Path to the `.tmx` map file - * + * \sa Map::generateTiles() */ - - void generateTiles(); + Map(const char* path); + void generateTiles(); //!< Generates the map based on the loaded definition private: - // required for initialisation + // struct required for initialisation struct MapData { - const std::vector* tileSets; - const std::vector* mapLayers; - const tmx::Vector2u* mapSize; - const tmx::Vector2u* mapTileSize; - const std::vector* texturePaths; + const std::vector* tileSets; + const std::vector* mapLayers; + const tmx::Vector2u* mapSize; + const tmx::Vector2u* mapTileSize; + const std::vector* texturePaths; }; struct TileSetData { - const char* texturePath{}; - tmx::Vector2i textureSize; - uint32_t tileCount{}; - tmx::Vector2u tileCount2D; - uint32_t firstGID{}; - }; + const char* texturePath{}; + tmx::Vector2i textureSize; + uint32_t tileCount{}; + tmx::Vector2u tileCount2D; + uint32_t firstGID{}; + }; tmx::Map map; Map::MapData mapData; @@ -55,4 +49,28 @@ private: template static std::optional getLayerProperty(const std::vector& properties, std::string propertyName) { return std::nullopt; }; + template<> std::optional getLayerProperty(const std::vector& properties, std::string propertyName) { + auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; + }); + + if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Boolean) { + return zIndexIterator->getBoolValue(); + } + + return std::nullopt; + } + + template<> std::optional getLayerProperty(const std::vector& properties, std::string propertyName) + { + auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; + }); + + if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Int) { + return zIndexIterator->getIntValue(); + } + + return std::nullopt; + } }; \ No newline at end of file diff --git a/src/Map.cpp b/src/Map.cpp index 975b83b..e75db70 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -5,13 +5,8 @@ #include #include #include -#include -#include #include #include -#include -#include -#include #include #include @@ -22,39 +17,14 @@ #include #include #include +#include #include "ColliderComponent.h" -#include "Constants.h" #include "GameInternal.h" #include "SpriteComponent.h" #include "TextureManager.h" #include "TileComponent.h" #include "VEGO.h" -#include "tmxlite/Types.hpp" - -template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) { -auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { - return property.getName().compare(propertyName) == 0; -}); - -if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Boolean) { - return zIndexIterator->getBoolValue(); -} - -return std::nullopt; -} - -template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) { -auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { - return property.getName().compare(propertyName) == 0; -}); - -if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Int) { - return zIndexIterator->getIntValue(); -} - -return std::nullopt; -} Map::Map(const char* path) { @@ -65,7 +35,7 @@ Map::Map(const char* path) std::vector texturePaths = {}; - for (auto tileSet : map.getTilesets()) { + for (const auto& tileSet : map.getTilesets()) { texturePaths.emplace_back(tileSet.getImagePath()); } @@ -99,8 +69,10 @@ void Map::loadTileLayer(const tmx::TileLayer& layer) const auto& tiles = layer.getTiles(); + // for each tile set auto tileConstructorRange = std::views::iota(0) | std::views::take(this->mapData.tileSets->size()) + // return the tile set metadata | std::views::transform([&](uint16_t i) { const char* texturePath = this->mapData.texturePaths->at(i).c_str(); @@ -121,14 +93,17 @@ void Map::loadTileLayer(const tmx::TileLayer& layer) return TileSetData { texturePath, textureSize, tileCount, tileCount2D, firstGID }; }) | std::views::transform([=, this](const TileSetData& data) { + // for each tile on the tile set return std::views::iota(0) | std::views::take(this->mapData.mapSize->x * this->mapData.mapSize->y) + // only take tiles that are on the ID range of the tile set | std::views::filter([=](uint16_t idx) { return idx < tiles.size() && tiles[idx].ID >= data.firstGID && tiles[idx].ID < (data.firstGID + data.tileCount); }) + // extract tile data | std::views::transform([=, this](uint16_t idx) { const auto x = idx % this->mapData.mapSize->x; const auto y = idx / this->mapData.mapSize->x; @@ -148,6 +123,7 @@ void Map::loadTileLayer(const tmx::TileLayer& layer) const float tilePosX = static_cast(x) * this->mapData.mapTileSize->x; const float tilePosY = (static_cast(y) * this->mapData.mapTileSize->y); + // return tile data as a function to spawn said tile return std::function( [tilePosX, tilePosY, capture0 = *this->mapData.mapTileSize, u, v, zIndex, capture1 = data.texturePath, collision] { Map::addTile(tilePosX, tilePosY, capture0, u, v, zIndex, capture1, collision); @@ -155,6 +131,7 @@ void Map::loadTileLayer(const tmx::TileLayer& layer) ); }); }) + // 2D view to 1D vector; might be better keep as view with scene management | std::views::join | std::ranges::to(); @@ -169,6 +146,7 @@ void Map::addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int tile.addComponent("assets/grassy-river-tiles.png" /*texturePath*/, v, u, zIndex); // why does uv need to be reversed? if (hasCollision) { + // tag currently does not have a clear purposes, TODO: figure out appropriate tag name tile.addComponent("hello I am a collider of a tile!"); tile.addGroup((size_t)Entity::GroupLabel::MAPTILES); } From 92dfbacd9be1730929bedf5d50a4e42a6b6715e7 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 17 Nov 2024 13:07:33 +0100 Subject: [PATCH 4/4] Fixed templates and const char* for texture --- include/Map.h | 28 ++-------------------------- src/Map.cpp | 30 ++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/include/Map.h b/include/Map.h index 3a6019a..244322e 100644 --- a/include/Map.h +++ b/include/Map.h @@ -33,7 +33,7 @@ private: }; struct TileSetData { - const char* texturePath{}; + std::string texturePath{}; tmx::Vector2i textureSize; uint32_t tileCount{}; tmx::Vector2u tileCount2D; @@ -45,32 +45,8 @@ private: std::vector> tileConstructors; void loadTileLayer(const tmx::TileLayer& layer); - static void addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath, bool hasCollision); + static void addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, std::string texturePath, bool hasCollision); template static std::optional getLayerProperty(const std::vector& properties, std::string propertyName) { return std::nullopt; }; - template<> std::optional getLayerProperty(const std::vector& properties, std::string propertyName) { - auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { - return property.getName().compare(propertyName) == 0; - }); - - if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Boolean) { - return zIndexIterator->getBoolValue(); - } - - return std::nullopt; - } - - template<> std::optional getLayerProperty(const std::vector& properties, std::string propertyName) - { - auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { - return property.getName().compare(propertyName) == 0; - }); - - if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Int) { - return zIndexIterator->getIntValue(); - } - - return std::nullopt; - } }; \ No newline at end of file diff --git a/src/Map.cpp b/src/Map.cpp index e75db70..dab109b 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -26,6 +26,32 @@ #include "TileComponent.h" #include "VEGO.h" + +template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) { + auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; + }); + + if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Boolean) { + return zIndexIterator->getBoolValue(); + } + + return std::nullopt; +} + +template<> std::optional Map::getLayerProperty(const std::vector& properties, std::string propertyName) +{ + auto zIndexIterator = std::ranges::find_if(properties, [propertyName](const tmx::Property& property) { + return property.getName().compare(propertyName) == 0; + }); + + if (zIndexIterator != properties.end() && zIndexIterator->getType() == tmx::Property::Type::Int) { + return zIndexIterator->getIntValue(); + } + + return std::nullopt; +} + Map::Map(const char* path) { if (!this->map.load(path)) { @@ -138,12 +164,12 @@ void Map::loadTileLayer(const tmx::TileLayer& layer) this->tileConstructors.insert(this->tileConstructors.end(), tileConstructorRange.begin(), tileConstructorRange.end()); } -void Map::addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, const char* texturePath, bool hasCollision) +void Map::addTile(float x, float y, const tmx::Vector2u& mapTileSize, int u, int v, int zIndex, std::string texturePath, bool hasCollision) { auto& tile(VEGO_Game().manager.addEntity()); tile.addComponent(x, y, mapTileSize.x, mapTileSize.y, 1); - tile.addComponent("assets/grassy-river-tiles.png" /*texturePath*/, v, u, zIndex); // why does uv need to be reversed? + tile.addComponent(texturePath.c_str(), v, u, zIndex); // why does uv need to be reversed? if (hasCollision) { // tag currently does not have a clear purposes, TODO: figure out appropriate tag name