ADD: Spawn Pawns

This commit is contained in:
sebastian 2026-08-02 20:11:05 +02:00
parent c82fc49aac
commit 9bce759259
11 changed files with 120 additions and 22 deletions

View File

@ -205,6 +205,8 @@ add_executable(ColorRace
game/src/ludo/LudoGameMode.h game/src/ludo/LudoGameMode.h
game/src/ludo/BoardLayout.cpp game/src/ludo/BoardLayout.cpp
game/src/ludo/BoardLayout.h game/src/ludo/BoardLayout.h
game/src/ludo/PiecePresenter.cpp
game/src/ludo/PiecePresenter.h
) )

View File

@ -23,10 +23,7 @@ void GameLayer::onAttachImpl() {
m_renderer = std::make_unique<engine::MeshRenderer>(); m_renderer = std::make_unique<engine::MeshRenderer>();
m_cameraController = std::make_unique<engine::CameraController>(getInputStack(), getInputContext()); m_cameraController = std::make_unique<engine::CameraController>(getInputStack(), getInputContext());
m_piecePresenter.spawnPieces(m_gameMode->getState());
for (int i = 0; i <= 3; i++) {
std::cout << glm::to_string( m_boardLayout.getWorldPosition(ludo::PlayerColor::Red, ludo::PieceState::AtHome, i)) << std::endl;
}
} }
void GameLayer::onDetachImpl() { void GameLayer::onDetachImpl() {

View File

@ -10,17 +10,18 @@
#include "ecs/EntityRegistry.h" #include "ecs/EntityRegistry.h"
#include "layer/Layer.h" #include "layer/Layer.h"
#include "ludo/BoardLayout.h" #include "ludo/BoardLayout.h"
#include "ludo/PiecePresenter.h"
#include "renderer/MeshRenderer.h" #include "renderer/MeshRenderer.h"
#include "renderer/RenderQueue.h" #include "renderer/RenderQueue.h"
#include "utils/openglWrapper/GLRenderState.h" #include "utils/openglWrapper/GLRenderState.h"
#include "ludo/LudoGameMode.h"
class GameLayer: public engine::Layer { class GameLayer: public engine::Layer {
public: public:
GameLayer(engine::EntityRegistry& entityRegistry, std::shared_ptr<engine::Camera> cam, std::shared_ptr<engine::PointLight> light, GameLayer(std::shared_ptr<ludo::LudoGameMode> gameMode, engine::EntityRegistry& entityRegistry, std::shared_ptr<engine::Camera> cam, std::shared_ptr<engine::PointLight> light,
engine::Keyboard& keyboard, engine::Mouse& mouse, std::shared_ptr<engine::Model> boardModel) engine::Keyboard& keyboard, engine::Mouse& mouse, std::shared_ptr<engine::Model> boardModel, std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModdels)
: Layer(keyboard, mouse), m_entityRegistry(entityRegistry), m_camera(std::move(cam)), m_renderer(std::make_unique<engine::MeshRenderer>()), : Layer(keyboard, mouse), m_gameMode(std::move(gameMode)), m_entityRegistry(entityRegistry), m_camera(std::move(cam)), m_renderer(std::make_unique<engine::MeshRenderer>()),
m_pointLight(std::move(light)), m_boardLayout(std::move(boardModel)){} m_pointLight(std::move(light)), m_boardLayout(std::move(boardModel)), m_piecePresenter(m_entityRegistry, std::move(pieceModdels), m_boardLayout){}
void onUpdate(float deltaTime) override; void onUpdate(float deltaTime) override;
void onRender() override; void onRender() override;
@ -37,6 +38,10 @@ private:
std::unique_ptr<engine::CameraController> m_cameraController; std::unique_ptr<engine::CameraController> m_cameraController;
ludo::BoardLayout m_boardLayout; ludo::BoardLayout m_boardLayout;
ludo::PiecePresenter m_piecePresenter;
engine::PlayerID m_localPlayer = 0;
std::shared_ptr<ludo::LudoGameMode> m_gameMode;
}; };
#endif //COLORRACE_GAMELAYER_H #endif //COLORRACE_GAMELAYER_H

View File

@ -11,6 +11,8 @@
GameScene::GameScene(engine::InputContextStack& inputStack, engine::Keyboard& keyboard, engine::Mouse& mouse) : Scene(inputStack, keyboard, mouse), m_camera(std::make_unique<engine::Camera>()) { GameScene::GameScene(engine::InputContextStack& inputStack, engine::Keyboard& keyboard, engine::Mouse& mouse) : Scene(inputStack, keyboard, mouse), m_camera(std::make_unique<engine::Camera>()) {
m_pointLight = std::make_shared<engine::PointLight>(glm::vec3(.0f, 10.f, -5.0f), glm::vec3(1.0f, 1.0f, 1.0f)); m_pointLight = std::make_shared<engine::PointLight>(glm::vec3(.0f, 10.f, -5.0f), glm::vec3(1.0f, 1.0f, 1.0f));
const std::vector<unsigned int> players = {0,1,2,3};
m_gameMode = std::make_shared<ludo::LudoGameMode>(players);
} }
void GameScene::onEnter() { void GameScene::onEnter() {
@ -20,8 +22,6 @@ void GameScene::onEnter() {
m_camera->setYaw(0.0f); m_camera->setYaw(0.0f);
m_camera->setPitch(0.0f); m_camera->setPitch(0.0f);
if (assetManager->hasModel("pawn")) {
const auto gameboardModel = assetManager->getModel("gameboard"); const auto gameboardModel = assetManager->getModel("gameboard");
const auto gameboardEntity = entityRegistry.createEntity(); const auto gameboardEntity = entityRegistry.createEntity();
@ -29,9 +29,14 @@ void GameScene::onEnter() {
const auto mesh = engine::MeshComponent(gameboardModel); const auto mesh = engine::MeshComponent(gameboardModel);
entityRegistry.addComponent<engine::TransformComponent>(gameboardEntity, transform); entityRegistry.addComponent<engine::TransformComponent>(gameboardEntity, transform);
entityRegistry.addComponent<engine::MeshComponent>(gameboardEntity, mesh); entityRegistry.addComponent<engine::MeshComponent>(gameboardEntity, mesh);
}
addLayer(std::make_unique<GameLayer>(entityRegistry, m_camera, m_pointLight, m_keyboard, m_mouse, assetManager->getModel("gameboard"))); std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModels;
pieceModels["Red"] = assetManager->getModel("pawn_red");
pieceModels["Blue"] = assetManager->getModel("pawn_blue");
pieceModels["Green"] = assetManager->getModel("pawn_green");
pieceModels["Yellow"] = assetManager->getModel("pawn_yellow");
addLayer(std::make_unique<GameLayer>(m_gameMode, entityRegistry, m_camera, m_pointLight, m_keyboard, m_mouse, assetManager->getModel("gameboard"), pieceModels));
} }
void GameScene::onExit() { void GameScene::onExit() {
@ -40,7 +45,10 @@ void GameScene::onExit() {
std::vector<engine::AssetRequest> GameScene::getRequiredAssets() const { std::vector<engine::AssetRequest> GameScene::getRequiredAssets() const {
std::vector<engine::AssetRequest> requests; std::vector<engine::AssetRequest> requests;
requests.emplace_back(engine::ModelRequest{"pawn", "assets/models/chess.obj", engine::ModelSplitPolicy::Combined}); requests.emplace_back(engine::ModelRequest{"pawn_red", "assets/models/chess_red.obj", engine::ModelSplitPolicy::Combined});
requests.emplace_back(engine::ModelRequest{"pawn_blue", "assets/models/chess_blue.obj", engine::ModelSplitPolicy::Combined});
requests.emplace_back(engine::ModelRequest{"pawn_green", "assets/models/chess_green.obj", engine::ModelSplitPolicy::Combined});
requests.emplace_back(engine::ModelRequest{"pawn_yellow", "assets/models/chess_yellow.obj", engine::ModelSplitPolicy::Combined});
requests.emplace_back(engine::ModelRequest{ "gameboard", "assets/models/GameBoard.obj", engine::ModelSplitPolicy::Combined}); requests.emplace_back(engine::ModelRequest{ "gameboard", "assets/models/GameBoard.obj", engine::ModelSplitPolicy::Combined});
return requests; return requests;
} }

View File

@ -5,6 +5,7 @@
#ifndef COLORRACE_GAMESCENE_H #ifndef COLORRACE_GAMESCENE_H
#define COLORRACE_GAMESCENE_H #define COLORRACE_GAMESCENE_H
#include "layer/Scene.h" #include "layer/Scene.h"
#include "ludo/LudoGameMode.h"
#include "renderer/entities/PointLight.h" #include "renderer/entities/PointLight.h"
@ -17,6 +18,7 @@ public:
private: private:
std::shared_ptr<engine::Camera> m_camera; std::shared_ptr<engine::Camera> m_camera;
std::shared_ptr<engine::PointLight> m_pointLight; std::shared_ptr<engine::PointLight> m_pointLight;
std::shared_ptr<ludo::LudoGameMode> m_gameMode;
}; };

View File

@ -81,7 +81,7 @@ void ludo::LudoGameMode::handle(const RollDiceCommand &command) {
} }
} }
ludo::PlayerColor ludo::LudoGameMode::getColorOf(engine::PlayerID player) { ludo::PlayerColor ludo::LudoGameMode::getColorOf(engine::PlayerID player) const {
const auto& order = getPlayerOrder(); const auto& order = getPlayerOrder();
auto it = std::find(order.begin(), order.end(), player); auto it = std::find(order.begin(), order.end(), player);
assert(it != order.end() && "getColorOf mit unregistrierter PlayerID aufgerufen"); assert(it != order.end() && "getColorOf mit unregistrierter PlayerID aufgerufen");

View File

@ -14,7 +14,8 @@
namespace ludo { namespace ludo {
class LudoGameMode: public engine::TurnBasedGameMode<LudoCommand, LudoEvent, LudoGameState> { class LudoGameMode: public engine::TurnBasedGameMode<LudoCommand, LudoEvent, LudoGameState> {
public: public:
explicit LudoGameMode(std::vector<engine::PlayerID> players, std::optional<unsigned int> seed = std::nullopt) : TurnBasedGameMode(std::move(players)), m_rng(seed.value_or(std::random_device{}())) {} explicit LudoGameMode(std::vector<engine::PlayerID> players, std::optional<unsigned int> seed = std::nullopt) : TurnBasedGameMode(std::move(players)),
m_rng(seed.value_or(std::random_device{}())), m_gameState(getPlayerOrder()) {}
void sendCommand(const std::variant<MovePieceCommand, RollDiceCommand> &command) override; void sendCommand(const std::variant<MovePieceCommand, RollDiceCommand> &command) override;
std::vector<LudoEvent> pollEvents() override; std::vector<LudoEvent> pollEvents() override;
@ -32,7 +33,7 @@ namespace ludo {
void handle(const RollDiceCommand &command); void handle(const RollDiceCommand &command);
PlayerColor getColorOf(engine::PlayerID playerID); [[nodiscard]] PlayerColor getColorOf(engine::PlayerID playerID) const;
void handle(const MovePieceCommand &command); void handle(const MovePieceCommand &command);
void finishTurn(); void finishTurn();

View File

@ -13,6 +13,15 @@
namespace ludo { namespace ludo {
class LudoGameState: public engine::GameState { class LudoGameState: public engine::GameState {
public: public:
explicit LudoGameState(const std::vector<engine::PlayerID>& playerIDs) {
for (const auto& playerID : playerIDs) {
PlayerColor playerColor = getColorOf(playerID, playerIDs);
for (int i = 0; i < 4; i++) {
auto piece = Piece(playerColor, PieceState::AtHome, i);
m_pieces.push_back(piece);
}
}
};
[[nodiscard]] const std::vector<Piece> &getPieces() const; [[nodiscard]] const std::vector<Piece> &getPieces() const;
[[nodiscard]] int getDiceValue() const; [[nodiscard]] int getDiceValue() const;
[[nodiscard]] TurnPhase getPhase() const; [[nodiscard]] TurnPhase getPhase() const;

View File

@ -4,6 +4,9 @@
#ifndef COLORRACE_LUDOTYPES_H #ifndef COLORRACE_LUDOTYPES_H
#define COLORRACE_LUDOTYPES_H #define COLORRACE_LUDOTYPES_H
#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint> #include <cstdint>
#include <variant> #include <variant>
@ -36,6 +39,18 @@ namespace ludo {
return "Unknown"; return "Unknown";
} }
constexpr std::array<PlayerColor, static_cast<size_t>(PlayerColor::Count)> PlayerColors = {
PlayerColor::Red,
PlayerColor::Blue,
PlayerColor::Yellow,
PlayerColor::Green
};
static PlayerColor getColorOf(engine::PlayerID player, std::vector<engine::PlayerID> playerOrder) {
auto it = std::find(playerOrder.begin(), playerOrder.end(), player);
assert(it != playerOrder.end() && "getColorOf mit unregistrierter PlayerID aufgerufen");
return static_cast<PlayerColor>(std::distance(playerOrder.begin(), it));
}
enum class PieceState : uint8_t { AtHome, OnTrack, InHomeStretch, Finished }; enum class PieceState : uint8_t { AtHome, OnTrack, InHomeStretch, Finished };
enum class TurnPhase : uint8_t { AwaitingRoll, AwaitingPieceSelection }; enum class TurnPhase : uint8_t { AwaitingRoll, AwaitingPieceSelection };

View File

@ -0,0 +1,28 @@
//
// Created by sebastian on 02.08.26.
//
#include "PiecePresenter.h"
#include "ecs/standardComponents/MeshComponent.h"
#include "ecs/standardComponents/TransformComponent.h"
void ludo::PiecePresenter::spawnPieces(const ludo::LudoGameState &state) {
for (const auto& piece : state.getPieces()) {
auto entity = m_registry.createEntity();
const auto transform = engine::TransformComponent(
m_layout.getWorldPosition(piece.color, piece.state, piece.position),
{0,0,0},
{0.334296f, 0.334296f, 0.334296f});
m_registry.addComponent<engine::TransformComponent>(entity, transform);
m_registry.addComponent<engine::MeshComponent>(entity, engine::MeshComponent(m_pieceModels[std::string(ludo::toString(piece.color))]));
}
}
void ludo::PiecePresenter::onPieceMoved(const ludo::PieceMovedEvent &event, const ludo::LudoGameState &state) {
const auto& piece = state.getPieces()[event.pieceIndex];
auto target = m_layout.getWorldPosition(piece.color, piece.state, piece.position);
auto entity = m_pieceEntities[event.pieceIndex];
auto& transform = m_registry.getComponent<engine::TransformComponent>(entity);
transform.m_position = target;
}

View File

@ -0,0 +1,31 @@
//
// Created by sebastian on 02.08.26.
//
#ifndef COLORRACE_PIECEPRESENTER_H
#define COLORRACE_PIECEPRESENTER_H
#include "BoardLayout.h"
#include "LudoGameState.h"
#include "ecs/EntityRegistry.h"
#include "loader/assets/AssetManager.h"
#include "loader/models/Model.h"
namespace ludo {
class PiecePresenter {
public:
PiecePresenter(engine::EntityRegistry& registry, std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModels, BoardLayout& layout)
: m_registry(registry), m_pieceModels(std::move(pieceModels)), m_layout(layout) {}
void spawnPieces(const ludo::LudoGameState& state);
void onPieceMoved(const ludo::PieceMovedEvent& event, const ludo::LudoGameState& state);
private:
engine::EntityRegistry& m_registry;
std::unordered_map<std::string, std::shared_ptr<engine::Model>> m_pieceModels;
BoardLayout& m_layout;
std::vector<engine::Entity> m_pieceEntities;
};
}
#endif //COLORRACE_PIECEPRESENTER_H