UPD: Introduce ECS System
This commit is contained in:
parent
fffc799447
commit
fe376e9c0f
@ -58,7 +58,6 @@ add_executable(Dicewars_Siedler src/main.cpp
|
|||||||
src/engine/layer/entities/Light.h
|
src/engine/layer/entities/Light.h
|
||||||
src/engine/platform/glfw/MousePicker.cpp
|
src/engine/platform/glfw/MousePicker.cpp
|
||||||
src/engine/platform/glfw/MousePicker.h
|
src/engine/platform/glfw/MousePicker.h
|
||||||
src/game/hexWorld/HexTile.h
|
|
||||||
src/game/hexWorld/Map.cpp
|
src/game/hexWorld/Map.cpp
|
||||||
src/game/hexWorld/Map.h
|
src/game/hexWorld/Map.h
|
||||||
src/game/hexWorld/MapGenerator.cpp
|
src/game/hexWorld/MapGenerator.cpp
|
||||||
@ -79,8 +78,25 @@ add_executable(Dicewars_Siedler src/main.cpp
|
|||||||
src/game/hexWorld/tileGenerator/ForestTileGenerator.h
|
src/game/hexWorld/tileGenerator/ForestTileGenerator.h
|
||||||
src/engine/toolbox/Random.cpp
|
src/engine/toolbox/Random.cpp
|
||||||
src/engine/toolbox/Random.h
|
src/engine/toolbox/Random.h
|
||||||
src/game/TileInteractionSystem.cpp
|
src/engine/core/ECS/Component.cpp
|
||||||
src/game/TileInteractionSystem.h
|
src/engine/core/ECS/Component.h
|
||||||
|
src/engine/core/ECS/TransformComponent.cpp
|
||||||
|
src/engine/core/ECS/TransformComponent.h
|
||||||
|
src/engine/core/ECS/ModelComponent.cpp
|
||||||
|
src/engine/core/ECS/ModelComponent.h
|
||||||
|
src/engine/core/ECS/EntityManager.cpp
|
||||||
|
src/engine/core/ECS/EntityManager.h
|
||||||
|
src/engine/core/ECS/RenderSystem.cpp
|
||||||
|
src/engine/core/ECS/RenderSystem.h
|
||||||
|
src/engine/core/ECS/TileRenderComponent.cpp
|
||||||
|
src/engine/core/ECS/TileRenderComponent.h
|
||||||
|
src/game/hexWorld/ecs/components/TileGameplayComponent.cpp
|
||||||
|
src/game/hexWorld/ecs/components/TileGameplayComponent.h
|
||||||
|
src/game/hexWorld/ecs/components/MapEntityComponent.h
|
||||||
|
src/engine/renderer/components/TerrainRenderingData.h
|
||||||
|
src/game/hexWorld/RessourceType.h
|
||||||
|
src/game/hexWorld/ecs/systems/TileHighlightSystem.cpp
|
||||||
|
src/game/hexWorld/ecs/systems/TileHighlightSystem.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(Dicewars_Siedler PRIVATE
|
target_include_directories(Dicewars_Siedler PRIVATE
|
||||||
|
|||||||
5
src/engine/core/ECS/Component.cpp
Normal file
5
src/engine/core/ECS/Component.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Component.h"
|
||||||
16
src/engine/core/ECS/Component.h
Normal file
16
src/engine/core/ECS/Component.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COMPONENT_H
|
||||||
|
#define COMPONENT_H
|
||||||
|
#include "glm/vec3.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class Component {
|
||||||
|
public:
|
||||||
|
virtual ~Component() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COMPONENT_H
|
||||||
17
src/engine/core/ECS/EntityManager.cpp
Normal file
17
src/engine/core/ECS/EntityManager.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "EntityManager.h"
|
||||||
|
#include <algorithm>
|
||||||
|
EntityID EntityManager::createEntity() {
|
||||||
|
const EntityID id = nextID++;
|
||||||
|
entities.push_back(id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityManager::destroyEntity(EntityID entity) {
|
||||||
|
entities.erase(std::remove(entities.begin(), entities.end(), entity), entities.end());
|
||||||
|
transforms.erase(entity);
|
||||||
|
models.erase(entity);
|
||||||
|
}
|
||||||
80
src/engine/core/ECS/EntityManager.h
Normal file
80
src/engine/core/ECS/EntityManager.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ENTITYMANAGER_H
|
||||||
|
#define ENTITYMANAGER_H
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Forward Declarations (KEINE includes hier!)
|
||||||
|
class TransformComponent;
|
||||||
|
class ModelComponent;
|
||||||
|
class TileRenderComponent;
|
||||||
|
class TileGameplayComponent;
|
||||||
|
class MapEntityComponent;
|
||||||
|
|
||||||
|
using EntityID = std::uint32_t;
|
||||||
|
|
||||||
|
class EntityManager {
|
||||||
|
private:
|
||||||
|
EntityID nextID = 1;
|
||||||
|
std::vector<EntityID> entities;
|
||||||
|
|
||||||
|
std::unordered_map<EntityID, std::shared_ptr<TransformComponent>> transforms;
|
||||||
|
std::unordered_map<EntityID, std::shared_ptr<ModelComponent>> models;
|
||||||
|
std::unordered_map<EntityID, std::shared_ptr<TileRenderComponent>> tileRenderComponents;
|
||||||
|
std::unordered_map<EntityID, std::shared_ptr<TileGameplayComponent>> tileGameplayComponents;
|
||||||
|
std::unordered_map<EntityID, std::shared_ptr<MapEntityComponent>> mapEntityComponents;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EntityID createEntity();
|
||||||
|
void destroyEntity(EntityID entity);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void addComponent(EntityID entity, std::shared_ptr<T> component) {
|
||||||
|
if constexpr (std::is_same_v<T, TransformComponent>) {
|
||||||
|
transforms[entity] = component;
|
||||||
|
} else if constexpr (std::is_same_v<T, ModelComponent>) {
|
||||||
|
models[entity] = component;
|
||||||
|
} else if constexpr (std::is_same_v<T, TileRenderComponent>) {
|
||||||
|
tileRenderComponents[entity] = component;
|
||||||
|
} else if constexpr (std::is_same_v<T, TileGameplayComponent>) {
|
||||||
|
tileGameplayComponents[entity] = component;
|
||||||
|
} else if constexpr (std::is_same_v<T, MapEntityComponent>) {
|
||||||
|
mapEntityComponents[entity] = component;
|
||||||
|
} else {
|
||||||
|
static_assert(sizeof(T) == 0, "Component-Typ nicht unterstützt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::shared_ptr<T> getComponent(EntityID entity) {
|
||||||
|
if constexpr (std::is_same_v<T, TransformComponent>) {
|
||||||
|
auto it = transforms.find(entity);
|
||||||
|
return (it != transforms.end()) ? it->second : nullptr;
|
||||||
|
} else if constexpr (std::is_same_v<T, ModelComponent>) {
|
||||||
|
auto it = models.find(entity);
|
||||||
|
return (it != models.end()) ? it->second : nullptr;
|
||||||
|
} else if constexpr (std::is_same_v<T, TileRenderComponent>) {
|
||||||
|
auto it = tileRenderComponents.find(entity);
|
||||||
|
return (it != tileRenderComponents.end()) ? it->second : nullptr;
|
||||||
|
} else if constexpr (std::is_same_v<T, TileGameplayComponent>) {
|
||||||
|
auto it = tileGameplayComponents.find(entity);
|
||||||
|
return (it != tileGameplayComponents.end()) ? it->second : nullptr;
|
||||||
|
} else if constexpr (std::is_same_v<T, MapEntityComponent>) {
|
||||||
|
auto it = mapEntityComponents.find(entity);
|
||||||
|
return (it != mapEntityComponents.end()) ? it->second : nullptr;
|
||||||
|
} else {
|
||||||
|
static_assert(sizeof(T) == 0, "Component-Typ nicht unterstützt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<EntityID>& getAllEntities() const { return entities; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ENTITYMANAGER_H
|
||||||
5
src/engine/core/ECS/ModelComponent.cpp
Normal file
5
src/engine/core/ECS/ModelComponent.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ModelComponent.h"
|
||||||
21
src/engine/core/ECS/ModelComponent.h
Normal file
21
src/engine/core/ECS/ModelComponent.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MODELCOMPONENT_H
|
||||||
|
#define MODELCOMPONENT_H
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Component.h"
|
||||||
|
#include "../../renderer/model/TexturedModel.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ModelComponent: public Component {
|
||||||
|
public:
|
||||||
|
std::shared_ptr<TexturedModel> model;
|
||||||
|
ModelComponent(std::shared_ptr<TexturedModel> model) : model(std::move(model)) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MODELCOMPONENT_H
|
||||||
24
src/engine/core/ECS/RenderSystem.cpp
Normal file
24
src/engine/core/ECS/RenderSystem.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "RenderSystem.h"
|
||||||
|
|
||||||
|
void RenderSystem::render(EntityManager &entityManager, MasterRenderer &renderer) {
|
||||||
|
for (auto id : entityManager.getAllEntities()) {
|
||||||
|
|
||||||
|
auto transform = entityManager.getComponent<TransformComponent>(id);
|
||||||
|
auto model = entityManager.getComponent<ModelComponent>(id);
|
||||||
|
auto tileRenderingComponent = entityManager.getComponent<TileRenderComponent>(id);
|
||||||
|
|
||||||
|
if (!transform || !model) continue;
|
||||||
|
|
||||||
|
if (tileRenderingComponent) {
|
||||||
|
renderer.submitTerrainTile(transform, model, tileRenderingComponent);
|
||||||
|
} else {
|
||||||
|
Entity entity = Entity(model->model, transform->position, transform->rotation.x, transform->rotation.y, transform->rotation.z, transform->scale);
|
||||||
|
renderer.submitEntity(std::make_unique<Entity>(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/engine/core/ECS/RenderSystem.h
Normal file
18
src/engine/core/ECS/RenderSystem.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RENDERSYSTEM_H
|
||||||
|
#define RENDERSYSTEM_H
|
||||||
|
#include "EntityManager.h"
|
||||||
|
#include "../../renderer/MasterRenderer.h"
|
||||||
|
|
||||||
|
|
||||||
|
class RenderSystem {
|
||||||
|
public:
|
||||||
|
void render(EntityManager &entityManager, MasterRenderer &renderer);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //RENDERSYSTEM_H
|
||||||
5
src/engine/core/ECS/TileRenderComponent.cpp
Normal file
5
src/engine/core/ECS/TileRenderComponent.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TileRenderComponent.h"
|
||||||
22
src/engine/core/ECS/TileRenderComponent.h
Normal file
22
src/engine/core/ECS/TileRenderComponent.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TILERENDERCOMPONENT_H
|
||||||
|
#define TILERENDERCOMPONENT_H
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Component.h"
|
||||||
|
#include "../../renderer/model/TexturedModel.h"
|
||||||
|
|
||||||
|
|
||||||
|
class TileRenderComponent : public Component{
|
||||||
|
public:
|
||||||
|
bool isHighlighted;
|
||||||
|
explicit TileRenderComponent(bool isHighlighted) : isHighlighted(isHighlighted) {};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //TILERENDERCOMPONENT_H
|
||||||
5
src/engine/core/ECS/TransformComponent.cpp
Normal file
5
src/engine/core/ECS/TransformComponent.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TransformComponent.h"
|
||||||
20
src/engine/core/ECS/TransformComponent.h
Normal file
20
src/engine/core/ECS/TransformComponent.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TRANSFORMCOMPONENT_H
|
||||||
|
#define TRANSFORMCOMPONENT_H
|
||||||
|
#include "Component.h"
|
||||||
|
|
||||||
|
|
||||||
|
class TransformComponent : public Component {
|
||||||
|
public:
|
||||||
|
TransformComponent(glm::vec3 position, glm::vec3 rotation, float scale) : position(position), rotation(rotation), scale(scale) {};
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec3 rotation;
|
||||||
|
float scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //TRANSFORMCOMPONENT_H
|
||||||
@ -9,7 +9,6 @@
|
|||||||
#include "../../renderer/model/TexturedModel.h"
|
#include "../../renderer/model/TexturedModel.h"
|
||||||
#include "glm/vec3.hpp"
|
#include "glm/vec3.hpp"
|
||||||
|
|
||||||
|
|
||||||
class Entity {
|
class Entity {
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<TexturedModel> model;
|
std::shared_ptr<TexturedModel> model;
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "MasterRenderer.h"
|
#include "MasterRenderer.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "../core/Application.h"
|
#include "../core/Application.h"
|
||||||
#include "glm/ext/matrix_clip_space.hpp"
|
#include "glm/ext/matrix_clip_space.hpp"
|
||||||
|
|
||||||
@ -24,13 +26,14 @@ void MasterRenderer::render(const Light &light, const Camera &camera) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterRenderer::submitEntity(Entity *entity) {
|
void MasterRenderer::submitEntity(std::unique_ptr<Entity> entity) {
|
||||||
TexturedModel* entityModel = entity->getModel().get();
|
TexturedModel* entityModel = entity->getModel().get();
|
||||||
entities[entityModel].push_back(entity);
|
entities[entityModel].push_back(std::move(entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MasterRenderer::submitTerrainTile(HexRenderData *tile) {
|
void MasterRenderer::submitTerrainTile(std::shared_ptr<TransformComponent> transform, std::shared_ptr<ModelComponent> model, std::shared_ptr<TileRenderComponent> terrainTileComponent) {
|
||||||
terrainTiles[tile->model.get()].push_back(tile);
|
TerrainRenderingData terrain = TerrainRenderingData(std::move(transform), std::move(model), std::move(terrainTileComponent));
|
||||||
|
terrainTiles[terrain.modelComponent->model.get()].push_back(std::make_unique<TerrainRenderingData>(std::move(terrain)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "TerrainRenderer.h"
|
#include "TerrainRenderer.h"
|
||||||
#include "../../game/hexWorld/HexTile.h"
|
|
||||||
#include "../layer/entities/Entity.h"
|
#include "../layer/entities/Entity.h"
|
||||||
#include "model/TexturedModel.h"
|
#include "model/TexturedModel.h"
|
||||||
|
|
||||||
@ -19,8 +18,8 @@ class Light;
|
|||||||
|
|
||||||
class MasterRenderer {
|
class MasterRenderer {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<TexturedModel*, std::vector<Entity*>> entities;
|
std::unordered_map<TexturedModel*, std::vector<std::unique_ptr<Entity>>> entities;
|
||||||
std::unordered_map<TexturedModel*, std::vector<HexRenderData*>> terrainTiles;
|
std::unordered_map<TexturedModel*, std::vector<std::unique_ptr<TerrainRenderingData>>> terrainTiles;
|
||||||
glm::mat4 projectionMatrix;
|
glm::mat4 projectionMatrix;
|
||||||
std::unique_ptr<Renderer> entityRenderer;
|
std::unique_ptr<Renderer> entityRenderer;
|
||||||
std::unique_ptr<TerrainRenderer> terrainRenderer;
|
std::unique_ptr<TerrainRenderer> terrainRenderer;
|
||||||
@ -39,8 +38,8 @@ public:
|
|||||||
};
|
};
|
||||||
void render(const Light &light, const Camera &camera);
|
void render(const Light &light, const Camera &camera);
|
||||||
|
|
||||||
void submitEntity(Entity* entity);
|
void submitEntity(std::unique_ptr<Entity> entity);
|
||||||
void submitTerrainTile(HexRenderData* tile);
|
void submitTerrainTile(std::shared_ptr<TransformComponent> transform, std::shared_ptr<ModelComponent> model, std::shared_ptr<TileRenderComponent>);
|
||||||
|
|
||||||
[[nodiscard]] glm::mat4 getProjectionMatrix() const {return projectionMatrix;}
|
[[nodiscard]] glm::mat4 getProjectionMatrix() const {return projectionMatrix;}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
#include "../../game/hexWorld/HexTile.h"
|
|
||||||
#include "../core/Application.h"
|
#include "../core/Application.h"
|
||||||
#include "../layer/entities/Light.h"
|
#include "../layer/entities/Light.h"
|
||||||
#include "../toolbox/MathUtils.h"
|
#include "../toolbox/MathUtils.h"
|
||||||
@ -24,7 +23,8 @@ void Renderer::prepare(const Camera& camera, const Light& light) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Renderer::renderEntities(const std::unordered_map<TexturedModel *, std::vector<Entity *>>& entities) {
|
void Renderer::renderEntities(const std::unordered_map<TexturedModel *, std::vector<std::unique_ptr<Entity>>>& entities) {
|
||||||
|
|
||||||
for (const auto& [texturedModel, batch] : entities) {
|
for (const auto& [texturedModel, batch] : entities) {
|
||||||
prepareTexturedModel(*texturedModel);
|
prepareTexturedModel(*texturedModel);
|
||||||
for (const auto& entity : batch) {
|
for (const auto& entity : batch) {
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#ifndef DICEWARS_SIEDLER_RENDERER_H
|
#ifndef DICEWARS_SIEDLER_RENDERER_H
|
||||||
#define DICEWARS_SIEDLER_RENDERER_H
|
#define DICEWARS_SIEDLER_RENDERER_H
|
||||||
#include "../../game/hexWorld/HexTile.h"
|
|
||||||
#include "../layer/entities/Entity.h"
|
#include "../layer/entities/Entity.h"
|
||||||
#include "model/RawModel.h"
|
#include "model/RawModel.h"
|
||||||
#include "model/TexturedModel.h"
|
#include "model/TexturedModel.h"
|
||||||
@ -24,7 +23,7 @@ public:
|
|||||||
};
|
};
|
||||||
void prepare(const ::Camera &camera, const Light& light);
|
void prepare(const ::Camera &camera, const Light& light);
|
||||||
|
|
||||||
void renderEntities(const std::unordered_map<TexturedModel *, std::vector<Entity *>> &entities);
|
void renderEntities(const std::unordered_map<TexturedModel *, std::vector<std::unique_ptr<Entity>>> &entities);
|
||||||
void finalizeFrame();
|
void finalizeFrame();
|
||||||
private:
|
private:
|
||||||
StaticShader staticShader;
|
StaticShader staticShader;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ void TerrainRenderer::prepare(const Camera &camera, const Light &light) {
|
|||||||
terrainShader.loadViewMatrix(viewMatrix);
|
terrainShader.loadViewMatrix(viewMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainRenderer::renderTerrainTiles(const std::unordered_map<TexturedModel *, std::vector<HexRenderData *>> &terrainTiles) {
|
void TerrainRenderer::renderTerrainTiles(const std::unordered_map<TexturedModel *, std::vector<std::unique_ptr<TerrainRenderingData>>> &terrainTiles) {
|
||||||
for (const auto& [texturedModel, batch] : terrainTiles) {
|
for (const auto& [texturedModel, batch] : terrainTiles) {
|
||||||
prepareTexturedModel(*texturedModel);
|
prepareTexturedModel(*texturedModel);
|
||||||
for (const auto& hexTile : batch) {
|
for (const auto& hexTile : batch) {
|
||||||
@ -47,9 +47,9 @@ void TerrainRenderer::unbindTexturedModel() {
|
|||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainRenderer::prepareInstance(const HexRenderData &hexTile) {
|
void TerrainRenderer::prepareInstance(const TerrainRenderingData &hexTile) {
|
||||||
glm::mat4 transformationMatrix = MathUtils::createTransformationMatrix(hexTile.position, 0,0,0,1);
|
glm::mat4 transformationMatrix = MathUtils::createTransformationMatrix(hexTile.transform->position, 0,0,0,1);
|
||||||
terrainShader.loadTransformationMatrix(transformationMatrix);
|
terrainShader.loadTransformationMatrix(transformationMatrix);
|
||||||
|
|
||||||
terrainShader.loadIsHighlighted(hexTile.highlight);
|
terrainShader.loadIsHighlighted(hexTile.terrainRenderComponent->isHighlighted);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
#ifndef TERRAINRENDERER_H
|
#ifndef TERRAINRENDERER_H
|
||||||
#define TERRAINRENDERER_H
|
#define TERRAINRENDERER_H
|
||||||
#include "../../game/hexWorld/HexTile.h"
|
|
||||||
#include "model/TexturedModel.h"
|
#include "model/TexturedModel.h"
|
||||||
#include "shaders/StaticShader.h"
|
#include "shaders/StaticShader.h"
|
||||||
|
|
||||||
#include "../layer/entities/Camera.h"
|
#include "../layer/entities/Camera.h"
|
||||||
#include "../layer/entities/Light.h"
|
#include "../layer/entities/Light.h"
|
||||||
|
#include "components/TerrainRenderingData.h"
|
||||||
#include "shaders/TerrainShader.h"
|
#include "shaders/TerrainShader.h"
|
||||||
|
|
||||||
|
|
||||||
@ -22,14 +23,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void prepare(const Camera &camera, const Light &light);
|
void prepare(const Camera &camera, const Light &light);
|
||||||
void renderTerrainTiles(const std::unordered_map<TexturedModel*, std::vector<HexRenderData*>>& terrainTiles);
|
void renderTerrainTiles(const std::unordered_map<TexturedModel*, std::vector<std::unique_ptr<TerrainRenderingData>>>& terrainTiles);
|
||||||
void finalizeFrame();
|
void finalizeFrame();
|
||||||
private:
|
private:
|
||||||
TerrainShader terrainShader;
|
TerrainShader terrainShader;
|
||||||
|
|
||||||
void prepareTexturedModel(const TexturedModel &texturedModel);
|
void prepareTexturedModel(const TexturedModel &texturedModel);
|
||||||
void unbindTexturedModel();
|
void unbindTexturedModel();
|
||||||
void prepareInstance(const HexRenderData& hexTile);
|
void prepareInstance(const TerrainRenderingData& hexTile);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
src/engine/renderer/components/TerrainRenderingData.h
Normal file
20
src/engine/renderer/components/TerrainRenderingData.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TERRAINRENDERINGDATA_H
|
||||||
|
#define TERRAINRENDERINGDATA_H
|
||||||
|
#include "../../core/ECS/ModelComponent.h"
|
||||||
|
#include "../../core/ECS/TileRenderComponent.h"
|
||||||
|
#include "../../core/ECS/TransformComponent.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct TerrainRenderingData {
|
||||||
|
std::shared_ptr<TransformComponent> transform;
|
||||||
|
std::shared_ptr<ModelComponent> modelComponent;
|
||||||
|
std::shared_ptr<TileRenderComponent> terrainRenderComponent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //TERRAINRENDERINGDATA_H
|
||||||
@ -5,6 +5,7 @@
|
|||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "../loader/OBJLoader.h"
|
#include "../loader/OBJLoader.h"
|
||||||
|
|
||||||
@ -23,3 +24,8 @@ std::shared_ptr<TexturedModel> AssetManager::getModel(const std::string &name) {
|
|||||||
assert(models.contains(name) && "Model not found!");
|
assert(models.contains(name) && "Model not found!");
|
||||||
return models.at(name);
|
return models.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetManager::insertGeneratedModel(const std::string &name, std::shared_ptr<TexturedModel> model) {
|
||||||
|
assert(!models.contains(name) && "Model already exists!");
|
||||||
|
models[name] = std::move(model);
|
||||||
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ class AssetManager {
|
|||||||
public:
|
public:
|
||||||
static std::shared_ptr<TexturedModel> loadModel(const std::string& name, const std::string& objPath, const std::string& texturePath, Loader& loader);
|
static std::shared_ptr<TexturedModel> loadModel(const std::string& name, const std::string& objPath, const std::string& texturePath, Loader& loader);
|
||||||
static std::shared_ptr<TexturedModel> getModel(const std::string& name);
|
static std::shared_ptr<TexturedModel> getModel(const std::string& name);
|
||||||
|
static void insertGeneratedModel(const std::string& name, std::shared_ptr<TexturedModel> model);
|
||||||
private:
|
private:
|
||||||
static inline std::unordered_map<std::string, std::shared_ptr<TexturedModel>> models;
|
static inline std::unordered_map<std::string, std::shared_ptr<TexturedModel>> models;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -38,10 +38,22 @@ void GameLayer::onAttach()
|
|||||||
|
|
||||||
//treeModel = std::make_unique<TexturedModel>(*OBJLoader::loadModel("assets/trees/lowPolyTree.obj", "assets/trees/lowPolyTree.png", loader));
|
//treeModel = std::make_unique<TexturedModel>(*OBJLoader::loadModel("assets/trees/lowPolyTree.obj", "assets/trees/lowPolyTree.png", loader));
|
||||||
//treeEntity = std::make_unique<Entity>(Entity(treeModel, glm::vec3(0,0,0), 0,0,0, 0.5f));
|
//treeEntity = std::make_unique<Entity>(Entity(treeModel, glm::vec3(0,0,0), 0,0,0, 0.5f));
|
||||||
MapGenerator::generateHexMap(*map, 10,10,10.f, mapEntities);
|
MapGenerator::init(loader, 10.f);
|
||||||
printf("Generated Terrain with %lu Tiles!\n", map->tiles.size());
|
MapGenerator::generateHexMap(*map, 10,10, *entityManager);
|
||||||
|
//printf("Generated Terrain with %lu Tiles!\n", map->tiles.size());
|
||||||
|
|
||||||
|
for (const auto& entity : mapEntities) {
|
||||||
|
EntityID entityID = entityManager->createEntity();
|
||||||
|
glm::vec3 pos = entity->getPosition();
|
||||||
|
glm::vec3 rot = glm::vec3(entity->getRotX(), entity->getRotY(), entity->getRotZ());
|
||||||
|
float scale = entity->getScale();
|
||||||
|
entityManager->addComponent(entityID, std::make_shared<TransformComponent>(pos, rot, scale));
|
||||||
|
entityManager->addComponent(entityID, std::make_shared<ModelComponent>(entity->getModel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
auto cabinModel = AssetManager::loadModel("cabin", "assets/cabin/cabin.obj", "assets/cabin/cabin.jpg", loader);
|
auto cabinModel = AssetManager::loadModel("cabin", "assets/cabin/cabin.obj", "assets/cabin/cabin.jpg", loader);
|
||||||
|
|
||||||
//entities.push_back(std::make_shared<Entity>(Entity(cabinModel, glm::vec3(0,0,0), 0,0,0, 1.f)));
|
//entities.push_back(std::make_shared<Entity>(Entity(cabinModel, glm::vec3(0,0,0), 0,0,0, 1.f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,26 +74,8 @@ void GameLayer::onUpdate()
|
|||||||
|
|
||||||
|
|
||||||
camera->move(moveDir, 0.5f);
|
camera->move(moveDir, 0.5f);
|
||||||
|
tileHighlightSystem->update(*entityManager, *mousePicker, *camera);
|
||||||
for (const auto& entity : entities) {
|
renderSystem->render(*entityManager, *renderer);
|
||||||
renderer->submitEntity(entity.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
tileInteractionSystem->update(*map, *camera, *mousePicker);
|
|
||||||
tileInteractionSystem->handleBuildAction(*map);
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<HexRenderData> terrainRenderData = map->getTerrainRenderData(hexModelDefault, hexModelWood, hexModelStone);
|
|
||||||
for (auto& renderData : terrainRenderData) {
|
|
||||||
renderer->submitTerrainTile(&renderData);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (HexTile& tile : map->tiles) {
|
|
||||||
for (const auto& entity : tile.entitiesOnTile) {
|
|
||||||
renderer->submitEntity(entity.get());
|
|
||||||
}
|
|
||||||
if (tile.building) renderer->submitEntity(tile.building.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer->render(*light, *camera);
|
renderer->render(*light, *camera);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#ifndef DICEWARS_SIEDLER_GAMELAYER_H
|
#ifndef DICEWARS_SIEDLER_GAMELAYER_H
|
||||||
#define DICEWARS_SIEDLER_GAMELAYER_H
|
#define DICEWARS_SIEDLER_GAMELAYER_H
|
||||||
#include "TileInteractionSystem.h"
|
#include "../engine/core/ECS/RenderSystem.h"
|
||||||
#include "../engine/layer/Layer.h"
|
#include "../engine/layer/Layer.h"
|
||||||
#include "../engine/platform/glfw/MousePicker.h"
|
#include "../engine/platform/glfw/MousePicker.h"
|
||||||
#include "../engine/renderer/Renderer.h"
|
#include "../engine/renderer/Renderer.h"
|
||||||
@ -13,6 +13,7 @@
|
|||||||
#include "../engine/layer/entities/Camera.h"
|
#include "../engine/layer/entities/Camera.h"
|
||||||
#include "../engine/renderer/MasterRenderer.h"
|
#include "../engine/renderer/MasterRenderer.h"
|
||||||
#include "hexWorld/Map.h"
|
#include "hexWorld/Map.h"
|
||||||
|
#include "hexWorld/ecs/systems/TileHighlightSystem.h"
|
||||||
|
|
||||||
|
|
||||||
class GameLayer: public Layer {
|
class GameLayer: public Layer {
|
||||||
@ -38,7 +39,11 @@ private:
|
|||||||
|
|
||||||
std::vector<std::shared_ptr<Entity>> mapEntities;
|
std::vector<std::shared_ptr<Entity>> mapEntities;
|
||||||
std::vector<std::shared_ptr<Entity>> entities;
|
std::vector<std::shared_ptr<Entity>> entities;
|
||||||
std::unique_ptr<TileInteractionSystem> tileInteractionSystem = std::make_unique<TileInteractionSystem>();
|
|
||||||
|
std::unique_ptr<RenderSystem> renderSystem = std::make_unique<RenderSystem>();
|
||||||
|
std::unique_ptr<TileHighlightSystem> tileHighlightSystem = std::make_unique<TileHighlightSystem>();
|
||||||
|
std::unique_ptr<EntityManager> entityManager = std::make_unique<EntityManager>();
|
||||||
|
|
||||||
std::unique_ptr<Map> map;
|
std::unique_ptr<Map> map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 08.02.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "TileInteractionSystem.h"
|
|
||||||
|
|
||||||
#include "../engine/layer/entities/Camera.h"
|
|
||||||
#include "../engine/platform/glfw/InputManager.h"
|
|
||||||
#include "../engine/renderer/model/AssetManager.h"
|
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
|
|
||||||
void TileInteractionSystem::update(Map &map, const Camera &camera, const MousePicker &mousePicker) {
|
|
||||||
for (HexTile& tile : map.tiles) {
|
|
||||||
glm::vec3 intersectionPoint;
|
|
||||||
tile.isHighlighted = tile.intersect(camera.getPosition(), mousePicker.getCurrentRay(), intersectionPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileInteractionSystem::handleBuildAction(Map &map) {
|
|
||||||
for (HexTile& tile : map.tiles) {
|
|
||||||
if (tile.isHighlighted && InputManager::isMouseButtonPressed(GLFW_MOUSE_BUTTON_1)) {
|
|
||||||
if (!tile.building && tile.resourceType == RessourceType::WOOD) {
|
|
||||||
tile.entitiesOnTile.clear();
|
|
||||||
tile.building = std::make_shared<Entity>(AssetManager::getModel("cabin"), tile.worldPos, 0,0,0,1.f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 08.02.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef TILEINTERACTIONSYSTEM_H
|
|
||||||
#define TILEINTERACTIONSYSTEM_H
|
|
||||||
#include "../engine/platform/glfw/MousePicker.h"
|
|
||||||
#include "hexWorld/Map.h"
|
|
||||||
|
|
||||||
|
|
||||||
class TileInteractionSystem {
|
|
||||||
public:
|
|
||||||
void update(Map& map, const Camera& camera, const MousePicker& mousePicker);
|
|
||||||
void handleBuildAction(Map& map);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //TILEINTERACTIONSYSTEM_H
|
|
||||||
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
#ifndef HEXMODELFACTORY_H
|
#ifndef HEXMODELFACTORY_H
|
||||||
#define HEXMODELFACTORY_H
|
#define HEXMODELFACTORY_H
|
||||||
#include "HexTile.h"
|
|
||||||
|
|
||||||
|
#include "RessourceType.h"
|
||||||
#include "../../engine/renderer/model/RawModel.h"
|
#include "../../engine/renderer/model/RawModel.h"
|
||||||
#include "../../engine/renderer/model/TexturedModel.h"
|
#include "../../engine/renderer/model/TexturedModel.h"
|
||||||
|
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by sebastian on 07.02.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef HEXTILE_H
|
|
||||||
#define HEXTILE_H
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "../../engine/layer/entities/Entity.h"
|
|
||||||
#include "../../engine/renderer/model/TexturedModel.h"
|
|
||||||
#include "glm/vec2.hpp"
|
|
||||||
#include "glm/vec3.hpp"
|
|
||||||
#include "glm/ext/quaternion_geometric.hpp"
|
|
||||||
|
|
||||||
enum class RessourceType {
|
|
||||||
NONE,
|
|
||||||
WOOD,
|
|
||||||
STONE
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HexTile {
|
|
||||||
glm::vec3 worldPos;
|
|
||||||
int q, r; //Axiale Koordinaten (hex-Koordinaten)
|
|
||||||
int ownerID = -1;
|
|
||||||
RessourceType resourceType = RessourceType::NONE;
|
|
||||||
float radius;
|
|
||||||
bool isHighlighted = false;
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Entity>> entitiesOnTile;
|
|
||||||
std::shared_ptr<Entity> building;
|
|
||||||
|
|
||||||
|
|
||||||
bool intersect(const glm::vec3& rayOrigin, const glm::vec3& rayDirection, glm::vec3& intersectionPoint) const {
|
|
||||||
float t = -rayOrigin.y / rayDirection.y;
|
|
||||||
if (t < 0) return false; // Ray zeigt nach oben, nicht getroffen
|
|
||||||
|
|
||||||
intersectionPoint = rayOrigin + t * rayDirection;
|
|
||||||
|
|
||||||
glm::vec2 diff(intersectionPoint.x - worldPos.x, intersectionPoint.z - worldPos.z);
|
|
||||||
return glm::length(diff) <= radius -0.1f;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HexRenderData {
|
|
||||||
std::shared_ptr<TexturedModel> model;
|
|
||||||
glm::vec3 position;
|
|
||||||
bool highlight = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //HEXTILE_H
|
|
||||||
@ -4,20 +4,13 @@
|
|||||||
|
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
|
|
||||||
std::vector<HexRenderData> Map::getTerrainRenderData(const std::shared_ptr<TexturedModel>& hexModel,
|
#include "ecs/components/MapEntityComponent.h"
|
||||||
const std::shared_ptr<TexturedModel>& woodModel, const std::shared_ptr<TexturedModel>& stoneModel) {
|
#include "ecs/components/TileGameplayComponent.h"
|
||||||
std::vector<HexRenderData> renderData;
|
|
||||||
renderData.reserve(tiles.size());
|
void Map::clear(EntityManager &entityManager) {
|
||||||
for (auto& tile : tiles) {
|
for (EntityID id: entityManager.getAllEntities()) {
|
||||||
HexRenderData data;
|
if (entityManager.getComponent<MapEntityComponent>(id)) {
|
||||||
if (tile.resourceType == RessourceType::WOOD) {
|
entityManager.destroyEntity(id);
|
||||||
data = HexRenderData(woodModel, tile.worldPos, tile.isHighlighted);
|
|
||||||
} else if (tile.resourceType == RessourceType::NONE) {
|
|
||||||
data = HexRenderData(hexModel, tile.worldPos, tile.isHighlighted);
|
|
||||||
} else if (tile.resourceType == RessourceType::STONE) {
|
|
||||||
data =HexRenderData(stoneModel, tile.worldPos, tile.isHighlighted);
|
|
||||||
}
|
}
|
||||||
renderData.push_back(data);
|
|
||||||
}
|
}
|
||||||
return renderData;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,20 +4,21 @@
|
|||||||
|
|
||||||
#ifndef MAP_H
|
#ifndef MAP_H
|
||||||
#define MAP_H
|
#define MAP_H
|
||||||
#include "HexTile.h"
|
#include "../../engine/core/ECS/EntityManager.h"
|
||||||
|
|
||||||
struct Area {
|
struct Area {
|
||||||
int id;
|
int id;
|
||||||
std::vector<HexTile*> tiles;
|
std::vector<EntityID> tiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Map {
|
class Map {
|
||||||
public:
|
public:
|
||||||
std::vector<Area> areas;
|
int width;
|
||||||
std::vector<HexTile> tiles;
|
int height;
|
||||||
|
|
||||||
std::vector<HexRenderData> getTerrainRenderData(const std::shared_ptr<TexturedModel> &hexModel, const std::shared_ptr<TexturedModel> &woodModel, const std::shared_ptr<
|
std::vector<Area> areas;
|
||||||
TexturedModel> &stoneModel);
|
|
||||||
|
void clear(EntityManager& entityManager);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,3 +3,60 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "MapGenerator.h"
|
#include "MapGenerator.h"
|
||||||
|
|
||||||
|
float MapGenerator::hexRadius = 10.0f;
|
||||||
|
|
||||||
|
void MapGenerator::init(Loader &loader, float hexRadius) {
|
||||||
|
MapGenerator::hexRadius = hexRadius;
|
||||||
|
auto hexModelNone = HexModelFactory::createTexturedHexModel(loader, hexRadius, RessourceType::NONE);
|
||||||
|
auto hexModelWood = HexModelFactory::createTexturedHexModel(loader, hexRadius, RessourceType::WOOD);
|
||||||
|
auto hexModelStone = HexModelFactory::createTexturedHexModel(loader, hexRadius, RessourceType::STONE);
|
||||||
|
|
||||||
|
AssetManager::insertGeneratedModel("hexModelNone", std::make_shared<TexturedModel>(hexModelNone));
|
||||||
|
AssetManager::insertGeneratedModel("hexModelWood", std::make_shared<TexturedModel>(hexModelWood));
|
||||||
|
AssetManager::insertGeneratedModel("hexModelStone", std::make_shared<TexturedModel>(hexModelStone));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapGenerator::generateHexMap(Map &map, int width, int height, EntityManager &entityManager) {
|
||||||
|
Random random;
|
||||||
|
|
||||||
|
map.clear(entityManager);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
float randomValue = random.randomFloat(0.0f, 1.0f);
|
||||||
|
RessourceType resourceType = RessourceType::NONE;
|
||||||
|
std::shared_ptr<TexturedModel> hexModel = AssetManager::getModel("hexModelNone");
|
||||||
|
if (randomValue < 0.5f) {
|
||||||
|
resourceType = RessourceType::WOOD;
|
||||||
|
ForestTileGenerator forestTileGenerator;
|
||||||
|
std::vector<EntityID> entities = forestTileGenerator.generateHexTile(entityManager, random, worldPos);
|
||||||
|
hexModel = AssetManager::getModel("hexModelWood");
|
||||||
|
} else if (randomValue < 0.75f) {
|
||||||
|
resourceType = RessourceType::STONE;
|
||||||
|
hexModel = AssetManager::getModel("hexModelStone");
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityID entityID = entityManager.createEntity();
|
||||||
|
const auto transformComponent = std::make_shared<TransformComponent>(worldPos, glm::vec3(0), 1.0f);
|
||||||
|
const auto modelComponent = std::make_shared<ModelComponent>(hexModel);
|
||||||
|
const auto tileHighlightComponent = std::make_shared<TileRenderComponent>(false);
|
||||||
|
const auto tileGameplayComponent = std::make_shared<TileGameplayComponent>(q, r, radius, resourceType);
|
||||||
|
|
||||||
|
entityManager.addComponent(entityID, transformComponent);
|
||||||
|
entityManager.addComponent(entityID, modelComponent);
|
||||||
|
entityManager.addComponent(entityID, tileHighlightComponent);
|
||||||
|
entityManager.addComponent(entityID, tileGameplayComponent);
|
||||||
|
entityManager.addComponent(entityID, std::make_shared<MapEntityComponent>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,48 +7,25 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include "HexTile.h"
|
#include "HexModelFactory.h"
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
|
#include "../../engine/core/ECS/ModelComponent.h"
|
||||||
|
#include "../../engine/core/ECS/TileRenderComponent.h"
|
||||||
|
#include "../../engine/core/ECS/TransformComponent.h"
|
||||||
#include "../../engine/renderer/model/AssetManager.h"
|
#include "../../engine/renderer/model/AssetManager.h"
|
||||||
#include "../../engine/toolbox/Random.h"
|
#include "../../engine/toolbox/Random.h"
|
||||||
|
#include "ecs/components/MapEntityComponent.h"
|
||||||
|
#include "ecs/components/TileGameplayComponent.h"
|
||||||
#include "tileGenerator/ForestTileGenerator.h"
|
#include "tileGenerator/ForestTileGenerator.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MapGenerator {
|
class MapGenerator {
|
||||||
|
private:
|
||||||
|
static float hexRadius;
|
||||||
public:
|
public:
|
||||||
static void generateHexMap(Map& map, int width, int height, float hexRadius, std::vector<std::shared_ptr<Entity>>& mapEntities) {
|
static void init(Loader& loader, float hexRadius);
|
||||||
// Zufallsgenerator initialisieren (einmal)
|
static void generateHexMap(Map& map, int width, int height, EntityManager& entityManager);
|
||||||
Random random;
|
|
||||||
|
|
||||||
map.tiles.clear();
|
|
||||||
|
|
||||||
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) {
|
|
||||||
HexTile tile;
|
|
||||||
tile.q = q;
|
|
||||||
tile.r = r;
|
|
||||||
|
|
||||||
// Pointy-top Hexes
|
|
||||||
float x = xOffset * (q + 0.5f * (r % 2));
|
|
||||||
float z = zOffset * r;
|
|
||||||
tile.worldPos = glm::vec3(x, 0.0f, z);
|
|
||||||
tile.radius = hexRadius;
|
|
||||||
|
|
||||||
float randomValue = random.randomFloat(0.0f, 1.0f);
|
|
||||||
if (randomValue < 0.5f) {
|
|
||||||
tile.resourceType = RessourceType::WOOD;
|
|
||||||
ForestTileGenerator forestTileGenerator;
|
|
||||||
const std::vector<std::shared_ptr<Entity>> forestEntities = forestTileGenerator.generateHexTile(random, tile.worldPos, mapEntities);
|
|
||||||
tile.entitiesOnTile = forestEntities;
|
|
||||||
} else if (randomValue < 0.75f) {
|
|
||||||
tile.resourceType = RessourceType::STONE;
|
|
||||||
}
|
|
||||||
map.tiles.push_back(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
8
src/game/hexWorld/RessourceType.h
Normal file
8
src/game/hexWorld/RessourceType.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RESSOURCETYPE_H
|
||||||
|
#define RESSOURCETYPE_H
|
||||||
|
enum class RessourceType {NONE, WOOD, STONE};
|
||||||
|
#endif //RESSOURCETYPE_H
|
||||||
14
src/game/hexWorld/ecs/components/MapEntityComponent.h
Normal file
14
src/game/hexWorld/ecs/components/MapEntityComponent.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MAPENTITYCOMPONENT_H
|
||||||
|
#define MAPENTITYCOMPONENT_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct MapEntityComponent {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MAPENTITYCOMPONENT_H
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TileGameplayComponent.h"
|
||||||
29
src/game/hexWorld/ecs/components/TileGameplayComponent.h
Normal file
29
src/game/hexWorld/ecs/components/TileGameplayComponent.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TILEGAMEPLAYCOMPONENT_H
|
||||||
|
#define TILEGAMEPLAYCOMPONENT_H
|
||||||
|
|
||||||
|
#include "../../../../engine/core/ECS/Component.h"
|
||||||
|
#include "../../../../engine/core/ECS/EntityManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum class RessourceType;
|
||||||
|
|
||||||
|
class TileGameplayComponent : public Component {
|
||||||
|
public:
|
||||||
|
int q, r;
|
||||||
|
float radius;
|
||||||
|
RessourceType ressourceType;
|
||||||
|
|
||||||
|
EntityID buildingEntityID = 0;
|
||||||
|
std::vector<EntityID> entitiesOnTile;
|
||||||
|
|
||||||
|
TileGameplayComponent(int q, int r, float radius, RessourceType ressourceType) : q(q), r(r), radius(radius), ressourceType(ressourceType) {};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //TILEGAMEPLAYCOMPONENT_H
|
||||||
42
src/game/hexWorld/ecs/systems/TileHighlightSystem.cpp
Normal file
42
src/game/hexWorld/ecs/systems/TileHighlightSystem.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TileHighlightSystem.h"
|
||||||
|
|
||||||
|
#include "../../../../engine/core/ECS/TileRenderComponent.h"
|
||||||
|
#include "../../../../engine/core/ECS/TransformComponent.h"
|
||||||
|
#include "../components/TileGameplayComponent.h"
|
||||||
|
#include "../../../../engine/layer/entities/Camera.h"
|
||||||
|
|
||||||
|
|
||||||
|
void TileHighlightSystem::update(EntityManager &entityManager, const MousePicker& picker, const Camera& camera) {
|
||||||
|
for (EntityID entityID : entityManager.getAllEntities()) {
|
||||||
|
auto tileRenderComponent = entityManager.getComponent<TileRenderComponent>(entityID);
|
||||||
|
auto transformComponent = entityManager.getComponent<TransformComponent>(entityID);
|
||||||
|
auto tileGameplayComponent = entityManager.getComponent<TileGameplayComponent>(entityID);
|
||||||
|
|
||||||
|
if (!tileRenderComponent || !transformComponent || !tileGameplayComponent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 rayOrigin = camera.getPosition();
|
||||||
|
glm::vec3 rayDirection = picker.getCurrentRay();
|
||||||
|
glm::vec3 intersectionPoint;
|
||||||
|
if (intersectTile(rayOrigin, rayDirection, transformComponent->position, tileGameplayComponent->radius, intersectionPoint)) {
|
||||||
|
tileRenderComponent->isHighlighted = true;
|
||||||
|
} else {
|
||||||
|
tileRenderComponent->isHighlighted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TileHighlightSystem::intersectTile(const glm::vec3 &rayOrigin, const glm::vec3 &rayDirection, glm::vec3 worldPos, float hexRadius, glm::vec3& intersectionPoint) {
|
||||||
|
float t = -rayOrigin.y / rayDirection.y;
|
||||||
|
if (t < 0) return false;
|
||||||
|
|
||||||
|
intersectionPoint = rayOrigin + rayDirection * t;
|
||||||
|
|
||||||
|
glm::vec2 diff(intersectionPoint.x - worldPos.x, intersectionPoint.z - worldPos.z);
|
||||||
|
return glm::length(diff) <= hexRadius - 0.1f;
|
||||||
|
}
|
||||||
20
src/game/hexWorld/ecs/systems/TileHighlightSystem.h
Normal file
20
src/game/hexWorld/ecs/systems/TileHighlightSystem.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 08.02.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef TILEHIGHLIGHTSYSTEM_H
|
||||||
|
#define TILEHIGHLIGHTSYSTEM_H
|
||||||
|
#include "../../../../engine/core/ECS/EntityManager.h"
|
||||||
|
#include "../../../../engine/platform/glfw/MousePicker.h"
|
||||||
|
class Camera;
|
||||||
|
|
||||||
|
class TileHighlightSystem {
|
||||||
|
public:
|
||||||
|
void update(EntityManager &entityManager, const MousePicker &picker, const Camera &camera);
|
||||||
|
private:
|
||||||
|
bool intersectTile(const glm::vec3 & rayOrigin, const glm::vec3 & rayDirection, glm::vec3 worldPos, float hexRadius, glm::vec3 &interectionPoint);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //TILEHIGHLIGHTSYSTEM_H
|
||||||
@ -4,17 +4,18 @@
|
|||||||
|
|
||||||
#include "ForestTileGenerator.h"
|
#include "ForestTileGenerator.h"
|
||||||
|
|
||||||
|
#include "../../../engine/core/ECS/ModelComponent.h"
|
||||||
|
#include "../../../engine/core/ECS/TransformComponent.h"
|
||||||
#include "../../../engine/renderer/model/AssetManager.h"
|
#include "../../../engine/renderer/model/AssetManager.h"
|
||||||
#include "glm/detail/func_geometric.inl"
|
#include "glm/detail/func_geometric.inl"
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Entity>> ForestTileGenerator::generateHexTile(Random& random, glm::vec3 tilePos, std::vector<std::shared_ptr<Entity>> &mapEntities) const {
|
std::vector<EntityID> ForestTileGenerator::generateHexTile(EntityManager& em, Random& random, glm::vec3 tilePos) const {
|
||||||
int treeCount = random.randomInt(minTreeCount, maxTreeCount);
|
int treeCount = random.randomInt(minTreeCount, maxTreeCount);
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Entity>> entitiesOnTile;
|
|
||||||
std::shared_ptr<TexturedModel> treeModel = AssetManager::getModel("lowPolyTree");
|
std::shared_ptr<TexturedModel> treeModel = AssetManager::getModel("lowPolyTree");
|
||||||
std::shared_ptr<TexturedModel> treeModel2 = AssetManager::getModel("lowPolyTree2");
|
std::shared_ptr<TexturedModel> treeModel2 = AssetManager::getModel("lowPolyTree2");
|
||||||
std::vector<std::shared_ptr<TexturedModel>> treeModels = {treeModel, treeModel2};
|
std::vector<std::shared_ptr<TexturedModel>> treeModels = {treeModel, treeModel2};
|
||||||
|
std::vector<EntityID> entitiyIDs;
|
||||||
for (int i = 0; i < treeCount; ++i) {
|
for (int i = 0; i < treeCount; ++i) {
|
||||||
glm::vec3 treePos;
|
glm::vec3 treePos;
|
||||||
bool validPos = false;
|
bool validPos = false;
|
||||||
@ -28,21 +29,30 @@ std::vector<std::shared_ptr<Entity>> ForestTileGenerator::generateHexTile(Random
|
|||||||
treePos.z += random.randomFloat(-hexRadius * 0.5f, hexRadius * 0.5f);
|
treePos.z += random.randomFloat(-hexRadius * 0.5f, hexRadius * 0.5f);
|
||||||
|
|
||||||
validPos = true;
|
validPos = true;
|
||||||
for (const auto& otherTree : entitiesOnTile) {
|
for (const auto& otherTreeID : entitiyIDs) {
|
||||||
if (glm::distance(treePos, otherTree->getPosition()) < minDistance) {
|
const auto otherTree = em.getComponent<TransformComponent>(otherTreeID);
|
||||||
|
if (otherTree) {
|
||||||
|
if (glm::distance(treePos, otherTree->position) < minDistance) {
|
||||||
validPos = false;
|
validPos = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
attempts++;
|
attempts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validPos) continue; // zu viele Versuche, überspringen
|
if (!validPos) continue; // zu viele Versuche, überspringen
|
||||||
|
|
||||||
int treeModelIndex = random.randomInt(0, static_cast<int>(treeModels.size()-1));
|
int treeModelIndex = random.randomInt(0, static_cast<int>(treeModels.size()-1));
|
||||||
auto treeEntity = std::make_shared<Entity>(treeModels[treeModelIndex], treePos, 0, 0, 0, 1.f);
|
|
||||||
mapEntities.push_back(treeEntity);
|
const auto transformComponent = std::make_shared<TransformComponent>(treePos, glm::vec3(0), 1.f);
|
||||||
entitiesOnTile.push_back(treeEntity);
|
const auto modelComponent = std::make_shared<ModelComponent>(treeModels[treeModelIndex]);
|
||||||
|
|
||||||
|
const EntityID entityID = em.createEntity();
|
||||||
|
em.addComponent(entityID, transformComponent);
|
||||||
|
em.addComponent(entityID, modelComponent);
|
||||||
|
entitiyIDs.push_back(entityID);
|
||||||
}
|
}
|
||||||
return entitiesOnTile;
|
return entitiyIDs;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
class ForestTileGenerator : public HexTileGeneratorStrategy {
|
class ForestTileGenerator : public HexTileGeneratorStrategy {
|
||||||
public:
|
public:
|
||||||
std::vector<std::shared_ptr<Entity>> generateHexTile(Random& random, glm::vec3 tilePos, std::vector<std::shared_ptr<Entity>>& mapEntities) const override;
|
std::vector<EntityID> generateHexTile(EntityManager& em, Random& random, glm::vec3 tilePos) const override;
|
||||||
private:
|
private:
|
||||||
const int minTreeCount = 3;
|
const int minTreeCount = 3;
|
||||||
const int maxTreeCount = 5;
|
const int maxTreeCount = 5;
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../../../engine/core/ECS/EntityManager.h"
|
||||||
#include "../../../engine/layer/entities/Entity.h"
|
#include "../../../engine/layer/entities/Entity.h"
|
||||||
#include "../../../engine/toolbox/Random.h"
|
#include "../../../engine/toolbox/Random.h"
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ class HexTileGeneratorStrategy {
|
|||||||
public:
|
public:
|
||||||
virtual ~HexTileGeneratorStrategy() = default;
|
virtual ~HexTileGeneratorStrategy() = default;
|
||||||
|
|
||||||
virtual std::vector<std::shared_ptr<Entity>> generateHexTile(Random& random, glm::vec3 tilePos, std::vector<std::shared_ptr<Entity>>& mapEntities) const = 0;
|
virtual std::vector<EntityID> generateHexTile(EntityManager& em, Random& random, glm::vec3 tilePos) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user