diff --git a/data/player/player_physics.yaml b/data/player/player_physics.yaml new file mode 100644 index 0000000..b86303e --- /dev/null +++ b/data/player/player_physics.yaml @@ -0,0 +1,15 @@ +# Player Physics Configuration +# All velocities in pixels/second +# All accelerations in pixels/second² +# All times in seconds + +# Horizontal movement +walk_velocity: 50.0 # Velocidad al caminar (inmediata) +run_velocity: 80.0 # Velocidad al correr +time_to_run: 0.8 # Segundos caminando antes de empezar a correr +run_acceleration: 150.0 # Aceleración de caminar a correr +horizontal_deceleration: 250.0 # Desaceleración al soltar (momentum) + +# Vertical movement (jump and gravity) +jump_velocity: -160.0 # Impulso de salto (negativo = hacia arriba) +gravity_force: 280.0 # Gravedad aplicada diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index ebb51b7..4982ca1 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -10,6 +10,8 @@ #include "core/input/input.hpp" // Para Input, InputAction #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/resources/resource_cache.hpp" // Para Resource +#include "core/resources/resource_helper.hpp" // Para Resource::Helper +#include "external/fkyaml_node.hpp" // Para fkyaml::node #include "game/defaults.hpp" // Para Defaults::Sound #include "game/gameplay/room.hpp" // Para Room, TileType #include "game/options.hpp" // Para Cheat, Options, options @@ -23,6 +25,7 @@ // Constructor Player::Player(const Data& player) : room_(player.room) { + loadPhysicsConfig("player_physics.yaml"); initSprite(player.animations_path); setColor(); applySpawnValues(player.spawn_data); @@ -122,7 +125,7 @@ void Player::transitionToState(State state) { break; case State::ON_AIR: if (previous_state_ == State::ON_GROUND) { - vy_ = JUMP_VELOCITY; // Impulso de salto + vy_ = physics_.jump_velocity; // Impulso de salto last_grounded_position_ = y_; Audio::get()->playSound(Defaults::Sound::JUMP, Audio::Group::GAME); } @@ -257,7 +260,7 @@ void Player::switchBorders() { void Player::applyGravity(float delta_time) { // La gravedad se aplica siempre que el jugador está en el aire if (state_ == State::ON_AIR) { - vy_ += GRAVITY_FORCE * delta_time; + vy_ += physics_.gravity_force * delta_time; } } @@ -415,6 +418,54 @@ void Player::initSprite(const std::string& animations_path) { sprite_->setCurrentAnimation("walk"); } +// Carga la configuración de física desde YAML +void Player::loadPhysicsConfig(const std::string& path) { + try { + auto file_data = Resource::Helper::loadFile(path); + std::string yaml_content(file_data.begin(), file_data.end()); + auto yaml = fkyaml::node::deserialize(yaml_content); + + // Cargar valores del YAML (con fallback a valores por defecto si falta alguna clave) + if (yaml.contains("walk_velocity")) { + physics_.walk_velocity = yaml["walk_velocity"].get_value(); + } + if (yaml.contains("run_velocity")) { + physics_.run_velocity = yaml["run_velocity"].get_value(); + } + if (yaml.contains("time_to_run")) { + physics_.time_to_run = yaml["time_to_run"].get_value(); + } + if (yaml.contains("run_acceleration")) { + physics_.run_acceleration = yaml["run_acceleration"].get_value(); + } + if (yaml.contains("horizontal_deceleration")) { + physics_.horizontal_deceleration = yaml["horizontal_deceleration"].get_value(); + } + if (yaml.contains("jump_velocity")) { + physics_.jump_velocity = yaml["jump_velocity"].get_value(); + } + if (yaml.contains("gravity_force")) { + physics_.gravity_force = yaml["gravity_force"].get_value(); + } + +#ifdef _DEBUG + std::cout << "[Player] Physics config loaded: walk=" << physics_.walk_velocity + << " run=" << physics_.run_velocity + << " jump=" << physics_.jump_velocity + << " gravity=" << physics_.gravity_force << std::endl; +#endif + } catch (const std::exception& e) { + std::cerr << "[Player] Error loading physics config from '" << path << "': " << e.what() << std::endl; + std::cerr << "[Player] Using default physics values" << std::endl; + // Los valores por defecto ya están establecidos en PhysicsConfig + } +} + +// Recarga la configuración de física desde el archivo YAML +void Player::reloadPhysics() { + loadPhysicsConfig("player_physics.yaml"); +} + // Actualiza la posición del sprite y las colisiones void Player::syncSpriteAndCollider() { placeSprite(); // Coloca el sprite en la posición del jugador @@ -434,7 +485,7 @@ void Player::placeSprite() { void Player::updateVelocity(float delta_time) { if (auto_movement_) { // La cinta transportadora tiene el control (velocidad fija) - vx_ = RUN_VELOCITY * room_->getConveyorBeltDirection(); + vx_ = physics_.run_velocity * room_->getConveyorBeltDirection(); sprite_->setFlip(vx_ < 0.0F ? Flip::LEFT : Flip::RIGHT); movement_time_ = 0.0F; } else { @@ -442,25 +493,25 @@ void Player::updateVelocity(float delta_time) { switch (wanna_go_) { case Direction::LEFT: movement_time_ += delta_time; - if (movement_time_ < TIME_TO_RUN) { + if (movement_time_ < physics_.time_to_run) { // Caminando: velocidad fija inmediata - vx_ = -WALK_VELOCITY; + vx_ = -physics_.walk_velocity; } else { // Corriendo: acelerar hacia RUN_VELOCITY - vx_ -= RUN_ACCELERATION * delta_time; - vx_ = std::max(vx_, -RUN_VELOCITY); + vx_ -= physics_.run_acceleration * delta_time; + vx_ = std::max(vx_, -physics_.run_velocity); } sprite_->setFlip(Flip::LEFT); break; case Direction::RIGHT: movement_time_ += delta_time; - if (movement_time_ < TIME_TO_RUN) { + if (movement_time_ < physics_.time_to_run) { // Caminando: velocidad fija inmediata - vx_ = WALK_VELOCITY; + vx_ = physics_.walk_velocity; } else { // Corriendo: acelerar hacia RUN_VELOCITY - vx_ += RUN_ACCELERATION * delta_time; - vx_ = std::min(vx_, RUN_VELOCITY); + vx_ += physics_.run_acceleration * delta_time; + vx_ = std::min(vx_, physics_.run_velocity); } sprite_->setFlip(Flip::RIGHT); break; @@ -468,10 +519,10 @@ void Player::updateVelocity(float delta_time) { movement_time_ = 0.0F; // Desacelerar gradualmente (momentum) if (vx_ > 0.0F) { - vx_ -= HORIZONTAL_DECELERATION * delta_time; + vx_ -= physics_.horizontal_deceleration * delta_time; vx_ = std::max(vx_, 0.0F); } else if (vx_ < 0.0F) { - vx_ += HORIZONTAL_DECELERATION * delta_time; + vx_ += physics_.horizontal_deceleration * delta_time; vx_ = std::min(vx_, 0.0F); } break; diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index c5239e1..7bd4be7 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -17,6 +17,10 @@ class Player { public: + // --- Constantes de tamaño --- + static constexpr int WIDTH = 8; // Ancho del jugador en pixels + static constexpr int HEIGHT = 16; // Alto del jugador en pixels + // --- Enums y Structs --- enum class State { ON_GROUND, // En suelo plano o conveyor belt @@ -66,6 +70,7 @@ class Player { [[nodiscard]] auto isAlive() const -> bool { return is_alive_; } // Comprueba si el jugador esta vivo void setPaused(bool value) { is_paused_ = value; } // Pone el jugador en modo pausa auto handleKillingTiles() -> bool; // Comprueba que el jugador no toque ningun tile de los que matan + void reloadPhysics(); // Recarga la configuración de física desde el archivo YAML #ifdef _DEBUG // --- Funciones de debug --- @@ -74,20 +79,18 @@ class Player { #endif private: - // --- Constantes de tamaño --- - static constexpr int WIDTH = 8; // Ancho del jugador en pixels - static constexpr int HEIGHT = 16; // Alto del jugador en pixels + // --- Configuración de física --- + struct PhysicsConfig { + float walk_velocity = 50.0F; // Velocidad al caminar (inmediata) en pixels/segundo + float run_velocity = 80.0F; // Velocidad al correr en pixels/segundo + float time_to_run = 0.8F; // Segundos caminando antes de empezar a correr + float run_acceleration = 150.0F; // Aceleración de caminar a correr en pixels/segundo² + float horizontal_deceleration = 250.0F; // Desaceleración al soltar (momentum) en pixels/segundo² + float jump_velocity = -160.0F; // Impulso de salto en pixels/segundo (más fuerte, menos floaty) + float gravity_force = 280.0F; // Gravedad en pixels/segundo² (más alta, menos floaty) + }; - // --- Constantes de movimiento horizontal --- - static constexpr float WALK_VELOCITY = 50.0F; // Velocidad al caminar (inmediata) en pixels/segundo - static constexpr float RUN_VELOCITY = 80.0F; // Velocidad al correr en pixels/segundo - static constexpr float TIME_TO_RUN = 0.8F; // Segundos caminando antes de empezar a correr - static constexpr float RUN_ACCELERATION = 150.0F; // Aceleración de caminar a correr en pixels/segundo² - static constexpr float HORIZONTAL_DECELERATION = 250.0F; // Desaceleración al soltar (momentum) en pixels/segundo² - - // --- Constantes de salto --- - static constexpr float JUMP_VELOCITY = -160.0F; // Impulso de salto en pixels/segundo (más fuerte, menos floaty) - static constexpr float GRAVITY_FORCE = 280.0F; // Gravedad en pixels/segundo² (más alta, menos floaty) + PhysicsConfig physics_; // Configuración de física cargada desde YAML // --- Objetos y punteros --- std::shared_ptr room_; // Objeto encargado de gestionar cada habitación del juego @@ -139,6 +142,7 @@ class Player { // --- Funciones de inicialización --- void initSprite(const std::string& animations_path); // Inicializa el sprite del jugador void applySpawnValues(const SpawnData& spawn); // Aplica los valores de spawn al jugador + void loadPhysicsConfig(const std::string& path); // Carga la configuración de física desde YAML // --- Funciones de procesamiento de entrada --- void handleInput(); // Comprueba las entradas y modifica variables diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index fdaac1f..d9bcfc7 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -39,10 +39,10 @@ Game::Game(Mode mode) mode_(mode), #ifdef _DEBUG current_room_("03.yaml"), - spawn_data_(Player::SpawnData(25 * Tile::SIZE, 21 * Tile::SIZE, 0, 0, 0, Player::State::ON_GROUND, Flip::LEFT)) + spawn_data_(Player::SpawnData(25 * Tile::SIZE, PlayArea::BOTTOM - Player::HEIGHT - Tile::SIZE, 0, 0, 0, Player::State::ON_GROUND, Flip::LEFT)) #else current_room_("03.yaml"), - spawn_data_(Player::SpawnData(25 * Tile::SIZE, 21 * Tile::SIZE, 0, 0, 0, Player::State::ON_GROUND, Flip::LEFT)) + spawn_data_(Player::SpawnData(25 * Tile::SIZE, PlayArea::BOTTOM - Player::HEIGHT - Tile::SIZE, 0, 0, 0, Player::State::ON_GROUND, Flip::LEFT)) #endif { // Crea objetos e inicializa variables @@ -418,6 +418,11 @@ void Game::handleDebugEvents(const SDL_Event& event) { Resource::Cache::get()->reload(); break; + case SDLK_P: + player_->reloadPhysics(); + Notifier::get()->show({"PHYSICS RELOADED"}); + break; + case SDLK_W: changeRoom(room_->getRoom(Room::Border::TOP)); break;