First approach of area generation
This commit is contained in:
parent
dad3a4e0f3
commit
762550fccf
@ -4,7 +4,12 @@
|
|||||||
|
|
||||||
#include "MapGenerator.h"
|
#include "MapGenerator.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
struct TileInfo {
|
||||||
|
int q, r;
|
||||||
|
EntityID id;
|
||||||
|
};
|
||||||
|
|
||||||
float MapGenerator::hexRadius = 10.0f;
|
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) {
|
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 xOffset = hexRadius * std::sqrt(3.0f);
|
||||||
float zOffset = hexRadius * 1.5f;
|
float zOffset = hexRadius * 1.5f;
|
||||||
|
|
||||||
for (int r = 0; r < height; ++r) {
|
for (int r = 0; r < height; ++r) {
|
||||||
for (int q = 0; q < width; ++q) {
|
for (int q = 0; q < width; ++q) {
|
||||||
// Pointy-top Hexes
|
// Pointy-top Hexes
|
||||||
float x = xOffset * (q + 0.5f * (r % 2));
|
float x = xOffset * (q + 0.5f * (r % 2));
|
||||||
float z = zOffset * r;
|
float z = zOffset * r;
|
||||||
glm::vec3 worldPos = glm::vec3(x, 0.0f, z);
|
glm::vec3 worldPos = glm::vec3(x, 0.0f, z);
|
||||||
float radius = hexRadius;
|
float radius = hexRadius;
|
||||||
EntityID entityID = entityManager.createEntity();
|
EntityID entityID = entityManager.createEntity();
|
||||||
float randomValue = random.randomFloat(0.0f, 1.0f);
|
float randomValue = random.randomFloat(0.0f, 1.0f);
|
||||||
RessourceType resourceType = RessourceType::NONE;
|
RessourceType resourceType = RessourceType::NONE;
|
||||||
std::shared_ptr<TexturedModel> hexModel = AssetManager::getModel("hexModelNone");
|
std::shared_ptr<TexturedModel> hexModel = AssetManager::getModel("hexModelNone");
|
||||||
std::vector<EntityID> tileEntities;
|
std::vector<EntityID> tileEntities;
|
||||||
std::string modelName = "hexModelNone";
|
std::string modelName = "hexModelNone";
|
||||||
if (randomValue < 0.5f) {
|
if (randomValue < 0.5f) {
|
||||||
resourceType = RessourceType::WOOD;
|
resourceType = RessourceType::WOOD;
|
||||||
ForestTileGenerator forestTileGenerator;
|
ForestTileGenerator forestTileGenerator;
|
||||||
tileEntities = forestTileGenerator.generateHexTile(entityManager, random, worldPos);
|
tileEntities = forestTileGenerator.generateHexTile(entityManager, random, worldPos);
|
||||||
hexModel = AssetManager::getModel("hexModelWood");
|
hexModel = AssetManager::getModel("hexModelWood");
|
||||||
modelName = "hexModelWood";
|
modelName = "hexModelWood";
|
||||||
} else if (randomValue < 0.75f) {
|
} else if (randomValue < 0.75f) {
|
||||||
resourceType = RessourceType::STONE;
|
resourceType = RessourceType::STONE;
|
||||||
hexModel = AssetManager::getModel("hexModelStone");
|
hexModel = AssetManager::getModel("hexModelStone");
|
||||||
modelName = "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);
|
std::vector<EntityID> borderTiles;
|
||||||
const auto modelComponent = std::make_shared<ModelComponent>(hexModel, modelName);
|
for (TileInfo& tile : allTiles) {
|
||||||
const auto tileHighlightComponent = std::make_shared<TileRenderComponent>(false);
|
auto owner = entityManager.getComponent<OwnerComponent>(tile.id);
|
||||||
const auto tileGameplayComponent = std::make_shared<TileGameplayComponent>(q, r, radius, resourceType);
|
if (!owner || owner->playerID != player) continue;
|
||||||
tileGameplayComponent->entitiesOnTile = tileEntities;
|
|
||||||
|
|
||||||
entityManager.addComponent(entityID, transformComponent);
|
for (TileInfo& neighbor : allTiles) {
|
||||||
entityManager.addComponent(entityID, modelComponent);
|
auto neighborOwner = entityManager.getComponent<OwnerComponent>(neighbor.id);
|
||||||
entityManager.addComponent(entityID, tileHighlightComponent);
|
if (neighborOwner || assigned.count(neighbor.id)) continue;
|
||||||
entityManager.addComponent(entityID, tileGameplayComponent);
|
if (areHexNeighbors(tile.q, tile.r, neighbor.q, neighbor.r)) {
|
||||||
entityManager.addComponent(entityID, std::make_shared<MapEntityComponent>());
|
borderTiles.push_back(neighbor.id);
|
||||||
//Todo replace with area system
|
}
|
||||||
entityManager.addComponent(entityID, std::make_shared<OwnerComponent>(random.randomInt(0,4)));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 init(Loader& loader, float hexRadius);
|
||||||
static void generateHexMap(Map& map, int width, int height, EntityManager& entityManager);
|
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:
|
private:
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user