refactor(entities): unifica loader d'animacio via AnimationComponent::fromYaml i elimina fps:
This commit is contained in:
1 parent
a779533d61
commit
b76a3eb1f3
21 files changed
+306
-231
No files matched your search
@@ -1,45 +1,16 @@
|
||||
#include "game/entities/concrete/door.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "game/entities/event_bus.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
#include "game/map/map.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
// Carrega una animació d'un bloc concret (closed/opening/open) amb
|
||||
// fallbacks tolerants. Si la clau no existeix, retorna una animació
|
||||
// d'un sol frame loopant: no fa estat invàlid, simplement no hi ha res
|
||||
// per reproduir.
|
||||
auto buildAnimation(const fkyaml::node& yaml, const std::string& key) -> AnimationComponent {
|
||||
std::vector<int> frames = {0};
|
||||
float fps = 1.0F;
|
||||
bool loop = true;
|
||||
if (yaml.contains("animations") && yaml["animations"].contains(key)) {
|
||||
const auto& anim = yaml["animations"][key];
|
||||
if (anim.contains("frames")) {
|
||||
frames.clear();
|
||||
for (const auto& f : anim["frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
frames.push_back(f.get_value<int>());
|
||||
}
|
||||
if (frames.empty()) { frames.push_back(0); }
|
||||
}
|
||||
if (anim.contains("fps")) { fps = anim["fps"].get_value<float>(); }
|
||||
if (anim.contains("loop")) { loop = anim["loop"].get_value<bool>(); }
|
||||
}
|
||||
return {frames, fps, loop};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Door::Door(const fkyaml::node& yaml)
|
||||
: anim_closed_(buildAnimation(yaml, "closed")),
|
||||
anim_opening_(buildAnimation(yaml, "opening")),
|
||||
anim_open_(buildAnimation(yaml, "open")) {
|
||||
: anim_closed_(AnimationComponent::fromYaml(yaml, "closed")),
|
||||
anim_opening_(AnimationComponent::fromYaml(yaml, "opening")),
|
||||
anim_open_(AnimationComponent::fromYaml(yaml, "open")) {
|
||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("door");
|
||||
collides_ = true;
|
||||
interactable_ = true;
|
||||
@@ -99,7 +70,7 @@ void Door::open() {
|
||||
// placeholders defineixen `loop: false` explícitament al YAML, així
|
||||
// que aquest fallback només actua si algú dissenya malament.
|
||||
if (anim_.has_value() && anim_->frameCount() <= 1 && anim_->loops()) {
|
||||
anim_ = AnimationComponent({0}, 6.0F, false);
|
||||
anim_ = AnimationComponent::uniform({0}, 167.0F, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,42 +1,12 @@
|
||||
#include "game/entities/concrete/dust.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
// Llig una animació opcional del bloc `animations` del YAML, amb
|
||||
// valors per defecte segurs (1 frame, fps=1, sense loop). Si la
|
||||
// clau no existeix, retornem una animació "ja completada" — així,
|
||||
// un Dust spawnejat amb una variant inexistent al YAML mor al
|
||||
// pròxim frame sense petar.
|
||||
auto buildAnim(const fkyaml::node& yaml, const std::string& key) -> AnimationComponent {
|
||||
std::vector<int> frames = {0};
|
||||
float fps = 1.0F;
|
||||
bool loop = false;
|
||||
if (yaml.contains("animations") && yaml["animations"].contains(key)) {
|
||||
const auto& anim = yaml["animations"][key];
|
||||
if (anim.contains("frames")) {
|
||||
frames.clear();
|
||||
for (const auto& f : anim["frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
frames.push_back(f.get_value<int>());
|
||||
}
|
||||
if (frames.empty()) { frames.push_back(0); }
|
||||
}
|
||||
if (anim.contains("fps")) { fps = anim["fps"].get_value<float>(); }
|
||||
if (anim.contains("loop")) { loop = anim["loop"].get_value<bool>(); }
|
||||
}
|
||||
return {frames, fps, loop};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Dust::Dust(const fkyaml::node& yaml)
|
||||
: anim_jump_(buildAnim(yaml, "jump")),
|
||||
anim_land_(buildAnim(yaml, "land")) {
|
||||
: anim_jump_(AnimationComponent::fromYaml(yaml, "jump")),
|
||||
anim_land_(AnimationComponent::fromYaml(yaml, "land")) {
|
||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("dust");
|
||||
collides_ = false;
|
||||
interactable_ = false;
|
||||
|
||||
@@ -29,36 +29,6 @@ namespace {
|
||||
return k_rng_;
|
||||
}
|
||||
|
||||
// Llegeix un bloc d'animació del YAML amb fallbacks tolerants (mateix
|
||||
// patró que Door/Sarcophagus). Si la clau no apareix, retorna una
|
||||
// animació d'1 frame loopant, neutra — la momia es podrà moure però
|
||||
// visualment es quedarà estàtica. Llegeix `flip_h`/`flip_v` (default
|
||||
// false) i els passa al component perquè el motor sàpiga aplicar-los
|
||||
// al sprite quan aquesta animació estigui activa.
|
||||
auto buildAnimation(const fkyaml::node& yaml, const std::string& key) -> AnimationComponent {
|
||||
std::vector<int> frames = {0};
|
||||
float fps = 8.0F;
|
||||
bool loop = true;
|
||||
bool flip_h = false;
|
||||
bool flip_v = false;
|
||||
if (yaml.contains("animations") && yaml["animations"].contains(key)) {
|
||||
const auto& anim = yaml["animations"][key];
|
||||
if (anim.contains("frames")) {
|
||||
frames.clear();
|
||||
for (const auto& f : anim["frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
frames.push_back(f.get_value<int>());
|
||||
}
|
||||
if (frames.empty()) { frames.push_back(0); }
|
||||
}
|
||||
if (anim.contains("fps")) { fps = anim["fps"].get_value<float>(); }
|
||||
if (anim.contains("loop")) { loop = anim["loop"].get_value<bool>(); }
|
||||
if (anim.contains("flip_h")) { flip_h = anim["flip_h"].get_value<bool>(); }
|
||||
if (anim.contains("flip_v")) { flip_v = anim["flip_v"].get_value<bool>(); }
|
||||
}
|
||||
return {frames, fps, loop, flip_h, flip_v};
|
||||
}
|
||||
|
||||
// Busca si el segment [prev, prev+delta] travessa una lane del patró
|
||||
// `base + k·pitch` (k ∈ [0..max_idx]). Retorna el delta que cal aplicar
|
||||
// per arribar exactament a la primera línia travessada. Iterem en el
|
||||
@@ -103,11 +73,11 @@ namespace {
|
||||
} // namespace
|
||||
|
||||
Mummy::Mummy(const fkyaml::node& yaml)
|
||||
: anim_walk_south_(buildAnimation(yaml, "walk_south")),
|
||||
anim_walk_north_(buildAnimation(yaml, "walk_north")),
|
||||
anim_walk_east_(buildAnimation(yaml, "walk_east")),
|
||||
anim_walk_west_(buildAnimation(yaml, "walk_west")),
|
||||
anim_raise_(buildAnimation(yaml, "raise")) {
|
||||
: anim_walk_south_(AnimationComponent::fromYaml(yaml, "walk_south")),
|
||||
anim_walk_north_(AnimationComponent::fromYaml(yaml, "walk_north")),
|
||||
anim_walk_east_(AnimationComponent::fromYaml(yaml, "walk_east")),
|
||||
anim_walk_west_(AnimationComponent::fromYaml(yaml, "walk_west")),
|
||||
anim_raise_(AnimationComponent::fromYaml(yaml, "raise")) {
|
||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("mummy");
|
||||
collides_ = true;
|
||||
interactable_ = false;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/audio/audio.hpp"
|
||||
#include "core/resources/resource_cache.hpp"
|
||||
@@ -21,26 +20,6 @@ namespace {
|
||||
return k_rng_;
|
||||
}
|
||||
|
||||
auto buildAnimation(const fkyaml::node& yaml, const std::string& key) -> AnimationComponent {
|
||||
std::vector<int> frames = {0};
|
||||
float fps = 1.0F;
|
||||
bool loop = true;
|
||||
if (yaml.contains("animations") && yaml["animations"].contains(key)) {
|
||||
const auto& anim = yaml["animations"][key];
|
||||
if (anim.contains("frames")) {
|
||||
frames.clear();
|
||||
for (const auto& f : anim["frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
frames.push_back(f.get_value<int>());
|
||||
}
|
||||
if (frames.empty()) { frames.push_back(0); }
|
||||
}
|
||||
if (anim.contains("fps")) { fps = anim["fps"].get_value<float>(); }
|
||||
if (anim.contains("loop")) { loop = anim["loop"].get_value<bool>(); }
|
||||
}
|
||||
return {frames, fps, loop};
|
||||
}
|
||||
|
||||
// Llig `tile_size: [w, h]` del YAML. Fallback [1,1] si no existeix.
|
||||
void readTileSize(const fkyaml::node& yaml, int& w, int& h) {
|
||||
w = 1;
|
||||
@@ -61,9 +40,9 @@ Sarcophagus::Sarcophagus(const fkyaml::node& yaml, int anchor_col, int anchor_ro
|
||||
}
|
||||
|
||||
Sarcophagus::Sarcophagus(const fkyaml::node& yaml)
|
||||
: anim_closed_(buildAnimation(yaml, "closed")),
|
||||
anim_opening_(buildAnimation(yaml, "opening")),
|
||||
anim_open_(buildAnimation(yaml, "open")) {
|
||||
: anim_closed_(AnimationComponent::fromYaml(yaml, "closed")),
|
||||
anim_opening_(AnimationComponent::fromYaml(yaml, "opening")),
|
||||
anim_open_(AnimationComponent::fromYaml(yaml, "open")) {
|
||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("sarcophagus");
|
||||
collides_ = true;
|
||||
interactable_ = true;
|
||||
|
||||
@@ -1,41 +1,14 @@
|
||||
#include "game/entities/concrete/torch.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
// Ajut: extreu l'animació `idle` del bloc `animations` del YAML si existeix,
|
||||
// amb valors per defecte que sempre produïxen una animació vàlida (1 frame).
|
||||
auto buildIdleAnimation(const fkyaml::node& yaml) -> AnimationComponent {
|
||||
std::vector<int> frames = {0};
|
||||
float fps = 1.0F;
|
||||
bool loop = true;
|
||||
if (yaml.contains("animations") && yaml["animations"].contains("idle")) {
|
||||
const auto& anim = yaml["animations"]["idle"];
|
||||
if (anim.contains("frames")) {
|
||||
frames.clear();
|
||||
for (const auto& f : anim["frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
frames.push_back(f.get_value<int>());
|
||||
}
|
||||
if (frames.empty()) { frames.push_back(0); }
|
||||
}
|
||||
if (anim.contains("fps")) { fps = anim["fps"].get_value<float>(); }
|
||||
if (anim.contains("loop")) { loop = anim["loop"].get_value<bool>(); }
|
||||
}
|
||||
return {frames, fps, loop};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Torch::Torch(const fkyaml::node& yaml) {
|
||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("torch");
|
||||
collides_ = false;
|
||||
interactable_ = false;
|
||||
anim_ = buildIdleAnimation(yaml);
|
||||
anim_ = AnimationComponent::fromYaml(yaml, "idle");
|
||||
}
|
||||
|
||||
REGISTER_ENTITY("torch", Torch)
|
||||
@@ -33,42 +33,18 @@ namespace {
|
||||
return sprite;
|
||||
}
|
||||
|
||||
// Construeix l'`AnimationComponent` del swing a partir del bloc
|
||||
// `animations.swing`. Convenció igual que la resta d'entitats:
|
||||
// - `frames` : llista d'índexs dins l'spritesheet (obligatori).
|
||||
// - `frame_ms` : durada uniforme per frame (ms). Alternativament `fps`.
|
||||
// - `loop` : per defecte true; al látigo el volem false (mor en
|
||||
// completar).
|
||||
auto buildSwingAnim(const fkyaml::node& yaml, std::vector<int>& active_out)
|
||||
-> AnimationComponent {
|
||||
std::vector<int> frames = {0};
|
||||
float fps = 8.0F;
|
||||
bool loop = false;
|
||||
if (yaml.contains("animations") && yaml["animations"].contains("swing")) {
|
||||
const auto& sw = yaml["animations"]["swing"];
|
||||
if (sw.contains("frames")) {
|
||||
frames.clear();
|
||||
for (const auto& f : sw["frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
frames.push_back(f.get_value<int>());
|
||||
}
|
||||
if (frames.empty()) { frames.push_back(0); }
|
||||
}
|
||||
if (sw.contains("frame_ms")) {
|
||||
const auto MS = static_cast<float>(sw["frame_ms"].get_value<int>());
|
||||
if (MS > 0.0F) { fps = 1000.0F / MS; }
|
||||
} else if (sw.contains("fps")) {
|
||||
fps = sw["fps"].get_value<float>();
|
||||
}
|
||||
if (sw.contains("loop")) { loop = sw["loop"].get_value<bool>(); }
|
||||
if (sw.contains("active_frames")) {
|
||||
for (const auto& f : sw["active_frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
active_out.push_back(f.get_value<int>());
|
||||
}
|
||||
}
|
||||
// Llig el camp `active_frames` del bloc `animations.swing` — específic
|
||||
// del látigo: els índexs llistats són els frames on la hitbox aplica
|
||||
// dany (wind-up i recovery no danyen). La resta de l'animació la
|
||||
// construeix `AnimationComponent::fromYaml`.
|
||||
void readActiveFrames(const fkyaml::node& yaml, std::vector<int>& active_out) {
|
||||
if (!yaml.contains("animations") || !yaml["animations"].contains("swing")) { return; }
|
||||
const auto& sw = yaml["animations"]["swing"];
|
||||
if (!sw.contains("active_frames")) { return; }
|
||||
for (const auto& f : sw["active_frames"]) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
active_out.push_back(f.get_value<int>());
|
||||
}
|
||||
return {frames, fps, loop};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -86,7 +62,8 @@ WhipAttack::WhipAttack(const fkyaml::node& yaml) {
|
||||
if (s.contains("west")) { sprite_west_ = readDirSprite(s["west"]); }
|
||||
}
|
||||
|
||||
anim_swing_ = buildSwingAnim(yaml, active_frames_);
|
||||
anim_swing_ = AnimationComponent::fromYaml(yaml, "swing");
|
||||
readActiveFrames(yaml, active_frames_);
|
||||
anim_ = anim_swing_;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user