migrant .ani a .yaml

This commit is contained in:
2025-11-17 13:08:38 +01:00
parent 3c4092df5e
commit 6a6cc22b21
72 changed files with 47 additions and 1050 deletions

View File

@@ -13,36 +13,6 @@
#include "core/resources/resource_helper.hpp" // Para ResourceHelper
#include "utils/utils.hpp" // Para printWithDots
// Carga las animaciones en un vector(Animations) desde un fichero
auto SurfaceAnimatedSprite::loadAnimationsFromFile(const std::string& file_path) -> Animations {
// Load file using ResourceHelper (supports both filesystem and pack)
auto file_data = Resource::Helper::loadFile(file_path);
if (file_data.empty()) {
std::cerr << "Error: Fichero no encontrado " << file_path << '\n';
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
// Convert bytes to string and parse
std::string content(file_data.begin(), file_data.end());
std::istringstream stream(content);
std::vector<std::string> buffer;
std::string line;
while (std::getline(stream, line)) {
// Eliminar \r de Windows line endings
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
if (!line.empty()) {
buffer.push_back(line);
}
}
return buffer;
}
// Helper: Convierte un nodo YAML de frames (array) a vector de SDL_FRect
auto convertYAMLFramesToRects(const fkyaml::node& frames_node, float frame_width, float frame_height, int frames_per_row, int max_tiles) -> std::vector<SDL_FRect> {
std::vector<SDL_FRect> frames;
@@ -154,65 +124,20 @@ auto SurfaceAnimatedSprite::loadAnimationsFromYAML(const std::string& file_path,
return animations;
}
// Constructor
SurfaceAnimatedSprite::SurfaceAnimatedSprite(const std::string& file_path) {
// Carga las animaciones
if (!file_path.empty()) {
// Detectar extensión del archivo
const bool IS_YAML = file_path.substr(file_path.find_last_of('.') + 1) == "yaml";
// Constructor con datos pre-cargados del cache
SurfaceAnimatedSprite::SurfaceAnimatedSprite(const ResourceAnimation& cached_data)
: SurfaceMovingSprite(cached_data.surface) {
// Copiar datos pre-cargados del cache
animations_ = cached_data.animations;
setWidth(cached_data.frame_width);
setHeight(cached_data.frame_height);
if (IS_YAML) {
// Cargar desde YAML (formato nuevo)
float frame_width = 1.0F;
float frame_height = 1.0F;
animations_ = loadAnimationsFromYAML(file_path, surface_, frame_width, frame_height);
setWidth(frame_width);
setHeight(frame_height);
} else {
// Cargar desde .ani (formato legacy)
Animations v = SurfaceAnimatedSprite::loadAnimationsFromFile(file_path);
setAnimations(v);
}
// Inicializar con la primera animación si existe
if (!animations_.empty() && !animations_[0].frames.empty()) {
setClip(animations_[0].frames[0]);
}
}
// Constructor
SurfaceAnimatedSprite::SurfaceAnimatedSprite(const Animations& animations) {
if (!animations.empty()) {
setAnimations(animations);
}
}
// Constructor
SurfaceAnimatedSprite::SurfaceAnimatedSprite(std::shared_ptr<Surface> surface, const std::string& file_path)
: SurfaceMovingSprite(std::move(surface)) {
// Carga las animaciones
if (!file_path.empty()) {
// Detectar extensión del archivo
const bool IS_YAML = file_path.substr(file_path.find_last_of('.') + 1) == "yaml";
if (IS_YAML) {
// Cargar desde YAML (formato nuevo)
float frame_width = 1.0F;
float frame_height = 1.0F;
animations_ = loadAnimationsFromYAML(file_path, surface_, frame_width, frame_height);
setWidth(frame_width);
setHeight(frame_height);
} else {
// Cargar desde .ani (formato legacy)
Animations v = SurfaceAnimatedSprite::loadAnimationsFromFile(file_path);
setAnimations(v);
}
}
}
// Constructor
SurfaceAnimatedSprite::SurfaceAnimatedSprite(std::shared_ptr<Surface> surface, const Animations& animations)
: SurfaceMovingSprite(std::move(surface)) {
if (!animations.empty()) {
setAnimations(animations);
}
}
// Obtiene el indice de la animación a partir del nombre
auto SurfaceAnimatedSprite::getIndex(const std::string& name) -> int {
@@ -319,133 +244,6 @@ void SurfaceAnimatedSprite::resetAnimation() {
animations_[current_animation_].completed = false;
}
// Helper: Parsea los parámetros de configuración globales (frame_width, frame_height)
auto parseGlobalParameter(const std::string& line, std::shared_ptr<Surface>& surface, float& frame_width, float& frame_height) -> bool {
size_t pos = line.find('=');
if (pos == std::string::npos) {
return false;
}
std::string key = line.substr(0, pos);
if (key == "tileSetFile") {
std::string value = line.substr(pos + 1);
surface = Resource::Cache::get()->getSurface(value);
return true;
}
if (key == "frame_width") {
int value = std::stoi(line.substr(pos + 1));
frame_width = value;
return true;
}
if (key == "frame_height") {
int value = std::stoi(line.substr(pos + 1));
frame_height = value;
return true;
}
std::cout << "Warning: unknown parameter " << key << '\n';
return false;
}
// Helper: Parsea los frames de una animación desde una cadena separada por comas
void parseAnimationFrames(const std::string& value, SurfaceAnimatedSprite::AnimationData& animation, float frame_width, float frame_height, int frames_per_row, int max_tiles) {
std::stringstream ss(value);
std::string tmp;
SDL_FRect rect = {0.0F, 0.0F, frame_width, frame_height};
while (getline(ss, tmp, ',')) {
const int NUM_TILE = std::stoi(tmp);
if (NUM_TILE <= max_tiles) {
rect.x = (NUM_TILE % frames_per_row) * frame_width;
rect.y = (NUM_TILE / frames_per_row) * frame_height;
animation.frames.emplace_back(rect);
}
}
}
// Helper: Parsea un parámetro de animación individual
auto parseAnimationParameter(const std::string& key, const std::string& value, SurfaceAnimatedSprite::AnimationData& animation, float frame_width, float frame_height, int frames_per_row, int max_tiles) -> bool {
if (key == "name") {
animation.name = value;
return true;
}
if (key == "speed") {
// Soporta tanto float (segundos) como int (compatibilidad con sistema antiguo)
animation.speed = std::stof(value);
return true;
}
if (key == "loop") {
animation.loop = std::stoi(value);
return true;
}
if (key == "frames") {
parseAnimationFrames(value, animation, frame_width, frame_height, frames_per_row, max_tiles);
return true;
}
std::cout << "Warning: unknown parameter " << key << '\n';
return false;
}
// Helper: Parsea una animación completa
auto parseAnimation(const SurfaceAnimatedSprite::Animations& animations, size_t& index, float frame_width, float frame_height, int frames_per_row, int max_tiles) -> SurfaceAnimatedSprite::AnimationData {
SurfaceAnimatedSprite::AnimationData animation;
std::string line;
do {
index++;
line = animations.at(index);
size_t pos = line.find('=');
if (pos != std::string::npos) {
std::string key = line.substr(0, pos);
std::string value = line.substr(pos + 1);
parseAnimationParameter(key, value, animation, frame_width, frame_height, frames_per_row, max_tiles);
}
} while (line != "[/animation]");
return animation;
}
// Carga la animación desde un vector de cadenas
void SurfaceAnimatedSprite::setAnimations(const Animations& animations) {
float frame_width = 1.0F;
float frame_height = 1.0F;
int frames_per_row = 1;
int max_tiles = 1;
size_t index = 0;
while (index < animations.size()) {
const std::string& line = animations.at(index);
// Parsea el fichero para buscar variables y valores
if (line != "[animation]") {
if (parseGlobalParameter(line, surface_, frame_width, frame_height)) {
if (surface_) {
frames_per_row = surface_->getWidth() / frame_width;
const int W = surface_->getWidth() / frame_width;
const int H = surface_->getHeight() / frame_height;
max_tiles = W * H;
}
}
}
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]") {
SurfaceAnimatedSprite::AnimationData animation = parseAnimation(animations, index, frame_width, frame_height, frames_per_row, max_tiles);
animations_.emplace_back(animation);
}
// Una vez procesada la linea, aumenta el indice para pasar a la siguiente
index++;
}
// Pone un valor por defecto
setWidth(frame_width);
setHeight(frame_height);
}
// Establece el frame actual de la animación
void SurfaceAnimatedSprite::setCurrentAnimationFrame(int num) {
// Descarta valores fuera de rango

View File

@@ -10,6 +10,7 @@
#include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite
class Surface;
struct ResourceAnimation; // Forward declaration
class SurfaceAnimatedSprite : public SurfaceMovingSprite {
public:
@@ -27,16 +28,10 @@ class SurfaceAnimatedSprite : public SurfaceMovingSprite {
};
// Métodos estáticos
static auto loadAnimationsFromFile(const std::string& file_path) -> Animations; // Carga las animaciones desde fichero .ani
static auto loadAnimationsFromYAML(const std::string& file_path, std::shared_ptr<Surface>& surface, float& frame_width, float& frame_height) -> std::vector<AnimationData>; // Carga las animaciones desde fichero .yaml
static auto loadAnimationsFromYAML(const std::string& file_path, std::shared_ptr<Surface>& surface, float& frame_width, float& frame_height) -> std::vector<AnimationData>; // Carga las animaciones desde fichero YAML
// Constructores
explicit SurfaceAnimatedSprite(const std::string& file_path);
explicit SurfaceAnimatedSprite(const Animations& animations);
SurfaceAnimatedSprite(std::shared_ptr<Surface> surface, const std::string& file_path);
SurfaceAnimatedSprite(std::shared_ptr<Surface> surface, const Animations& animations);
explicit SurfaceAnimatedSprite(std::shared_ptr<Surface> surface)
: SurfaceMovingSprite(std::move(surface)) {}
explicit SurfaceAnimatedSprite(const ResourceAnimation& cached_data); // Constructor con datos pre-cargados del cache
~SurfaceAnimatedSprite() override = default; // Destructor
@@ -55,15 +50,9 @@ class SurfaceAnimatedSprite : public SurfaceMovingSprite {
protected:
// Métodos protegidos
void animate(float delta_time); // Calcula el frame correspondiente a la animación actual (time-based)
void setAnimations(const Animations& animations); // Carga la animación desde un vector de cadenas
void animate(float delta_time); // Calcula el frame correspondiente a la animación actual (time-based)
private:
// Funciones amigas (helper functions del .cpp)
friend void parseAnimationFrames(const std::string& value, AnimationData& animation, float frame_width, float frame_height, int frames_per_row, int max_tiles);
friend auto parseAnimationParameter(const std::string& key, const std::string& value, AnimationData& animation, float frame_width, float frame_height, int frames_per_row, int max_tiles) -> bool;
friend auto parseAnimation(const Animations& animations, size_t& index, float frame_width, float frame_height, int frames_per_row, int max_tiles) -> AnimationData;
// Variables miembro
std::vector<AnimationData> animations_; // Vector con las diferentes animaciones
int current_animation_{0}; // Animación activa

View File

@@ -148,12 +148,12 @@ auto Cache::getText(const std::string& name) -> std::shared_ptr<Text> {
throw std::runtime_error("Texto no encontrado: " + name);
}
// Obtiene la animación a partir de un nombre
auto Cache::getAnimations(const std::string& name) -> SurfaceAnimatedSprite::Animations& {
// Obtiene los datos de animación parseados a partir de un nombre
auto Cache::getAnimationData(const std::string& name) -> const ResourceAnimation& {
auto it = std::ranges::find_if(animations_, [&name](const auto& a) { return a.name == name; });
if (it != animations_.end()) {
return it->animation;
return *it;
}
std::cerr << "Error: Animación no encontrada " << name << '\n';
@@ -300,7 +300,14 @@ void Cache::loadAnimations() {
for (const auto& l : list) {
auto name = getFileName(l);
animations_.emplace_back(name, SurfaceAnimatedSprite::loadAnimationsFromFile(l));
// Parsear YAML y almacenar datos pre-cargados
std::shared_ptr<Surface> surface;
float frame_width = 0.0F;
float frame_height = 0.0F;
auto animation_data = SurfaceAnimatedSprite::loadAnimationsFromYAML(l, surface, frame_width, frame_height);
animations_.emplace_back(name, animation_data, surface, frame_width, frame_height);
updateLoadingProgress();
}
}

View File

@@ -80,13 +80,19 @@ struct ResourceText {
// Estructura para almacenar ficheros animaciones y su nombre
struct ResourceAnimation {
std::string name; // Nombre del fichero
SurfaceAnimatedSprite::Animations animation; // Objeto con las animaciones
std::string name; // Nombre del fichero
std::vector<SurfaceAnimatedSprite::AnimationData> animations; // Datos de animaciones parseadas desde YAML
std::shared_ptr<Surface> surface; // Surface asociada al sprite sheet
float frame_width{0.0F}; // Ancho de cada frame
float frame_height{0.0F}; // Alto de cada frame
// Constructor
ResourceAnimation(std::string name, SurfaceAnimatedSprite::Animations animation)
ResourceAnimation(std::string name, std::vector<SurfaceAnimatedSprite::AnimationData> animations, std::shared_ptr<Surface> surface, float frame_width, float frame_height)
: name(std::move(name)),
animation(std::move(animation)) {}
animations(std::move(animations)),
surface(std::move(surface)),
frame_width(frame_width),
frame_height(frame_height) {}
};
// Estructura para almacenar ficheros con el mapa de tiles de una habitación y su nombre
@@ -244,8 +250,8 @@ class Cache {
// Obtiene el objeto de texto a partir de un nombre
auto getText(const std::string& name) -> std::shared_ptr<Text>;
// Obtiene la animación a partir de un nombre
auto getAnimations(const std::string& name) -> SurfaceAnimatedSprite::Animations&;
// Obtiene los datos de animación parseados a partir de un nombre
auto getAnimationData(const std::string& name) -> const ResourceAnimation&;
// Obtiene el mapa de tiles a partir de un nombre
auto getTileMap(const std::string& name) -> std::vector<int>&;

View File

@@ -10,8 +10,7 @@
// Constructor
Enemy::Enemy(const Data& enemy)
// [DOC:29/10/2025] la surface ara se pillarà del .ANI
: sprite_(std::make_shared<SurfaceAnimatedSprite>(/*Resource::Cache::get()->getSurface(enemy.surface_path), */ Resource::Cache::get()->getAnimations(enemy.animation_path))),
: sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimationData(enemy.animation_path))),
color_string_(enemy.color),
x1_(enemy.x1),
x2_(enemy.x2),

View File

@@ -809,8 +809,8 @@ void Player::applySpawnValues(const SpawnData& spawn) {
// Inicializa el sprite del jugador
void Player::initSprite(const std::string& animations_path) {
auto animations = Resource::Cache::get()->getAnimations(animations_path);
sprite_ = std::make_unique<SurfaceAnimatedSprite>(animations);
const auto& animation_data = Resource::Cache::get()->getAnimationData(animations_path);
sprite_ = std::make_unique<SurfaceAnimatedSprite>(animation_data);
sprite_->setWidth(WIDTH);
sprite_->setHeight(HEIGHT);
sprite_->setCurrentAnimation("walk");

View File

@@ -21,9 +21,8 @@ Scoreboard::Scoreboard(std::shared_ptr<Data> data)
constexpr float SURFACE_HEIGHT = 6.0F * TILE_SIZE;
// Reserva memoria para los objetos
// auto player_texture = Resource::Cache::get()->getSurface(Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.gif" : "player.gif");
auto player_animations = Resource::Cache::get()->getAnimations(Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.yaml" : "player.yaml");
player_sprite_ = std::make_shared<SurfaceAnimatedSprite>(player_animations);
const auto& player_animation_data = Resource::Cache::get()->getAnimationData(Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.yaml" : "player.yaml");
player_sprite_ = std::make_shared<SurfaceAnimatedSprite>(player_animation_data);
player_sprite_->setCurrentAnimation("walk_menu");
surface_ = std::make_shared<Surface>(SURFACE_WIDTH, SURFACE_HEIGHT);

View File

@@ -23,7 +23,7 @@
Credits::Credits()
: text_surface_(std::make_shared<Surface>(Options::game.width, Options::game.height)),
cover_surface_(std::make_shared<Surface>(Options::game.width, Options::game.height)),
shining_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimations("shine.yaml"))),
shining_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimationData("shine.yaml"))),
delta_timer_(std::make_unique<DeltaTimer>()) {
// Configura la escena
SceneManager::current = SceneManager::Scene::CREDITS;

View File

@@ -287,7 +287,8 @@ void Ending2::loadSprites() {
// Carga los sprites
for (const auto& file : sprite_list_) {
sprites_.emplace_back(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimations(file + ".yaml")));
const auto& animation_data = Resource::Cache::get()->getAnimationData(file + ".yaml");
sprites_.emplace_back(std::make_shared<SurfaceAnimatedSprite>(animation_data));
sprite_max_width_ = std::max(sprites_.back()->getWidth(), sprite_max_width_);
sprite_max_height_ = std::max(sprites_.back()->getHeight(), sprite_max_height_);
}

View File

@@ -21,8 +21,8 @@
// Constructor
GameOver::GameOver()
: player_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimations("player_game_over.yaml"))),
tv_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimations("tv.yaml"))),
: player_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimationData("player_game_over.yaml"))),
tv_sprite_(std::make_shared<SurfaceAnimatedSprite>(Resource::Cache::get()->getAnimationData("tv.yaml"))),
delta_timer_(std::make_shared<DeltaTimer>()) {
SceneManager::current = SceneManager::Scene::GAME_OVER;
SceneManager::options = SceneManager::Options::NONE;