migrant .ani a .yaml
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>&;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user