fixos en la plataforma mobil

This commit is contained in:
2026-04-08 17:39:19 +02:00
parent 3db74ebd4d
commit 88a822c562
8 changed files with 395 additions and 240 deletions

View File

@@ -1,39 +1,181 @@
#include "game/entities/moving_platform.hpp"
#include <cmath> // Para std::sqrt
#include <cstdlib> // Para rand
#include "core/rendering/sprite/animated_sprite.hpp" // Para AnimatedSprite
#include "core/resources/resource_cache.hpp" // Para Resource
#include "utils/easing_functions.hpp" // Para Easing::*
// Resuelve el nombre de un easing a su función
auto MovingPlatform::resolveEasing(const std::string& name) -> EasingFunc {
if (name == "quadIn") { return Easing::quadIn; }
if (name == "quadOut") { return Easing::quadOut; }
if (name == "quadInOut") { return Easing::quadInOut; }
if (name == "cubicIn") { return Easing::cubicIn; }
if (name == "cubicOut") { return Easing::cubicOut; }
if (name == "cubicInOut") { return Easing::cubicInOut; }
if (name == "sineIn") { return Easing::sineIn; }
if (name == "sineOut") { return Easing::sineOut; }
if (name == "sineInOut") { return Easing::sineInOut; }
return Easing::linear;
}
// Constructor
MovingPlatform::MovingPlatform(const Data& data)
: sprite_(std::make_shared<AnimatedSprite>(Resource::Cache::get()->getAnimationData(data.animation_path))),
x1_(data.x1),
x2_(data.x2),
y1_(data.y1),
y2_(data.y2) {
sprite_->setPosX(data.x);
sprite_->setPosY(data.y);
sprite_->setVelX(data.vx);
sprite_->setVelY(data.vy);
path_(data.path),
speed_(data.speed),
loop_mode_(data.loop),
easing_(resolveEasing(data.easing)) {
// Colocar el sprite en el primer waypoint
if (!path_.empty()) {
sprite_->setPosX(path_[0].x);
sprite_->setPosY(path_[0].y);
}
collider_ = getRect();
// Coloca un frame al azar o el designado
// Frame inicial
sprite_->setCurrentAnimationFrame((data.frame == -1) ? (rand() % sprite_->getCurrentAnimationSize()) : data.frame);
// Calcular longitud del primer segmento
recalcSegmentLength();
}
// Actualiza posición, calcula desplazamiento real del frame
// Índice del waypoint origen del segmento actual
auto MovingPlatform::getSegmentFrom() const -> int {
if (direction_ == 1) {
return current_segment_;
}
// Pingpong retrocediendo: segmento N va de path[N+1] a path[N]
return current_segment_ + 1;
}
// Índice del waypoint destino del segmento actual
auto MovingPlatform::getSegmentTo() const -> int {
if (direction_ == 1) {
if (loop_mode_ == LoopMode::CIRCULAR) {
return (current_segment_ + 1) % static_cast<int>(path_.size());
}
return current_segment_ + 1;
}
// Pingpong retrocediendo
return current_segment_;
}
// Recalcula la longitud del segmento actual
void MovingPlatform::recalcSegmentLength() {
if (path_.size() < 2) {
segment_length_ = 0.0F;
return;
}
int from = getSegmentFrom();
int to = getSegmentTo();
float dx = path_[to].x - path_[from].x;
float dy = path_[to].y - path_[from].y;
segment_length_ = std::sqrt(dx * dx + dy * dy);
}
// Avanza al siguiente segmento
void MovingPlatform::advanceSegment() {
int path_size = static_cast<int>(path_.size());
if (loop_mode_ == LoopMode::PINGPONG) {
if (direction_ == 1) {
if (current_segment_ + 1 >= path_size - 1) {
// Llegamos al final, invertir dirección
direction_ = -1;
current_segment_ = path_size - 2;
} else {
current_segment_++;
}
} else {
if (current_segment_ <= 0) {
// Llegamos al inicio, invertir dirección
direction_ = 1;
current_segment_ = 0;
} else {
current_segment_--;
}
}
} else {
// CIRCULAR
current_segment_ = (current_segment_ + 1) % path_size;
}
segment_progress_ = 0.0F;
recalcSegmentLength();
}
// Actualiza posición de la plataforma siguiendo la ruta
void MovingPlatform::update(float delta_time) {
sprite_->animate(delta_time);
if (path_.size() < 2) {
last_dx_ = 0.0F;
last_dy_ = 0.0F;
return;
}
float old_x = sprite_->getPosX();
float old_y = sprite_->getPosY();
sprite_->update(delta_time);
checkPath();
// Si estamos esperando en un waypoint
if (waiting_) {
wait_timer_ -= delta_time;
if (wait_timer_ <= 0.0F) {
waiting_ = false;
advanceSegment();
} else {
last_dx_ = 0.0F;
last_dy_ = 0.0F;
return;
}
}
// Avanzar por el segmento
if (segment_length_ > 0.0F) {
float distance = speed_ * delta_time;
float delta_progress = distance / segment_length_;
segment_progress_ += delta_progress;
} else {
// Segmento de longitud 0: saltar al siguiente
segment_progress_ = 1.0F;
}
// Comprobar si llegamos al final del segmento
if (segment_progress_ >= 1.0F) {
segment_progress_ = 1.0F;
// Colocar en el waypoint destino exacto
int to = getSegmentTo();
sprite_->setPosX(path_[to].x);
sprite_->setPosY(path_[to].y);
// Comprobar si hay espera en este waypoint
if (path_[to].wait > 0.0F) {
waiting_ = true;
wait_timer_ = path_[to].wait;
} else {
advanceSegment();
}
} else {
// Interpolar posición con easing
float t = easing_(segment_progress_);
int from = getSegmentFrom();
int to = getSegmentTo();
float new_x = path_[from].x + (path_[to].x - path_[from].x) * t;
float new_y = path_[from].y + (path_[to].y - path_[from].y) * t;
sprite_->setPosX(new_x);
sprite_->setPosY(new_y);
}
last_dx_ = sprite_->getPosX() - old_x;
last_dy_ = sprite_->getPosY() - old_y;
collider_ = getRect();
}
@@ -50,17 +192,24 @@ void MovingPlatform::updateAnimation(float delta_time) {
// Resetea la plataforma a su posición inicial (para editor)
void MovingPlatform::resetToInitialPosition(const Data& data) {
sprite_->setPosX(data.x);
sprite_->setPosY(data.y);
sprite_->setVelX(data.vx);
sprite_->setVelY(data.vy);
path_ = data.path;
speed_ = data.speed;
loop_mode_ = data.loop;
easing_ = resolveEasing(data.easing);
x1_ = data.x1;
x2_ = data.x2;
y1_ = data.y1;
y2_ = data.y2;
current_segment_ = 0;
direction_ = 1;
segment_progress_ = 0.0F;
waiting_ = false;
wait_timer_ = 0.0F;
if (!path_.empty()) {
sprite_->setPosX(path_[0].x);
sprite_->setPosY(path_[0].y);
}
collider_ = getRect();
recalcSegmentLength();
}
#endif
@@ -73,24 +222,3 @@ auto MovingPlatform::getRect() -> SDL_FRect {
auto MovingPlatform::getCollider() -> SDL_FRect& {
return collider_;
}
// Comprueba los límites del recorrido para invertir dirección
void MovingPlatform::checkPath() { // NOLINT(readability-make-member-function-const)
if (sprite_->getPosX() > x2_ || sprite_->getPosX() < x1_) {
if (sprite_->getPosX() > x2_) {
sprite_->setPosX(x2_);
} else {
sprite_->setPosX(x1_);
}
sprite_->setVelX(sprite_->getVelX() * (-1));
}
if (sprite_->getPosY() > y2_ || sprite_->getPosY() < y1_) {
if (sprite_->getPosY() > y2_) {
sprite_->setPosY(y2_);
} else {
sprite_->setPosY(y1_);
}
sprite_->setVelY(sprite_->getVelY() * (-1));
}
}