diff --git a/src/game/hexWorld/MapGenerator.cpp b/src/game/hexWorld/MapGenerator.cpp index 7867a94..03a2d60 100644 --- a/src/game/hexWorld/MapGenerator.cpp +++ b/src/game/hexWorld/MapGenerator.cpp @@ -4,7 +4,12 @@ #include "MapGenerator.h" +#include #include +struct TileInfo { + int q, r; + EntityID id; +}; float MapGenerator::hexRadius = 10.0f; @@ -20,51 +25,130 @@ void MapGenerator::init(Loader &loader, float hexRadius) { } void MapGenerator::generateHexMap(Map &map, int width, int height, EntityManager &entityManager) { - Random random; + Random random; - map.clear(entityManager); + map.clear(entityManager); - float xOffset = hexRadius * std::sqrt(3.0f); - float zOffset = hexRadius * 1.5f; + float xOffset = hexRadius * std::sqrt(3.0f); + float zOffset = hexRadius * 1.5f; - for (int r = 0; r < height; ++r) { - for (int q = 0; q < width; ++q) { - // Pointy-top Hexes - float x = xOffset * (q + 0.5f * (r % 2)); - float z = zOffset * r; - glm::vec3 worldPos = glm::vec3(x, 0.0f, z); - float radius = hexRadius; - EntityID entityID = entityManager.createEntity(); - float randomValue = random.randomFloat(0.0f, 1.0f); - RessourceType resourceType = RessourceType::NONE; - std::shared_ptr hexModel = AssetManager::getModel("hexModelNone"); - std::vector tileEntities; - std::string modelName = "hexModelNone"; - if (randomValue < 0.5f) { - resourceType = RessourceType::WOOD; - ForestTileGenerator forestTileGenerator; - tileEntities = forestTileGenerator.generateHexTile(entityManager, random, worldPos); - hexModel = AssetManager::getModel("hexModelWood"); - modelName = "hexModelWood"; - } else if (randomValue < 0.75f) { - resourceType = RessourceType::STONE; - hexModel = AssetManager::getModel("hexModelStone"); - modelName = "hexModelStone"; + for (int r = 0; r < height; ++r) { + for (int q = 0; q < width; ++q) { + // Pointy-top Hexes + float x = xOffset * (q + 0.5f * (r % 2)); + float z = zOffset * r; + glm::vec3 worldPos = glm::vec3(x, 0.0f, z); + float radius = hexRadius; + EntityID entityID = entityManager.createEntity(); + float randomValue = random.randomFloat(0.0f, 1.0f); + RessourceType resourceType = RessourceType::NONE; + std::shared_ptr hexModel = AssetManager::getModel("hexModelNone"); + std::vector tileEntities; + std::string modelName = "hexModelNone"; + if (randomValue < 0.5f) { + resourceType = RessourceType::WOOD; + ForestTileGenerator forestTileGenerator; + tileEntities = forestTileGenerator.generateHexTile(entityManager, random, worldPos); + hexModel = AssetManager::getModel("hexModelWood"); + modelName = "hexModelWood"; + } else if (randomValue < 0.75f) { + resourceType = RessourceType::STONE; + hexModel = AssetManager::getModel("hexModelStone"); + modelName = "hexModelStone"; + } + + const auto transformComponent = std::make_shared(worldPos, glm::vec3(0), 1.0f); + const auto modelComponent = std::make_shared(hexModel, modelName); + const auto tileHighlightComponent = std::make_shared(false); + const auto tileGameplayComponent = std::make_shared(q, r, radius, resourceType); + tileGameplayComponent->entitiesOnTile = tileEntities; + + entityManager.addComponent(entityID, transformComponent); + entityManager.addComponent(entityID, modelComponent); + entityManager.addComponent(entityID, tileHighlightComponent); + entityManager.addComponent(entityID, tileGameplayComponent); + entityManager.addComponent(entityID, std::make_shared()); + } + } + + assignOwners(entityManager, 2); +} + +void MapGenerator::assignOwners(EntityManager &entityManager, int numPlayers) { + Random random; + + + std::vector allTiles; + for (EntityID id: entityManager.getAllEntities()) { + if (auto tileComponent = entityManager.getComponent(id)) { + allTiles.push_back({tileComponent->q, tileComponent->r, id}); + } + } + int maxTilesPerPlayer = static_cast(allTiles.size() / numPlayers * (1.f / numPlayers)); // z.B. 60% der Map + std::unordered_set assigned; + + //1 Seets pro Spieler + std::vector seeds; + for (int player = 0; player < numPlayers; ++player) { + EntityID seed = allTiles[random.randomInt(0, static_cast(allTiles.size()))].id; + seeds.push_back(seed); + entityManager.addComponent(seed, std::make_shared(player-1)); + } + + // 2. Expansion + bool changed = true; + while (changed) { + changed = false; + for (PlayerID player = 0; player < static_cast(numPlayers); ++player) { + + + // Finde alle Tiles des Spielers + int ownedCount = 0; + for (TileInfo& tile : allTiles) { + if (assigned.count(tile.id) == 0) continue; + auto owner = entityManager.getComponent(tile.id); + if (owner && owner->playerID == player) { + ++ownedCount; } + } - const auto transformComponent = std::make_shared(worldPos, glm::vec3(0), 1.0f); - const auto modelComponent = std::make_shared(hexModel, modelName); - const auto tileHighlightComponent = std::make_shared(false); - const auto tileGameplayComponent = std::make_shared(q, r, radius, resourceType); - tileGameplayComponent->entitiesOnTile = tileEntities; + std::vector borderTiles; + for (TileInfo& tile : allTiles) { + auto owner = entityManager.getComponent(tile.id); + if (!owner || owner->playerID != player) continue; - entityManager.addComponent(entityID, transformComponent); - entityManager.addComponent(entityID, modelComponent); - entityManager.addComponent(entityID, tileHighlightComponent); - entityManager.addComponent(entityID, tileGameplayComponent); - entityManager.addComponent(entityID, std::make_shared()); - //Todo replace with area system - entityManager.addComponent(entityID, std::make_shared(random.randomInt(0,4))); + for (TileInfo& neighbor : allTiles) { + auto neighborOwner = entityManager.getComponent(neighbor.id); + if (neighborOwner || assigned.count(neighbor.id)) continue; + if (areHexNeighbors(tile.q, tile.r, neighbor.q, neighbor.r)) { + borderTiles.push_back(neighbor.id); + } + } + } + + if (ownedCount >= maxTilesPerPlayer) continue; + + // Zufällige Auswahl eines Nachbarn zum expandieren + if (!borderTiles.empty()) { + EntityID newTile = borderTiles[random.randomInt(0, static_cast(borderTiles.size()-1))]; + entityManager.addComponent(newTile, std::make_shared(player)); + assigned.insert(newTile); + changed = true; } } -} \ No newline at end of file + } + +} + +bool MapGenerator::areHexNeighbors(int q1, int r1, int q2, int r2) { + // Hex axial neighbor differences + static const std::vector> directions = { + {+1, 0}, {+1, -1}, {0, -1}, + {-1, 0}, {-1, +1}, {0, +1} + }; + + for (auto [dq, dr] : directions) { + if (q1 + dq == q2 && r1 + dr == r2) return true; + } + return false; +} diff --git a/src/game/hexWorld/MapGenerator.h b/src/game/hexWorld/MapGenerator.h index 25018bb..a718d89 100644 --- a/src/game/hexWorld/MapGenerator.h +++ b/src/game/hexWorld/MapGenerator.h @@ -30,7 +30,9 @@ public: static void init(Loader& loader, float hexRadius); static void generateHexMap(Map& map, int width, int height, EntityManager& entityManager); - std::vector generateAreas(const EntityManager &em); + static void assignOwners(EntityManager &entityManager, int numPlayers); + + static bool areHexNeighbors(int tile_q, int tile_r, int neighbor_q, int neighbor_r); private: