feat(entities): light_radius + getLightCenter a Entity i Player
This commit is contained in:
1 parent
68be8e55ec
commit
ebb161f1f5
5 files changed
+67
No files matched your search
@@ -63,6 +63,16 @@ auto Entity::getCollisionRect() const -> SDL_FRect {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Entity::getLightCenter() const -> SDL_FPoint {
|
||||||
|
// Centre del rect de render. Per a entitats que es desplacen
|
||||||
|
// visualment sobre la seva posició lògica (p.ex. el Player saltant),
|
||||||
|
// la subclasse override aquest mètode per restar el desplaçament.
|
||||||
|
return {
|
||||||
|
.x = pixel_rect_.x + (pixel_rect_.w * 0.5F),
|
||||||
|
.y = pixel_rect_.y + (pixel_rect_.h * 0.5F),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
auto Entity::getFeetY() const -> float {
|
auto Entity::getFeetY() const -> float {
|
||||||
// Decal de sòl: sentinel mínim per quedar al principi del Y-sort
|
// Decal de sòl: sentinel mínim per quedar al principi del Y-sort
|
||||||
// ascendent de `GameScene` (stable_sort) i així pintar-se ABANS de
|
// ascendent de `GameScene` (stable_sort) i així pintar-se ABANS de
|
||||||
|
|||||||
@@ -253,6 +253,19 @@ class Entity {
|
|||||||
[[nodiscard]] auto getFlip() const -> SDL_FlipMode { return flip_; }
|
[[nodiscard]] auto getFlip() const -> SDL_FlipMode { return flip_; }
|
||||||
void setFlip(SDL_FlipMode flip) { flip_ = flip; }
|
void setFlip(SDL_FlipMode flip) { flip_ = flip; }
|
||||||
|
|
||||||
|
// Radi de la llum emesa per aquesta entitat (en píxels del canvas).
|
||||||
|
// 0 = no emet (cas habitual). El bloc opcional `light: { radius: N }`
|
||||||
|
// del YAML de la plantilla el pobla via `EntityManager::buildEntity`.
|
||||||
|
[[nodiscard]] auto getLightRadius() const -> int { return light_radius_; }
|
||||||
|
void setLightRadius(int r) { light_radius_ = r; }
|
||||||
|
|
||||||
|
// Centre de la llum en píxels del canvas. Per defecte és el centre del
|
||||||
|
// `pixel_rect_` (que és la caixa de render: sprite top-left + mida).
|
||||||
|
// Virtual perquè entitats amb desplaçament visual sobre la posició
|
||||||
|
// lògica (p.ex. el Player en l'aire, que rebaixa visualment `pos_.y`
|
||||||
|
// amb `jump_z_`) puguin retornar el centre que realment es veu.
|
||||||
|
[[nodiscard]] virtual auto getLightCenter() const -> SDL_FPoint;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
TilePos tile_{};
|
TilePos tile_{};
|
||||||
@@ -266,6 +279,7 @@ class Entity {
|
|||||||
bool is_floor_decal_{false};
|
bool is_floor_decal_{false};
|
||||||
bool blocks_movement_{false};
|
bool blocks_movement_{false};
|
||||||
int height_{0};
|
int height_{0};
|
||||||
|
int light_radius_{0};
|
||||||
bool dead_{false};
|
bool dead_{false};
|
||||||
SDL_FlipMode flip_{SDL_FLIP_NONE};
|
SDL_FlipMode flip_{SDL_FLIP_NONE};
|
||||||
EventBus* bus_{nullptr};
|
EventBus* bus_{nullptr};
|
||||||
|
|||||||
@@ -155,6 +155,17 @@ namespace {
|
|||||||
return c["height"].get_value<int>();
|
return c["height"].get_value<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bloc opcional `light: { radius: N }` de la plantilla. Si manca, el
|
||||||
|
// radi és 0 i l'entitat no entra a la pasada d'il·luminació. La forma
|
||||||
|
// del gradient (3 anells) viu a data/config/lighting.yaml — no cal
|
||||||
|
// declarar-la per entitat.
|
||||||
|
auto readLightRadius(const fkyaml::node& tmpl) -> int {
|
||||||
|
if (!tmpl.contains("light")) { return 0; }
|
||||||
|
const auto& l = tmpl["light"];
|
||||||
|
if (!l.contains("radius")) { return 0; }
|
||||||
|
return l["radius"].get_value<int>();
|
||||||
|
}
|
||||||
|
|
||||||
// Bloc `collision: { size: [w, h], base_size: [bw, bh]?, offset: [x, y]? }`
|
// Bloc `collision: { size: [w, h], base_size: [bw, bh]?, offset: [x, y]? }`
|
||||||
// de la plantilla d'entitat.
|
// de la plantilla d'entitat.
|
||||||
// - Sense `base_size` ni `offset`: la caja queda alineada a la vora
|
// - Sense `base_size` ni `offset`: la caja queda alineada a la vora
|
||||||
@@ -277,6 +288,7 @@ namespace {
|
|||||||
entity->setCollisionBox(*BOX);
|
entity->setCollisionBox(*BOX);
|
||||||
}
|
}
|
||||||
entity->setHeight(readHeight(tmpl));
|
entity->setHeight(readHeight(tmpl));
|
||||||
|
entity->setLightRadius(readLightRadius(tmpl));
|
||||||
anchor_out = readAnchor(tmpl);
|
anchor_out = readAnchor(tmpl);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,14 @@ void Player::loadFrom(const std::string& yaml_path) {
|
|||||||
// `duration_ms` és 0 (o el bloc manca) la mecànica queda
|
// `duration_ms` és 0 (o el bloc manca) la mecànica queda
|
||||||
// desactivada i els hazards toquen al primer frame, com abans.
|
// desactivada i els hazards toquen al primer frame, com abans.
|
||||||
readImmunityBlock(yaml);
|
readImmunityBlock(yaml);
|
||||||
|
|
||||||
|
// Bloc opcional `light: { radius: N }` — radi en píxels del cercle
|
||||||
|
// de llum emès pel jugador. 0 = no emet. La forma del gradient és
|
||||||
|
// global (data/config/lighting.yaml), no per jugador.
|
||||||
|
light_radius = 0;
|
||||||
|
if (yaml.contains("light") && yaml["light"].contains("radius")) {
|
||||||
|
light_radius = yaml["light"]["radius"].get_value<int>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::readCollisionBlock(const fkyaml::node& yaml, const std::string& yaml_path) {
|
void Player::readCollisionBlock(const fkyaml::node& yaml, const std::string& yaml_path) {
|
||||||
@@ -1462,6 +1470,16 @@ void Player::render() {
|
|||||||
if (CLIP_HOLE) { Rendering::popClip(); }
|
if (CLIP_HOLE) { Rendering::popClip(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Player::getLightCenter() const -> SDL_FPoint {
|
||||||
|
// Sprite top-left = (pos_.x, pos_.y). El render desplaça verticalment
|
||||||
|
// `jump_z_` píxels durant el salt; aplicar el mateix offset aquí fa
|
||||||
|
// que la llum "salti" amb el jugador en lloc de quedar-se al sòl.
|
||||||
|
return {
|
||||||
|
.x = getPosX() + (static_cast<float>(sprite_w) * 0.5F),
|
||||||
|
.y = getPosY() - jump_z_ + (static_cast<float>(sprite_h) * 0.5F),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void Player::renderShadow() const {
|
void Player::renderShadow() const {
|
||||||
// Sense salt actiu, no hi ha sombra: això simplifica els callsites,
|
// Sense salt actiu, no hi ha sombra: això simplifica els callsites,
|
||||||
// que poden cridar `renderShadow` per a tots els jugadors sense
|
// que poden cridar `renderShadow` per a tots els jugadors sense
|
||||||
|
|||||||
@@ -124,6 +124,12 @@ class Player : public AnimatedSprite {
|
|||||||
// creua mentre `jump_z_` és superior a aquest valor, no col·lisionem.
|
// creua mentre `jump_z_` és superior a aquest valor, no col·lisionem.
|
||||||
inline static int body_height = 0;
|
inline static int body_height = 0;
|
||||||
|
|
||||||
|
// Radi de la llum emesa pel jugador (en píxels del canvas), llegit
|
||||||
|
// del bloc opcional `light: { radius: N }` del YAML. 0 = no emet.
|
||||||
|
// Es declara estàtic com la resta de configs del jugador (immunity,
|
||||||
|
// jump, ...): tots els jugadors del mateix YAML comparteixen el valor.
|
||||||
|
inline static int light_radius = 0;
|
||||||
|
|
||||||
// Ha de cridar-se abans d'instanciar Player; GameScene ho fa al ctor.
|
// Ha de cridar-se abans d'instanciar Player; GameScene ho fa al ctor.
|
||||||
static void loadFrom(const std::string& yaml_path);
|
static void loadFrom(const std::string& yaml_path);
|
||||||
|
|
||||||
@@ -132,6 +138,13 @@ class Player : public AnimatedSprite {
|
|||||||
// marcador i `Player::resetForJoin` per a re-entrades mid-partida.
|
// marcador i `Player::resetForJoin` per a re-entrades mid-partida.
|
||||||
[[nodiscard]] static auto getInitialLives() -> int { return death_config.initial_lives; }
|
[[nodiscard]] static auto getInitialLives() -> int { return death_config.initial_lives; }
|
||||||
|
|
||||||
|
// Emissió de llum (mateix paper que `Entity::getLightRadius` per a
|
||||||
|
// les entitats). El centre puja amb el salt: durant `jump_z_>0` el
|
||||||
|
// sprite es dibuixa amb `pos_.y - jump_z_`, i la llum ha de seguir-lo
|
||||||
|
// per a que el cercle "salti" amb el jugador, no es quedi al sòl.
|
||||||
|
[[nodiscard]] static auto getLightRadius() -> int { return light_radius; }
|
||||||
|
[[nodiscard]] auto getLightCenter() const -> SDL_FPoint;
|
||||||
|
|
||||||
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);
|
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);
|
||||||
|
|
||||||
// Update en una sola crida: manté l'API anterior per als tests i
|
// Update en una sola crida: manté l'API anterior per als tests i
|
||||||
|
|||||||
Reference in new issue
Block a user