diff --git a/data/entities/momia/momia.gif b/data/entities/momia/momia.gif new file mode 100644 index 0000000..9352a96 Binary files /dev/null and b/data/entities/momia/momia.gif differ diff --git a/data/entities/momia/momia.yaml b/data/entities/momia/momia.yaml new file mode 100644 index 0000000..7602bc2 --- /dev/null +++ b/data/entities/momia/momia.yaml @@ -0,0 +1,35 @@ +name: momia +type: dynamic_hazard +sprite: + path: momia.gif + size: [16, 32] +tile_size: [1, 1] +# Variant 16×32 de la momia: el sprite fa 16×32 (dos 16×16: cap i peus) +# i la caja de col·lisió amb el mapa és 16×16, coincident amb el +# rectangle-base 16×16 dels peus. Com que `size` i `base_size` són +# iguals, el padding és zero i la caja s'alinea exactament amb la +# silueta inferior del sprite; amb `anchor: feet` ocupa la cel·la +# 16×16 del corredor on naix. +anchor: feet +collision: + size: [16, 16] + base_size: [16, 16] +flags: + collides: true + interactable: false +# Strip de 12 frames en graella 4×3 (mateix esquema que el jugador): +# 0..3 → walk_down (cara avall) +# 4..7 → walk_up (cara amunt) +# 8..11 → walk (lateral; flip horitzontal segons el sentit) +# La momia no té variants `stand_*` perquè mai no para. +animations: + walk_down: { frames: [0, 1, 2, 3], fps: 8, loop: true } + walk_up: { frames: [4, 5, 6, 7], fps: 8, loop: true } + walk: { frames: [8, 9, 10, 11], fps: 8, loop: true } +ai: + type: corridor_wanderer + direction_choice: random + initial_direction: right +stats: + speed: 30 + damage: 1 diff --git a/data/maps/pyramid.yaml b/data/maps/pyramid.yaml index 763ca8b..aeda305 100644 --- a/data/maps/pyramid.yaml +++ b/data/maps/pyramid.yaml @@ -118,7 +118,7 @@ entities: sarc_position: [3, 4] - type: door position: [9, 1] - - type: mummy + - type: momia position: [10, 7] - - type: mummy + - type: momia position: [7, 9] diff --git a/data/player/sam.gif b/data/player/sam.gif new file mode 100644 index 0000000..98eaa5d Binary files /dev/null and b/data/player/sam.gif differ diff --git a/data/player/sam.yaml b/data/player/sam.yaml new file mode 100644 index 0000000..83017bf --- /dev/null +++ b/data/player/sam.yaml @@ -0,0 +1,37 @@ +# player animation +tileSetFile: sam.gif +frameWidth: 16 +frameHeight: 32 + +# Geometria de col·lisió del jugador (independent de l'animació): +# size → costat del quadrat de col·lisió (16×16) +# base_size → costat del quadrat visual inferior del sprite (els "peus"); +# s'usa per centrar la caixa de col·lisió sobre ell. +collision: + size: 16 + base_size: 16 + +animations: + - name: stand_down + frames: [1] + + - name: stand_up + frames: [5] + + - name: stand + frames: [9] + + - name: walk_down + speed: 0.1 + loopFrom: 0 + frames: [0, 1, 2, 3] + + - name: walk_up + speed: 0.1 + loopFrom: 0 + frames: [4, 5, 6, 7] + + - name: walk + speed: 0.1 + loopFrom: 0 + frames: [8, 9, 10, 11] diff --git a/source/game/entities/concrete/mummy.cpp b/source/game/entities/concrete/mummy.cpp index 08a056c..63f83c0 100644 --- a/source/game/entities/concrete/mummy.cpp +++ b/source/game/entities/concrete/mummy.cpp @@ -299,3 +299,4 @@ void Mummy::onPlayerContact(Player* /*player*/) { } REGISTER_ENTITY("mummy", Mummy) +REGISTER_ENTITY_AS("momia", Mummy, Momia) diff --git a/source/game/entities/entity_factory.hpp b/source/game/entities/entity_factory.hpp index 601d195..4fba022 100644 --- a/source/game/entities/entity_factory.hpp +++ b/source/game/entities/entity_factory.hpp @@ -43,23 +43,28 @@ class EntityFactory { }; // La macro genera un objecte anònim dins un namespace anònim: el seu -// constructor s'executa abans de `main` i registra la factory. El nom del -// símbol és únic per `CLASS` perquè el preprocessor el concatena; així -// dues entitats diferents no xoquen. +// constructor s'executa abans de `main` i registra la factory. El nom +// del símbol es compon amb `TAG`, perquè així es poden registrar àlies +// per una mateixa classe (p.ex. "mummy" i "momia" → Mummy) sense que +// els símbols xoquen. La forma curta `REGISTER_ENTITY(NAME, CLASS)` +// reusa `CLASS` com a tag; per àlies cal usar `REGISTER_ENTITY_AS` i +// passar un identificador únic. // // IMPORTANT: perquè el registrador es cridi, el `.cpp` que el conté ha // d'estar enllaçat directament a l'executable (no dins una STATIC lib // sense `--whole-archive`). Tots els `concrete/*.cpp` entren a APP_SOURCES. -#define REGISTER_ENTITY(NAME, CLASS) \ - namespace { \ - struct CLASS##_Registrar { \ - CLASS##_Registrar() { \ - EntityFactory::instance().registerCreator( \ - NAME, \ - [](const fkyaml::node& yaml) -> std::unique_ptr { \ - return std::make_unique(yaml); \ - }); \ - } \ - }; \ - const CLASS##_Registrar g_##CLASS##_registrar; /* NOLINT(cert-err58-cpp) */ \ +#define REGISTER_ENTITY_AS(NAME, CLASS, TAG) \ + namespace { \ + struct TAG##_Registrar { \ + TAG##_Registrar() { \ + EntityFactory::instance().registerCreator( \ + NAME, \ + [](const fkyaml::node& yaml) -> std::unique_ptr { \ + return std::make_unique(yaml); \ + }); \ + } \ + }; \ + const TAG##_Registrar g_##TAG##_registrar; /* NOLINT(cert-err58-cpp) */ \ } + +#define REGISTER_ENTITY(NAME, CLASS) REGISTER_ENTITY_AS(NAME, CLASS, CLASS) diff --git a/source/utils/defaults.hpp b/source/utils/defaults.hpp index f906fca..bcbb859 100644 --- a/source/utils/defaults.hpp +++ b/source/utils/defaults.hpp @@ -181,8 +181,8 @@ namespace Defaults { // conjunt de constants + un Config distint passat al ctor. namespace Pyramid { constexpr const char* MAP_YAML = "data/maps/pyramid.yaml"; - constexpr const char* PLAYER_SPRITE = "data/player/player.gif"; - constexpr const char* PLAYER_YAML = "data/player/player.yaml"; + constexpr const char* PLAYER_SPRITE = "data/player/sam.gif"; + constexpr const char* PLAYER_YAML = "data/player/sam.yaml"; constexpr const char* MUSIC_TRACK = "pyramid_1.ogg"; } // namespace Pyramid