ADD: Basic AI
This commit is contained in:
parent
c6d1fd8910
commit
bb29a1d3f1
@ -212,6 +212,8 @@ add_executable(ColorRace
|
|||||||
game/src/ludo/BoardLayout.h
|
game/src/ludo/BoardLayout.h
|
||||||
game/src/ludo/PiecePresenter.cpp
|
game/src/ludo/PiecePresenter.cpp
|
||||||
game/src/ludo/PiecePresenter.h
|
game/src/ludo/PiecePresenter.h
|
||||||
|
game/src/ludo/LudoAiController.cpp
|
||||||
|
game/src/ludo/LudoAiController.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -18,11 +18,12 @@ namespace engine {
|
|||||||
explicit TurnBasedGameMode(std::vector<PlayerID> playerOrder) : m_playerOrder(std::move(playerOrder)) {}
|
explicit TurnBasedGameMode(std::vector<PlayerID> playerOrder) : m_playerOrder(std::move(playerOrder)) {}
|
||||||
[[nodiscard]] PlayerID getCurrentPlayer() const { return m_playerOrder[m_currentPlayerIndex]; }
|
[[nodiscard]] PlayerID getCurrentPlayer() const { return m_playerOrder[m_currentPlayerIndex]; }
|
||||||
[[nodiscard]] bool isCurrentPlayer(PlayerID playerID) const { return getCurrentPlayer() == playerID; }
|
[[nodiscard]] bool isCurrentPlayer(PlayerID playerID) const { return getCurrentPlayer() == playerID; }
|
||||||
|
[[nodiscard]] std::vector<PlayerID> getPlayerOrder() const { return m_playerOrder; }
|
||||||
protected:
|
protected:
|
||||||
void endTurn(bool extraTurn = false) {
|
void endTurn(bool extraTurn = false) {
|
||||||
if (!extraTurn) m_currentPlayerIndex = (m_currentPlayerIndex + 1) % m_playerOrder.size();
|
if (!extraTurn) m_currentPlayerIndex = (m_currentPlayerIndex + 1) % m_playerOrder.size();
|
||||||
}
|
}
|
||||||
std::vector<PlayerID> getPlayerOrder() const { return m_playerOrder; }
|
|
||||||
private:
|
private:
|
||||||
std::vector<PlayerID> m_playerOrder;
|
std::vector<PlayerID> m_playerOrder;
|
||||||
size_t m_currentPlayerIndex = 0;
|
size_t m_currentPlayerIndex = 0;
|
||||||
|
|||||||
@ -56,6 +56,9 @@ void GameLayer::renderHud() {
|
|||||||
void GameLayer::onUpdate(float deltaTime) {
|
void GameLayer::onUpdate(float deltaTime) {
|
||||||
Layer::onUpdate(deltaTime);
|
Layer::onUpdate(deltaTime);
|
||||||
m_cameraController->update(getKeyboard(), *m_camera, deltaTime);
|
m_cameraController->update(getKeyboard(), *m_camera, deltaTime);
|
||||||
|
for (auto& ai : aiControllers) {
|
||||||
|
ai.update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& event : m_gameMode->pollEvents()) {
|
for (const auto& event : m_gameMode->pollEvents()) {
|
||||||
std::visit([this]<typename T>(const T& e) {
|
std::visit([this]<typename T>(const T& e) {
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "ecs/systems/PickingSystem.h"
|
#include "ecs/systems/PickingSystem.h"
|
||||||
#include "layer/Layer.h"
|
#include "layer/Layer.h"
|
||||||
#include "ludo/BoardLayout.h"
|
#include "ludo/BoardLayout.h"
|
||||||
|
#include "ludo/LudoAiController.h"
|
||||||
#include "ludo/PiecePresenter.h"
|
#include "ludo/PiecePresenter.h"
|
||||||
#include "renderer/MeshRenderer.h"
|
#include "renderer/MeshRenderer.h"
|
||||||
#include "renderer/RenderQueue.h"
|
#include "renderer/RenderQueue.h"
|
||||||
@ -23,7 +24,13 @@ public:
|
|||||||
engine::Keyboard& keyboard, engine::Mouse& mouse, std::shared_ptr<engine::Model> boardModel, std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModdels)
|
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_gameMode(std::move(gameMode)), 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_piecePresenter(m_entityRegistry, std::move(pieceModdels), m_boardLayout),
|
m_pointLight(std::move(light)), m_boardLayout(std::move(boardModel)), m_piecePresenter(m_entityRegistry, std::move(pieceModdels), m_boardLayout),
|
||||||
m_pickingSystem(*m_camera){}
|
m_pickingSystem(*m_camera) {
|
||||||
|
for (auto playerID : m_gameMode->getPlayerOrder()) {
|
||||||
|
if (playerID != m_localPlayer) {
|
||||||
|
aiControllers.emplace_back(m_gameMode, playerID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onUpdate(float deltaTime) override;
|
void onUpdate(float deltaTime) override;
|
||||||
void onRender() override;
|
void onRender() override;
|
||||||
@ -46,6 +53,8 @@ private:
|
|||||||
engine::PickingSystem m_pickingSystem;
|
engine::PickingSystem m_pickingSystem;
|
||||||
std::string m_lastEventMessage;
|
std::string m_lastEventMessage;
|
||||||
|
|
||||||
|
std::vector<ludo::LudoAiController> aiControllers;
|
||||||
|
|
||||||
void renderHud();
|
void renderHud();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
59
game/src/ludo/LudoAiController.cpp
Normal file
59
game/src/ludo/LudoAiController.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 02.08.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "LudoAiController.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
ludo::LudoAiController::LudoAiController(std::shared_ptr<LudoGameMode> gameMode, engine::PlayerID player) : m_gameMode(std::move(gameMode)), m_player(player){
|
||||||
|
}
|
||||||
|
|
||||||
|
void ludo::LudoAiController::update(float deltaTime) {
|
||||||
|
if (m_gameMode->getCurrentPlayer() != m_player) {
|
||||||
|
m_thinkTimer = 0.0f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_thinkTimer += deltaTime;
|
||||||
|
std::cout << "Thinking..." << std::endl;
|
||||||
|
|
||||||
|
if (m_thinkTimer < kThinkDelay) return;
|
||||||
|
std::cout << "Thinking done" << std::endl;
|
||||||
|
m_thinkTimer = 0.0f;
|
||||||
|
|
||||||
|
switch (m_gameMode->getState().getPhase()) {
|
||||||
|
case TurnPhase::AwaitingRoll:
|
||||||
|
m_gameMode->sendCommand(RollDiceCommand{m_player});
|
||||||
|
break;
|
||||||
|
case TurnPhase::AwaitingPieceSelection:
|
||||||
|
if (auto pieceIndex = chooseMove()) {
|
||||||
|
m_gameMode->sendCommand(MovePieceCommand{m_player, *pieceIndex});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<int> ludo::LudoAiController::chooseMove() const {
|
||||||
|
auto color = m_gameMode->getColorOf(m_player);
|
||||||
|
auto moveable = m_gameMode->getMoveablePieceIndices(color, m_gameMode->getState().getDiceValue());
|
||||||
|
if (moveable.empty()) return std::nullopt;
|
||||||
|
|
||||||
|
int diceValue = m_gameMode->getState().getDiceValue();
|
||||||
|
|
||||||
|
//Priority 1: Schmeißen
|
||||||
|
for (int idx : moveable) {
|
||||||
|
if (m_gameMode->wouldCapture(idx, diceValue).has_value()) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int idx : moveable) {
|
||||||
|
if (m_gameMode->getState().getPieces()[idx].state == PieceState::AtHome) return idx;
|
||||||
|
}
|
||||||
|
// Fallback: erste bewegbare Figur
|
||||||
|
return moveable.front();
|
||||||
|
}
|
||||||
28
game/src/ludo/LudoAiController.h
Normal file
28
game/src/ludo/LudoAiController.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 02.08.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COLORRACE_LUDOAICONTROLLER_H
|
||||||
|
#define COLORRACE_LUDOAICONTROLLER_H
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "LudoGameMode.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace ludo {
|
||||||
|
class LudoAiController {
|
||||||
|
public:
|
||||||
|
LudoAiController(std::shared_ptr<LudoGameMode> gameMode, engine::PlayerID player);
|
||||||
|
void update(float deltaTime);
|
||||||
|
private:
|
||||||
|
static constexpr float kThinkDelay = 0.8f;
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<int> chooseMove() const;
|
||||||
|
std::shared_ptr<LudoGameMode> m_gameMode;
|
||||||
|
engine::PlayerID m_player;
|
||||||
|
float m_thinkTimer = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //COLORRACE_LUDOAICONTROLLER_H
|
||||||
@ -17,37 +17,50 @@ std::vector<ludo::LudoEvent> ludo::LudoGameMode::pollEvents() {
|
|||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
ludo::LudoGameMode::MoveResult ludo::LudoGameMode::movePieceInternal(int pieceIndex, int diceValue) {
|
[[nodiscard]] std::optional<ludo::LudoGameMode::Destination> ludo::LudoGameMode::computeDestination(const Piece &piece, int diceValue) const {
|
||||||
Piece& piece = m_gameState.m_pieces[pieceIndex];
|
|
||||||
int fromPosition = piece.position;
|
|
||||||
|
|
||||||
switch (piece.state) {
|
switch (piece.state) {
|
||||||
case PieceState::AtHome: {
|
case PieceState::AtHome:
|
||||||
piece.state = PieceState::OnTrack;
|
return Destination{PieceState::OnTrack, getEntryOffset(piece.color)};
|
||||||
piece.position = getEntryOffset(piece.color);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PieceState::OnTrack: {
|
case PieceState::OnTrack: {
|
||||||
int distanceTraveled = (piece.position - getEntryOffset(piece.color) + kTrackLength) % kTrackLength;
|
int distanceTraveled = (piece.position - getEntryOffset(piece.color) + kTrackLength) % kTrackLength;
|
||||||
int newDistance = distanceTraveled + diceValue;
|
int newDistance = distanceTraveled + diceValue;
|
||||||
if (newDistance <= kTrackLength - 1) {
|
if (newDistance <= kTrackLength - 1) {
|
||||||
piece.position = (piece.position + diceValue) % kTrackLength;
|
return Destination{PieceState::OnTrack, (piece.position + diceValue) % kTrackLength};
|
||||||
} else {
|
}
|
||||||
int homeIndex = newDistance - kTrackLength;
|
int homeIndex = newDistance - kTrackLength;
|
||||||
piece.state = PieceState::InHomeStretch;
|
if (homeIndex > kHomeStretchLength - 1) return std::nullopt; // überzählig
|
||||||
piece.position = homeIndex;
|
return Destination{homeIndex == kHomeStretchLength - 1 ? PieceState::Finished : PieceState::InHomeStretch, homeIndex};
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case PieceState::InHomeStretch: {
|
case PieceState::InHomeStretch: {
|
||||||
piece.position += diceValue;
|
int newIndex = piece.position + diceValue;
|
||||||
if (piece.position == kHomeStretchLength - 1) {
|
if (newIndex > kHomeStretchLength - 1) return std::nullopt; // überzählig
|
||||||
piece.state = PieceState::Finished;
|
return Destination{newIndex == kHomeStretchLength - 1 ? PieceState::Finished : PieceState::InHomeStretch, newIndex};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case PieceState::Finished:
|
case PieceState::Finished:
|
||||||
break;
|
return std::nullopt; // nie bewegbar
|
||||||
}
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<int> ludo::LudoGameMode::findLowestHomeSlotPiece(PlayerColor color) const {
|
||||||
|
for (int i = 0; i < static_cast<int>(m_gameState.m_pieces.size()); ++i) {
|
||||||
|
const auto& piece = m_gameState.m_pieces[i];
|
||||||
|
if (piece.color == color && piece.state == PieceState::AtHome) {
|
||||||
|
return i; // erste Übereinstimmung = kleinster Home-Slot, dank Erzeugungsreihenfolge
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ludo::LudoGameMode::MoveResult ludo::LudoGameMode::movePieceInternal(int pieceIndex, int diceValue) {
|
||||||
|
Piece& piece = m_gameState.m_pieces[pieceIndex];
|
||||||
|
int fromPosition = piece.position;
|
||||||
|
|
||||||
|
Destination destination = computeDestination(piece, diceValue).value();
|
||||||
|
piece.state = destination.state;
|
||||||
|
piece.position = destination.position;
|
||||||
|
|
||||||
MoveResult result{fromPosition, piece.position, false, -1};
|
MoveResult result{fromPosition, piece.position, false, -1};
|
||||||
|
|
||||||
@ -68,12 +81,30 @@ ludo::LudoGameMode::MoveResult ludo::LudoGameMode::movePieceInternal(int pieceIn
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ludo::LudoGameMode::autoReleasePiece(int pieceIndex) {
|
||||||
|
auto result = movePieceInternal(pieceIndex, m_gameState.getDiceValue());
|
||||||
|
m_pendingEvents.emplace_back(PieceMovedEvent{pieceIndex, result.fromPosition, result.toPosition, result.captured});
|
||||||
|
if (result.captured) {
|
||||||
|
m_pendingEvents.emplace_back(PieceMovedEvent{result.capturedPieceIndex, result.toPosition, -1, false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ludo::LudoGameMode::handle(const RollDiceCommand &command) {
|
void ludo::LudoGameMode::handle(const RollDiceCommand &command) {
|
||||||
if (!isCurrentPlayer(command.player) || m_gameState.m_phase != TurnPhase::AwaitingRoll) return;
|
if (!isCurrentPlayer(command.player) || m_gameState.m_phase != TurnPhase::AwaitingRoll) return;
|
||||||
|
|
||||||
m_gameState.m_diceValue = rollDice();
|
m_gameState.m_diceValue = rollDice();
|
||||||
m_pendingEvents.emplace_back(DiceRolledEvent(command.player, m_gameState.m_diceValue));
|
m_pendingEvents.emplace_back(DiceRolledEvent(command.player, m_gameState.m_diceValue));
|
||||||
|
|
||||||
|
if (m_gameState.m_diceValue == 6) {
|
||||||
|
if (auto homeIndex = findLowestHomeSlotPiece(getColorOf(command.player))) {
|
||||||
|
if (!isBlockedByOwnPiece(getColorOf(command.player), PieceState::OnTrack, getEntryOffset(getColorOf(command.player)))) {
|
||||||
|
autoReleasePiece(*homeIndex);
|
||||||
|
finishTurn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (getMoveablePieceIndices(getColorOf(command.player), m_gameState.m_diceValue).empty()) {
|
if (getMoveablePieceIndices(getColorOf(command.player), m_gameState.m_diceValue).empty()) {
|
||||||
finishTurn(); // kein gültiger zug, sofort weitergeben
|
finishTurn(); // kein gültiger zug, sofort weitergeben
|
||||||
} else {
|
} else {
|
||||||
@ -120,46 +151,38 @@ std::vector<int> ludo::LudoGameMode::getMoveablePieceIndices(PlayerColor color,
|
|||||||
const Piece& piece = m_gameState.getPieces()[i];
|
const Piece& piece = m_gameState.getPieces()[i];
|
||||||
if (piece.color != color) continue;
|
if (piece.color != color) continue;
|
||||||
|
|
||||||
switch (piece.state) {
|
Destination dest = computeDestination(piece, diceValue).value();
|
||||||
case PieceState::AtHome: {
|
|
||||||
if (diceValue == 6 && !isBlockedByOwnPiece(color, PieceState::OnTrack, getEntryOffset(color))) {
|
|
||||||
moveablePieceIndices.push_back(i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PieceState::OnTrack: {
|
|
||||||
int distanceTraveled = (piece.position - getEntryOffset(color)) + kTrackLength;
|
|
||||||
int newDistance = distanceTraveled + diceValue;
|
|
||||||
|
|
||||||
if (newDistance <= kTrackLength - 1) {
|
// Überschuss in der Zielgeraden abfangen: computeDestination liefert bei Überschuss
|
||||||
int newPos = (piece.position + diceValue) % kTrackLength;
|
// aktuell denselben Zustand zurück, wie unten in computeDestination definiert
|
||||||
if (!isBlockedByOwnPiece(color, PieceState::OnTrack, newPos)) {
|
if (piece.state == PieceState::InHomeStretch && dest.position > kHomeStretchLength - 1) continue;
|
||||||
moveablePieceIndices.push_back(i);
|
|
||||||
}
|
|
||||||
} else if (newDistance <= kTrackLength - 1 + kHomeStretchLength){
|
|
||||||
int homeIndex = newDistance - kTrackLength;
|
|
||||||
if (!isBlockedByOwnPiece(color, PieceState::InHomeStretch, homeIndex)) {
|
|
||||||
moveablePieceIndices.push_back(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// sonst: Wurf zu hoch, Figur kann sich nicht "totlaufen" -> nicht bewegbar
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PieceState::InHomeStretch: {
|
|
||||||
int newIndex = piece.position + diceValue;
|
|
||||||
if (newIndex <= kHomeStretchLength - 1 && !isBlockedByOwnPiece(color, PieceState::Finished, newIndex)) {
|
|
||||||
moveablePieceIndices.push_back(i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PieceState::Finished:
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
if (piece.state == PieceState::AtHome && diceValue != 6) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isBlockedByOwnPiece(color, dest.state, dest.position)) {
|
||||||
|
moveablePieceIndices.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return moveablePieceIndices;
|
return moveablePieceIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<int> ludo::LudoGameMode::wouldCapture(int pieceIndex, int diceValue) const {
|
||||||
|
const auto& piece = m_gameState.m_pieces[pieceIndex];
|
||||||
|
auto dest = computeDestination(piece, diceValue);
|
||||||
|
if (dest.value().state != PieceState::OnTrack) return std::nullopt;
|
||||||
|
|
||||||
|
for (int i = 0; i < static_cast<int>(m_gameState.m_pieces.size()); ++i) {
|
||||||
|
if (i == pieceIndex) continue;
|
||||||
|
const auto& other = m_gameState.m_pieces[i];
|
||||||
|
if (other.color != piece.color && other.state == PieceState::OnTrack && other.position == dest.value().position) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ludo::LudoGameMode::rollDice() {
|
int ludo::LudoGameMode::rollDice() {
|
||||||
std::uniform_int_distribution<int> distribution(1, 6);
|
std::uniform_int_distribution<int> distribution(1, 6);
|
||||||
|
|||||||
@ -22,6 +22,9 @@ namespace ludo {
|
|||||||
|
|
||||||
[[nodiscard]] const LudoGameState& getState() const override { return m_gameState; }
|
[[nodiscard]] const LudoGameState& getState() const override { return m_gameState; }
|
||||||
[[nodiscard]] PlayerColor getColorOf(engine::PlayerID playerID) const;
|
[[nodiscard]] PlayerColor getColorOf(engine::PlayerID playerID) const;
|
||||||
|
|
||||||
|
std::vector<int> getMoveablePieceIndices(PlayerColor color, int diceValue) const;
|
||||||
|
std::optional<int> wouldCapture(int pieceIndex, int diceValue) const;
|
||||||
private:
|
private:
|
||||||
struct MoveResult {
|
struct MoveResult {
|
||||||
int fromPosition;
|
int fromPosition;
|
||||||
@ -30,7 +33,16 @@ namespace ludo {
|
|||||||
int capturedPieceIndex = -1;
|
int capturedPieceIndex = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Destination {
|
||||||
|
PieceState state;
|
||||||
|
int position;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<Destination> computeDestination(const Piece &piece, int diceValue) const;
|
||||||
|
[[nodiscard]] std::optional<int> findLowestHomeSlotPiece(PlayerColor color) const;
|
||||||
|
|
||||||
MoveResult movePieceInternal(int pieceIndex, int diceValue);
|
MoveResult movePieceInternal(int pieceIndex, int diceValue);
|
||||||
|
void autoReleasePiece(int pieceIndex);
|
||||||
|
|
||||||
void handle(const RollDiceCommand &command);
|
void handle(const RollDiceCommand &command);
|
||||||
|
|
||||||
@ -39,7 +51,6 @@ namespace ludo {
|
|||||||
void handle(const MovePieceCommand &command);
|
void handle(const MovePieceCommand &command);
|
||||||
void finishTurn();
|
void finishTurn();
|
||||||
|
|
||||||
std::vector<int> getMoveablePieceIndices(PlayerColor color, int diceValue) const;
|
|
||||||
|
|
||||||
LudoGameState m_gameState;
|
LudoGameState m_gameState;
|
||||||
std::vector<LudoEvent> m_pendingEvents;
|
std::vector<LudoEvent> m_pendingEvents;
|
||||||
|
|||||||
@ -18,6 +18,7 @@ void ludo::PiecePresenter::spawnPieces(const ludo::LudoGameState &state) {
|
|||||||
m_registry.addComponent<engine::TransformComponent>(entity, transform);
|
m_registry.addComponent<engine::TransformComponent>(entity, transform);
|
||||||
m_registry.addComponent<engine::MeshComponent>(entity, engine::MeshComponent(m_pieceModels[std::string(ludo::toString(piece.color))]));
|
m_registry.addComponent<engine::MeshComponent>(entity, engine::MeshComponent(m_pieceModels[std::string(ludo::toString(piece.color))]));
|
||||||
m_registry.addComponent<engine::PickableComponent>(entity, engine::PickableComponent(kPieceRadius));
|
m_registry.addComponent<engine::PickableComponent>(entity, engine::PickableComponent(kPieceRadius));
|
||||||
|
m_pieceEntities.push_back(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user