From 1735d89eca1c0d801206d9ceb281a6addaa24625 Mon Sep 17 00:00:00 2001 From: sebastian Date: Fri, 13 Feb 2026 20:42:19 +0100 Subject: [PATCH] ADD: Implement Basic Turnsystem with UI Update --- CMakeLists.txt | 9 +++++ src/engine/core/Application.h | 3 ++ src/engine/core/events/EventBus.cpp | 5 +++ src/engine/core/events/EventBus.h | 39 +++++++++++++++++++ src/engine/core/gui/uiComponent/UiText.cpp | 4 ++ src/engine/core/gui/uiComponent/UiText.h | 4 +- src/engine/platform/glfw/InputManager.cpp | 23 +++++++++-- src/engine/platform/glfw/InputManager.h | 10 ++++- src/game/GameLayer.cpp | 14 ++++--- src/game/GameLayer.h | 3 ++ src/game/UILayer.cpp | 23 +++++++++-- src/game/UILayer.h | 5 +++ .../hexWorld/events/ResourceCollectEvent.cpp | 5 +++ .../hexWorld/events/ResourceCollectEvent.h | 18 +++++++++ src/game/hexWorld/events/TurnChangedEvent.cpp | 5 +++ src/game/hexWorld/events/TurnChangedEvent.h | 15 +++++++ src/game/hexWorld/gameplay/TurnState.h | 12 ++++++ src/game/hexWorld/gameplay/TurnSystem.cpp | 13 +++++++ src/game/hexWorld/gameplay/TurnSystem.h | 18 +++++++++ 19 files changed, 214 insertions(+), 14 deletions(-) create mode 100644 src/engine/core/events/EventBus.cpp create mode 100644 src/engine/core/events/EventBus.h create mode 100644 src/game/hexWorld/events/ResourceCollectEvent.cpp create mode 100644 src/game/hexWorld/events/ResourceCollectEvent.h create mode 100644 src/game/hexWorld/events/TurnChangedEvent.cpp create mode 100644 src/game/hexWorld/events/TurnChangedEvent.h create mode 100644 src/game/hexWorld/gameplay/TurnState.h create mode 100644 src/game/hexWorld/gameplay/TurnSystem.cpp create mode 100644 src/game/hexWorld/gameplay/TurnSystem.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e6154b2..fcfd505 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,6 +162,15 @@ add_executable(Dicewars_Siedler src/main.cpp src/game/hexWorld/building/BuildingConfig.cpp src/game/hexWorld/building/BuildingConfig.h src/engine/toolbox/util.h + src/engine/core/events/EventBus.cpp + src/engine/core/events/EventBus.h + src/game/hexWorld/events/TurnChangedEvent.cpp + src/game/hexWorld/events/TurnChangedEvent.h + src/game/hexWorld/events/ResourceCollectEvent.cpp + src/game/hexWorld/events/ResourceCollectEvent.h + src/game/hexWorld/gameplay/TurnSystem.cpp + src/game/hexWorld/gameplay/TurnSystem.h + src/game/hexWorld/gameplay/TurnState.h ) target_compile_options(Dicewars_Siedler PRIVATE diff --git a/src/engine/core/Application.h b/src/engine/core/Application.h index 1bde5b5..d9de98a 100644 --- a/src/engine/core/Application.h +++ b/src/engine/core/Application.h @@ -8,6 +8,7 @@ #include #include "Window.h" +#include "events/EventBus.h" class Layer; @@ -23,6 +24,7 @@ public: static Application& getInstance(); [[nodiscard]] Window& getWindow() const {return *window;} + EventBus& getEventBus() {return eventBus;} private: bool running = true; std::unique_ptr window; @@ -30,6 +32,7 @@ private: static Application* instance; std::vector layers; + EventBus eventBus; protected: void pushLayer(Layer* layer); diff --git a/src/engine/core/events/EventBus.cpp b/src/engine/core/events/EventBus.cpp new file mode 100644 index 0000000..0305a22 --- /dev/null +++ b/src/engine/core/events/EventBus.cpp @@ -0,0 +1,5 @@ +// +// Created by sebastian on 13.02.26. +// + +#include "EventBus.h" \ No newline at end of file diff --git a/src/engine/core/events/EventBus.h b/src/engine/core/events/EventBus.h new file mode 100644 index 0000000..87b9a9a --- /dev/null +++ b/src/engine/core/events/EventBus.h @@ -0,0 +1,39 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_EVENTBUS_H +#define DICEWARS_SIEDLER_EVENTBUS_H +#include +#include + + +class EventBus { +public: + template + using Handler = std::function; + + template + void subscribe(Handler handler) { + auto& handlers = getHandlers(); + handlers.emplace_back(std::move(handler)); + } + + template + void emit(const Event& event) { + auto& handlers = getHandlers(); + for (auto& h : handlers) { + h(event); + } + } + +private: + template + std::vector>& getHandlers() { + static std::vector> handlers; + return handlers; + } +}; + + +#endif //DICEWARS_SIEDLER_EVENTBUS_H \ No newline at end of file diff --git a/src/engine/core/gui/uiComponent/UiText.cpp b/src/engine/core/gui/uiComponent/UiText.cpp index 1c0706f..4bc1aff 100644 --- a/src/engine/core/gui/uiComponent/UiText.cpp +++ b/src/engine/core/gui/uiComponent/UiText.cpp @@ -22,5 +22,9 @@ void UiText::setText(const std::string &text) { void UiText::onCollectRenderData(UiRenderBundle& ui_render_bundle) { if (!visible) return; + if (this->text == "Runde: 0") { + printf("Runde: 0\n"); + } + ui_render_bundle.addText(this); } diff --git a/src/engine/core/gui/uiComponent/UiText.h b/src/engine/core/gui/uiComponent/UiText.h index fa977f6..5b9f84f 100644 --- a/src/engine/core/gui/uiComponent/UiText.h +++ b/src/engine/core/gui/uiComponent/UiText.h @@ -13,8 +13,8 @@ class Font; class UiText : public UiComponent { public: - UiText(Font& font, std::string text, LayoutStyle& style, glm::vec3 size); - UiText(Font& font, std::string text, LayoutStyle& style); + UiText(Font& font, std::string text, LayoutStyle& style, glm::vec3 color); + UiText(Font& font, std::string text, LayoutStyle& color); void setText(const std::string& text); [[nodiscard]] const Font& getFont() const { return font; } diff --git a/src/engine/platform/glfw/InputManager.cpp b/src/engine/platform/glfw/InputManager.cpp index 72f979c..da16568 100644 --- a/src/engine/platform/glfw/InputManager.cpp +++ b/src/engine/platform/glfw/InputManager.cpp @@ -8,10 +8,15 @@ bool InputManager::current[GLFW_MOUSE_BUTTON_LAST] = { false }; bool InputManager::previous[GLFW_MOUSE_BUTTON_LAST] = { false }; +bool InputManager::currentKeys[GLFW_KEY_LAST] = { false }; +bool InputManager::previousKeys[GLFW_KEY_LAST] = { false }; bool InputManager::isKeyPressed(int keycode) { - auto window = static_cast(Application::getInstance().getWindow().GetNativeWindow()); - return glfwGetKey(window, keycode) == GLFW_PRESS; + return currentKeys[keycode] && !previousKeys[keycode]; +} + +bool InputManager::isKeyReleased(int keycode) { + return !currentKeys[keycode] && previousKeys[keycode]; } bool InputManager::isMouseButtonPressed(int button) { @@ -22,11 +27,23 @@ bool InputManager::isMouseButtonReleased(int button) { return !current[button] && previous[button]; } +bool InputManager::isKeyDown(int keycode) { + return currentKeys[keycode]; +} + void InputManager::update() { + auto window = static_cast(Application::getInstance().getWindow().GetNativeWindow()); + for (int i=0; i < GLFW_MOUSE_BUTTON_LAST; ++i) { previous[i] = current[i]; - current[i] = glfwGetMouseButton(static_cast(Application::getInstance().getWindow().GetNativeWindow()), i) == GLFW_PRESS; + current[i] = glfwGetMouseButton(window, i) == GLFW_PRESS; } + + for (int i=0; i < GLFW_KEY_LAST; ++i) { + previousKeys[i] = currentKeys[i]; + currentKeys[i] = glfwGetKey(window, i) == GLFW_PRESS; + } + } glm::vec2 InputManager::getMousePosition() { diff --git a/src/engine/platform/glfw/InputManager.h b/src/engine/platform/glfw/InputManager.h index 2155d0d..36dbe19 100644 --- a/src/engine/platform/glfw/InputManager.h +++ b/src/engine/platform/glfw/InputManager.h @@ -11,7 +11,7 @@ class InputManager { public: - static bool isKeyPressed(int keycode); + static glm::vec2 getMousePosition(); static glm::vec2 getMousePositionNormalized(); @@ -21,12 +21,20 @@ public: static bool isMouseButtonPressed(int button); static bool isMouseButtonReleased(int button); + static bool isKeyDown(int keycode); + static bool isKeyPressed(int keycode); + static bool isKeyReleased(int keycode); + + static void update(); private: static bool current[GLFW_MOUSE_BUTTON_LAST]; static bool previous[GLFW_MOUSE_BUTTON_LAST]; + static bool currentKeys[GLFW_KEY_LAST]; + static bool previousKeys[GLFW_KEY_LAST]; + }; diff --git a/src/game/GameLayer.cpp b/src/game/GameLayer.cpp index b5ccaab..f8c04af 100644 --- a/src/game/GameLayer.cpp +++ b/src/game/GameLayer.cpp @@ -25,7 +25,7 @@ void GameLayer::onAttach() texturedModel = *OBJLoader::loadModel("assets/dragon/dragon.obj", "assets/dragon/dragon.png", loader); entities.push_back(std::make_shared(Entity(std::make_shared(texturedModel), glm::vec3(0,0,-25), 0,0,0, 1.f))); camera = std::make_unique(); - light = std::make_unique(glm::vec3(0,10,0), glm::vec3(1,1,1)); + light = std::make_unique(glm::vec3(50,100,50), glm::vec3(1,1,1)); mousePicker = std::make_unique(renderer->getProjectionMatrix(), MathUtils::createViewMatrix(*camera)); //Map Generation @@ -77,10 +77,10 @@ void GameLayer::onUpdate() mousePicker->update(*camera); //printf("Mouse Ray: %f, %f, %f\n", mousePicker->getCurrentRay().x, mousePicker->getCurrentRay().y, mousePicker->getCurrentRay().z); glm::vec3 moveDir = glm::vec3(0,0,0); - if (InputManager::isKeyPressed(GLFW_KEY_W)) moveDir.z -= 1.0f; - if (InputManager::isKeyPressed(GLFW_KEY_S)) moveDir.z += 1.0f; - if (InputManager::isKeyPressed(GLFW_KEY_A)) moveDir.x -= 1.0f; - if (InputManager::isKeyPressed(GLFW_KEY_D)) moveDir.x += 1.0f; + if (InputManager::isKeyDown(GLFW_KEY_W)) moveDir.z -= 1.0f; + if (InputManager::isKeyDown(GLFW_KEY_S)) moveDir.z += 1.0f; + if (InputManager::isKeyDown(GLFW_KEY_A)) moveDir.x -= 1.0f; + if (InputManager::isKeyDown(GLFW_KEY_D)) moveDir.x += 1.0f; if (InputManager::isKeyPressed(GLFW_KEY_1)) { gameMode->setActiveBuilding(BuildingType::FOREST_HUT); @@ -88,6 +88,10 @@ void GameLayer::onUpdate() gameMode->setActiveBuilding(BuildingType::STONE_MASON); } + if (InputManager::isKeyPressed(GLFW_KEY_KP_ADD)) { + turnSystem->nextTurn(*turnState, Application::getInstance().getEventBus()); + } + camera->move(moveDir, 0.5f); tileHighlightSystem->update(*entityManager, *mousePicker, *camera); diff --git a/src/game/GameLayer.h b/src/game/GameLayer.h index 0e225b8..b9322b1 100644 --- a/src/game/GameLayer.h +++ b/src/game/GameLayer.h @@ -15,6 +15,7 @@ #include "hexWorld/Map.h" #include "hexWorld/ecs/systems/BuildingPlacementSystem.h" #include "hexWorld/ecs/systems/TileHighlightSystem.h" +#include "hexWorld/gameplay/TurnSystem.h" class GameLayer: public Layer { @@ -45,6 +46,8 @@ private: std::unique_ptr entityManager = std::make_unique(); std::unique_ptr map; + std::unique_ptr turnSystem = std::make_unique(); + std::unique_ptr turnState = std::make_unique(); }; diff --git a/src/game/UILayer.cpp b/src/game/UILayer.cpp index ccc9ea6..7c50ac8 100644 --- a/src/game/UILayer.cpp +++ b/src/game/UILayer.cpp @@ -7,17 +7,19 @@ #include #include +#include "../engine/core/Application.h" #include "../engine/core/gui/text/Font.h" #include "../engine/core/gui/uiComponent/UiButton.h" #include "../engine/core/gui/uiComponent/UiImage.h" #include "../engine/core/gui/uiComponent/UiText.h" #include "../engine/renderer/loader/Loader.h" #include "../engine/renderer/model/GUITexture.h" +#include "hexWorld/events/TurnChangedEvent.h" #include "ui/components/UiInventoryContainer.h" #include "ui/components/UiRessourceWidget.h" #include "ui/components/factorys/RessourceWidgetFactory.h" -UILayer::UILayer() { +UILayer::UILayer(): events(Application::getInstance().getEventBus()) { Loader& loader = Loader::instance(); guiRenderer = std::make_unique(loader); textRenderer = std::make_unique(); @@ -28,7 +30,7 @@ void UILayer::onAttach() { rootContainer = std::make_unique(); - rootContainer->getLayoutStyle().flexDirection = FlexDirection::Row; + rootContainer->getLayoutStyle().flexDirection = FlexDirection::Column; auto imageStyle = LayoutStyle(); imageStyle.width = SizeValue(0.25f, SizeUnit::Percent); @@ -63,7 +65,7 @@ void UILayer::onAttach() { //rootContainer->addChild(std::move(button)); smallFont =std::make_unique("/usr/share/fonts/TTF/DejaVuSans.ttf", 18); - + mediumFont = std::make_unique("/usr/share/fonts/TTF/DejaVuSans.ttf", 28); auto inventoryContainer = std::make_unique(*smallFont); @@ -75,6 +77,21 @@ void UILayer::onAttach() { inventoryContainerID = rootContainer->addChild(std::move(inventoryContainer)); + LayoutStyle turnStyle; + turnStyle.width = SizeValue(200.f, SizeUnit::Pixels); + turnStyle.height = SizeValue(30.f, SizeUnit::Pixels); // nur für Layout, echte Höhe kommt aus Font + turnStyle.margin.left = {20.f, SizeUnit::Pixels}; // Abstand zum Inventory + turnStyle.margin.top = {10.f, SizeUnit::Pixels}; + + auto turnLabel = std::make_unique(*mediumFont, "Runde: 1", turnStyle, glm::vec3(1,1,1)); + turnTextID = rootContainer->addChild(std::move(turnLabel)); + + events.subscribe([this](const TurnChangedEvent& event) { + auto turnTextLabel = dynamic_cast(rootContainer->getChildAtIndex(turnTextID)); + if (turnTextLabel) { + turnTextLabel->setText("Runde: " + std::to_string(event.newTurn)); + }; + }); } void UILayer::onUpdate() { diff --git a/src/game/UILayer.h b/src/game/UILayer.h index 67de6b0..54796eb 100644 --- a/src/game/UILayer.h +++ b/src/game/UILayer.h @@ -7,6 +7,7 @@ #include #include "GameMode.h" +#include "../engine/core/events/EventBus.h" #include "../engine/core/gui/text/Font.h" #include "../engine/core/gui/uiMain/UiContainer.h" #include "../engine/layer/Layer.h" @@ -21,9 +22,13 @@ private: std::unique_ptr textRenderer; std::unique_ptr font; std::unique_ptr smallFont; + std::unique_ptr mediumFont; std::unique_ptr rootContainer; size_t inventoryContainerID; + size_t turnTextID; + + EventBus& events; public: UILayer(); void onAttach() override; diff --git a/src/game/hexWorld/events/ResourceCollectEvent.cpp b/src/game/hexWorld/events/ResourceCollectEvent.cpp new file mode 100644 index 0000000..8f2ad7d --- /dev/null +++ b/src/game/hexWorld/events/ResourceCollectEvent.cpp @@ -0,0 +1,5 @@ +// +// Created by sebastian on 13.02.26. +// + +#include "ResourceCollectEvent.h" \ No newline at end of file diff --git a/src/game/hexWorld/events/ResourceCollectEvent.h b/src/game/hexWorld/events/ResourceCollectEvent.h new file mode 100644 index 0000000..f332bec --- /dev/null +++ b/src/game/hexWorld/events/ResourceCollectEvent.h @@ -0,0 +1,18 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_RESOURCECOLLECTEVENT_H +#define DICEWARS_SIEDLER_RESOURCECOLLECTEVENT_H +#include "../../../engine/core/ECS/EntityManager.h" + + +class ResourceCollectEvent { +public: + EntityID buildingEntityID; + RessourceType ressourceType; + int amount; +}; + + +#endif //DICEWARS_SIEDLER_RESOURCECOLLECTEVENT_H \ No newline at end of file diff --git a/src/game/hexWorld/events/TurnChangedEvent.cpp b/src/game/hexWorld/events/TurnChangedEvent.cpp new file mode 100644 index 0000000..a312fde --- /dev/null +++ b/src/game/hexWorld/events/TurnChangedEvent.cpp @@ -0,0 +1,5 @@ +// +// Created by sebastian on 13.02.26. +// + +#include "TurnChangedEvent.h" \ No newline at end of file diff --git a/src/game/hexWorld/events/TurnChangedEvent.h b/src/game/hexWorld/events/TurnChangedEvent.h new file mode 100644 index 0000000..40107ce --- /dev/null +++ b/src/game/hexWorld/events/TurnChangedEvent.h @@ -0,0 +1,15 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_TURNCHANGEDEVENT_H +#define DICEWARS_SIEDLER_TURNCHANGEDEVENT_H + + +class TurnChangedEvent { +public: + int newTurn; +}; + + +#endif //DICEWARS_SIEDLER_TURNCHANGEDEVENT_H \ No newline at end of file diff --git a/src/game/hexWorld/gameplay/TurnState.h b/src/game/hexWorld/gameplay/TurnState.h new file mode 100644 index 0000000..6e48f99 --- /dev/null +++ b/src/game/hexWorld/gameplay/TurnState.h @@ -0,0 +1,12 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_TURNSTATE_H +#define DICEWARS_SIEDLER_TURNSTATE_H + +struct TurnState { + int currentTurn = 1; +}; + +#endif //DICEWARS_SIEDLER_TURNSTATE_H \ No newline at end of file diff --git a/src/game/hexWorld/gameplay/TurnSystem.cpp b/src/game/hexWorld/gameplay/TurnSystem.cpp new file mode 100644 index 0000000..e121993 --- /dev/null +++ b/src/game/hexWorld/gameplay/TurnSystem.cpp @@ -0,0 +1,13 @@ +// +// Created by sebastian on 13.02.26. +// + +#include "TurnSystem.h" + +#include "../events/TurnChangedEvent.h" + +void TurnSystem::nextTurn(TurnState &turn, EventBus &events) { + turn.currentTurn++; + + events.emit(TurnChangedEvent{turn.currentTurn}); +} diff --git a/src/game/hexWorld/gameplay/TurnSystem.h b/src/game/hexWorld/gameplay/TurnSystem.h new file mode 100644 index 0000000..4b7dfdd --- /dev/null +++ b/src/game/hexWorld/gameplay/TurnSystem.h @@ -0,0 +1,18 @@ +// +// Created by sebastian on 13.02.26. +// + +#ifndef DICEWARS_SIEDLER_TURNSYSTEM_H +#define DICEWARS_SIEDLER_TURNSYSTEM_H +#include "TurnState.h" +#include "../../../engine/core/ECS/EntityManager.h" +#include "../../../engine/core/events/EventBus.h" + + +class TurnSystem { +public: + void nextTurn(TurnState& turn, EventBus& events); +}; + + +#endif //DICEWARS_SIEDLER_TURNSYSTEM_H \ No newline at end of file