feat(players): suport del segon jugador amb events amb player_id
This commit is contained in:
1 parent
74dad71cc2
commit
4e9d5df872
21 files changed
+309
-49
No files matched your search
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "game/entities/event_bus.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -63,9 +64,15 @@ void Door::update(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
void Door::onPlayerContact(Player* /*player*/) {
|
||||
void Door::onPlayerContact(Player* player) {
|
||||
if (state_ != State::OPEN || level_complete_emitted_) { return; }
|
||||
if (bus_ != nullptr) { bus_->publish("level_complete"); }
|
||||
if (bus_ != nullptr) {
|
||||
bus_->publish(Event{
|
||||
.name = "level_complete",
|
||||
.payload = std::monostate{},
|
||||
.player_id = (player != nullptr) ? player->getId() : -1,
|
||||
});
|
||||
}
|
||||
level_complete_emitted_ = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "game/entities/event_bus.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
|
||||
FloorTrap::FloorTrap(const fkyaml::node& yaml) {
|
||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("floor_trap");
|
||||
@@ -21,9 +22,15 @@ FloorTrap::FloorTrap(const fkyaml::node& yaml) {
|
||||
}
|
||||
}
|
||||
|
||||
void FloorTrap::onPlayerContact(Player* /*player*/) {
|
||||
void FloorTrap::onPlayerContact(Player* player) {
|
||||
if (!isActive()) { return; }
|
||||
if (bus_ != nullptr) { bus_->publish("player_hit", getDamage()); }
|
||||
if (bus_ != nullptr) {
|
||||
bus_->publish(Event{
|
||||
.name = "player_hit",
|
||||
.payload = getDamage(),
|
||||
.player_id = (player != nullptr) ? player->getId() : -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_ENTITY("floor_trap", FloorTrap)
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "game/entities/event_bus.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
#include "game/map/map.hpp"
|
||||
|
||||
namespace {
|
||||
@@ -294,8 +295,14 @@ void Mummy::applyChoice(Direction dir) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mummy::onPlayerContact(Player* /*player*/) {
|
||||
if (bus_ != nullptr) { bus_->publish("player_hit", getDamage()); }
|
||||
void Mummy::onPlayerContact(Player* player) {
|
||||
if (bus_ != nullptr) {
|
||||
bus_->publish(Event{
|
||||
.name = "player_hit",
|
||||
.payload = getDamage(),
|
||||
.player_id = (player != nullptr) ? player->getId() : -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_ENTITY("mummy", Mummy)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "game/entities/event_bus.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
#include "game/map/map.hpp"
|
||||
|
||||
namespace {
|
||||
@@ -60,8 +61,14 @@ void RollingRock::step(float delta_time) {
|
||||
setDirection(0.0F, 0.0F);
|
||||
}
|
||||
|
||||
void RollingRock::onPlayerContact(Player* /*player*/) {
|
||||
if (bus_ != nullptr) { bus_->publish("player_hit", getDamage()); }
|
||||
void RollingRock::onPlayerContact(Player* player) {
|
||||
if (bus_ != nullptr) {
|
||||
bus_->publish(Event{
|
||||
.name = "player_hit",
|
||||
.payload = getDamage(),
|
||||
.player_id = (player != nullptr) ? player->getId() : -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_ENTITY("rolling_rock", RollingRock)
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "game/entities/event_bus.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
|
||||
WallTrap::WallTrap(const fkyaml::node& yaml) {
|
||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("wall_trap");
|
||||
@@ -21,9 +22,15 @@ WallTrap::WallTrap(const fkyaml::node& yaml) {
|
||||
}
|
||||
}
|
||||
|
||||
void WallTrap::onPlayerContact(Player* /*player*/) {
|
||||
void WallTrap::onPlayerContact(Player* player) {
|
||||
if (!isActive()) { return; }
|
||||
if (bus_ != nullptr) { bus_->publish("player_hit", getDamage()); }
|
||||
if (bus_ != nullptr) {
|
||||
bus_->publish(Event{
|
||||
.name = "player_hit",
|
||||
.payload = getDamage(),
|
||||
.player_id = (player != nullptr) ? player->getId() : -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_ENTITY("wall_trap", WallTrap)
|
||||
@@ -45,6 +45,11 @@ struct Event {
|
||||
std::string name;
|
||||
using Payload = std::variant<std::monostate, int, std::string, Entity*, TilePos, PaintedTile>;
|
||||
Payload payload;
|
||||
// Jugador que ha originat (o provocat) l'event. -1 = sense jugador
|
||||
// associat (events del món, com `sarcophagus_opened` des de la pròpia
|
||||
// entitat). Usat per al HUD (dispatch a P1/P2) i per a regles futures
|
||||
// de puntuació que atribueixin accions al jugador concret.
|
||||
int player_id{-1};
|
||||
};
|
||||
|
||||
class EventBus {
|
||||
|
||||
@@ -222,13 +222,19 @@ void Player::updateFacingAndTurn(float delta_time, float vx, float vy) {
|
||||
}
|
||||
}
|
||||
|
||||
Player::Player(const std::string& anim_key, float x, float y, const Controls& controls, const Map::Info& map_info, int paint_tile_index)
|
||||
Player::Player(const std::string& anim_key, int id, float x, float y, const Controls& controls, const Map::Info& map_info, int paint_tile_index)
|
||||
: AnimatedSprite(Resource::Cache::get().getAnimationData(anim_key)),
|
||||
id_(id),
|
||||
controls_(controls),
|
||||
map_(map_info),
|
||||
paint_tile_index_(paint_tile_index) {
|
||||
setPos(x, y);
|
||||
setCurrentAnimation("stand");
|
||||
// Postura inicial mirant cap al jugador (cara avall), no de costat:
|
||||
// forcem facing_ a DOWN i l'animació `stand_down` abans del primer
|
||||
// frame d'input — el primer `update` la preservarà si l'usuari no
|
||||
// prem cap tecla.
|
||||
facing_ = Facing::DOWN;
|
||||
setCurrentAnimation("stand_down");
|
||||
}
|
||||
|
||||
void Player::update(float delta_time) {
|
||||
@@ -308,7 +314,11 @@ void Player::update(float delta_time) {
|
||||
if (COL != last_tile_col_ || ROW != last_tile_row_) {
|
||||
last_tile_col_ = COL;
|
||||
last_tile_row_ = ROW;
|
||||
bus_->publish("on_tile_entered", PaintedTile{.col = COL, .row = ROW, .tile_index = paint_tile_index_});
|
||||
bus_->publish(Event{
|
||||
.name = "on_tile_entered",
|
||||
.payload = PaintedTile{.col = COL, .row = ROW, .tile_index = paint_tile_index_},
|
||||
.player_id = id_,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,16 @@ class Player : public AnimatedSprite {
|
||||
// Ha de cridar-se abans d'instanciar Player; GameScene ho fa al ctor.
|
||||
static void loadFrom(const std::string& yaml_path);
|
||||
|
||||
Player(const std::string& anim_key, float x, float y, const Controls& controls, const Map::Info& map_info, int paint_tile_index = -1);
|
||||
Player(const std::string& anim_key, int id, float x, float y, const Controls& controls, const Map::Info& map_info, int paint_tile_index = -1);
|
||||
|
||||
void update(float delta_time) override;
|
||||
|
||||
// Identificador local (0 = P1, 1 = P2…). S'usa als events del bus
|
||||
// perquè els consumidors (HUD, futures regles de puntuació) sàpiguen
|
||||
// quin jugador ha originat l'event. No té cap vinculació amb la
|
||||
// xarxa — és únic per dins del procés.
|
||||
[[nodiscard]] auto getId() const -> int { return id_; }
|
||||
|
||||
// Y de la base del jugador (cara inferior de la caixa de colisió). Usada
|
||||
// per al Z-order contra els sarcs: peus per sobre d'un sarc → darrere;
|
||||
// per sota → davant.
|
||||
@@ -104,6 +110,7 @@ class Player : public AnimatedSprite {
|
||||
float (Player::*get_pos)() const,
|
||||
void (Player::*set_pos)(float));
|
||||
|
||||
int id_{-1};
|
||||
Controls controls_;
|
||||
// Còpia plana de la geometria del mapa + punters a `collides`/
|
||||
// `inside_playfield`. POD trivial; copiada al ctor i no muta durant
|
||||
|
||||
Reference in new issue
Block a user