Files
aee-arcade/source/game/entities/concrete/mummy.hpp
T

81 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <cstdint>
#include <vector>
#include "external/fkyaml_node.hpp"
#include "game/entities/animation_component.hpp"
#include "game/entities/hazard.hpp"
// Mòmia: perill dinàmic que deambula pels passadís. A cada intersecció
// tria una direcció vàlida; l'algoritme per triar-la és un hook virtual
// (`chooseDirection`) que la base implementa com a aleatori uniforme
// sobre les direccions admissibles. Futurs derivats poden sesgar cap al
// jugador sense tocar la lògica de moviment.
//
// Andamiatge: el concepte d'"intersecció" i la validació de direcció
// requereixen conèixer el mapa. De moment l'exposem com un conjunt de
// direccions admissibles que l'EntityManager injecta; la implementació
// real arribarà quan cablegem l'entitat al game loop.
class Mummy : public DynamicHazard {
public:
enum class Direction : std::uint8_t { NONE,
UP,
DOWN,
LEFT,
RIGHT };
explicit Mummy(const fkyaml::node& yaml);
// Hook d'IA. Donat un conjunt de direccions admissibles, decideix la
// següent direcció a prendre. La implementació de la base tria una
// aleatoria; si `allowed` està buit, retorna `NONE`.
virtual auto chooseDirection(const std::vector<Direction>& allowed) -> Direction;
// Política de moviment "corridor_wanderer": camina recte fins que el
// pròxim tram la bloquejaria (mur del playfield o sarc). Quan troba un
// obstacle, recull les direccions perpendiculars vàlides (evitant
// U-turn llevat que no hi hagi alternativa) i crida `chooseDirection`
// per decidir-ne una. No consumeix moviment el frame de gir.
void step(float delta_time) override;
// Contacte amb el jugador: publica `player_hit` amb el dany.
void onPlayerContact(Player* player) override;
private:
// Caixa de col·lisió candidata si l'entitat es desplaçara (dx, dy).
[[nodiscard]] auto candidateBox(float dx, float dy) const -> SDL_FRect;
// Amarra la caja a la vora exacta del playfield quan el candidat hi
// sortiria — sense això, amb la caja 16×16 iguala el corredor, la
// posició subpíxel dins de l'última cel·la impediria girar a cap
// perpendicular (col·lisionaria amb el sarc adjacent). Es crida abans
// de la lògica de gir.
void snapToPlayfieldEdge(float dx, float dy);
// Recull les direccions alternatives viables des de la posició actual:
// `perpendiculars` (girs) i `uturn` (inversa). La direcció actual s'exclou
// perquè ja sabem que està bloquejada. Cada candidata es valida amb
// `Map::insidePlayfield` + `Map::collides` sobre la caja resultant.
struct DirectionPools {
std::vector<Direction> perp;
std::vector<Direction> uturn;
};
[[nodiscard]] auto collectDirectionPools(float step) const -> DirectionPools;
// Canvi de direcció + aplicació de l'animació i flip corresponents.
// Tots els camins que trien nova direcció (ctor amb `initial_direction`,
// gir després d'un bloqueig) passen per ací per mantenir anim_ i
// flip_ en sincronia amb (dir_x_, dir_y_).
void changeDirection(float dx, float dy);
// Aplica la direcció triada (wrapper del switch en una sola crida).
void applyChoice(Direction dir);
// Animacions carregades del YAML, una per cada facing. Per a horitzontal
// només en cal una (`walk`) i el flip ja diferencia esquerra/dreta.
AnimationComponent anim_walk_down_;
AnimationComponent anim_walk_up_;
AnimationComponent anim_walk_lateral_;
};