First approach of area generation
This commit is contained in:
parent
dad3a4e0f3
commit
762550fccf
@ -4,7 +4,12 @@
|
||||
|
||||
#include "MapGenerator.h"
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
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<TexturedModel> hexModel = AssetManager::getModel("hexModelNone");
|
||||
std::vector<EntityID> 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<TexturedModel> hexModel = AssetManager::getModel("hexModelNone");
|
||||
std::vector<EntityID> 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<TransformComponent>(worldPos, glm::vec3(0), 1.0f);
|
||||
const auto modelComponent = std::make_shared<ModelComponent>(hexModel, modelName);
|
||||
const auto tileHighlightComponent = std::make_shared<TileRenderComponent>(false);
|
||||
const auto tileGameplayComponent = std::make_shared<TileGameplayComponent>(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<MapEntityComponent>());
|
||||
}
|
||||
}
|
||||
|
||||
assignOwners(entityManager, 2);
|
||||
}
|
||||
|
||||
void MapGenerator::assignOwners(EntityManager &entityManager, int numPlayers) {
|
||||
Random random;
|
||||
|
||||
|
||||
std::vector<TileInfo> allTiles;
|
||||
for (EntityID id: entityManager.getAllEntities()) {
|
||||
if (auto tileComponent = entityManager.getComponent<TileGameplayComponent>(id)) {
|
||||
allTiles.push_back({tileComponent->q, tileComponent->r, id});
|
||||
}
|
||||
}
|
||||
int maxTilesPerPlayer = static_cast<int>(allTiles.size() / numPlayers * (1.f / numPlayers)); // z.B. 60% der Map
|
||||
std::unordered_set<EntityID> assigned;
|
||||
|
||||
//1 Seets pro Spieler
|
||||
std::vector<EntityID> seeds;
|
||||
for (int player = 0; player < numPlayers; ++player) {
|
||||
EntityID seed = allTiles[random.randomInt(0, static_cast<int>(allTiles.size()))].id;
|
||||
seeds.push_back(seed);
|
||||
entityManager.addComponent(seed, std::make_shared<OwnerComponent>(player-1));
|
||||
}
|
||||
|
||||
// 2. Expansion
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for (PlayerID player = 0; player < static_cast<uint32_t>(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<OwnerComponent>(tile.id);
|
||||
if (owner && owner->playerID == player) {
|
||||
++ownedCount;
|
||||
}
|
||||
}
|
||||
|
||||
const auto transformComponent = std::make_shared<TransformComponent>(worldPos, glm::vec3(0), 1.0f);
|
||||
const auto modelComponent = std::make_shared<ModelComponent>(hexModel, modelName);
|
||||
const auto tileHighlightComponent = std::make_shared<TileRenderComponent>(false);
|
||||
const auto tileGameplayComponent = std::make_shared<TileGameplayComponent>(q, r, radius, resourceType);
|
||||
tileGameplayComponent->entitiesOnTile = tileEntities;
|
||||
std::vector<EntityID> borderTiles;
|
||||
for (TileInfo& tile : allTiles) {
|
||||
auto owner = entityManager.getComponent<OwnerComponent>(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<MapEntityComponent>());
|
||||
//Todo replace with area system
|
||||
entityManager.addComponent(entityID, std::make_shared<OwnerComponent>(random.randomInt(0,4)));
|
||||
for (TileInfo& neighbor : allTiles) {
|
||||
auto neighborOwner = entityManager.getComponent<OwnerComponent>(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<int>(borderTiles.size()-1))];
|
||||
entityManager.addComponent(newTile, std::make_shared<OwnerComponent>(player));
|
||||
assigned.insert(newTile);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool MapGenerator::areHexNeighbors(int q1, int r1, int q2, int r2) {
|
||||
// Hex axial neighbor differences
|
||||
static const std::vector<std::pair<int,int>> 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;
|
||||
}
|
||||
@ -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<MapArea> 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:
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user