treballant en la visió original de la intro
This commit is contained in:
203
source/card_sprite.cpp
Normal file
203
source/card_sprite.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
#include "card_sprite.hpp"
|
||||
|
||||
#include <algorithm> // Para std::clamp
|
||||
#include <functional> // Para function
|
||||
#include <utility> // Para move
|
||||
|
||||
#include "texture.hpp" // Para Texture
|
||||
#include "utils.hpp" // Para easeOutBounce
|
||||
|
||||
// Constructor
|
||||
CardSprite::CardSprite(std::shared_ptr<Texture> texture)
|
||||
: MovingSprite(std::move(texture)),
|
||||
entry_easing_(easeOutBounce) {}
|
||||
|
||||
// Inicia la animación de entrada (solo si está en IDLE)
|
||||
void CardSprite::enable() {
|
||||
if (state_ != CardState::IDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
state_ = CardState::ENTERING;
|
||||
entry_elapsed_ = 0.0F;
|
||||
|
||||
// Posición fija en el punto de aterrizaje
|
||||
setPos(landing_x_, landing_y_);
|
||||
|
||||
// Zoom inicial grande (como si estuviera cerca de la cámara)
|
||||
horizontal_zoom_ = start_zoom_;
|
||||
vertical_zoom_ = start_zoom_;
|
||||
|
||||
// Ángulo inicial
|
||||
rotate_.angle = start_angle_;
|
||||
rotate_.center = {pos_.w / 2.0F, pos_.h / 2.0F};
|
||||
|
||||
shadow_visible_ = true;
|
||||
}
|
||||
|
||||
// Inicia la animación de salida (solo si está en LANDED)
|
||||
void CardSprite::startExit() {
|
||||
if (state_ != CardState::LANDED) {
|
||||
return;
|
||||
}
|
||||
|
||||
state_ = CardState::EXITING;
|
||||
shadow_visible_ = false;
|
||||
|
||||
// Velocidad y aceleración de salida
|
||||
vx_ = exit_vx_;
|
||||
vy_ = exit_vy_;
|
||||
ax_ = exit_ax_;
|
||||
ay_ = exit_ay_;
|
||||
|
||||
// Rotación continua
|
||||
rotate_.enabled = true;
|
||||
rotate_.amount = exit_rotate_amount_;
|
||||
rotate_.center = {pos_.w / 2.0F, pos_.h / 2.0F};
|
||||
}
|
||||
|
||||
// Actualiza según el estado
|
||||
void CardSprite::update(float delta_time) {
|
||||
switch (state_) {
|
||||
case CardState::ENTERING:
|
||||
updateEntering(delta_time);
|
||||
break;
|
||||
case CardState::EXITING:
|
||||
updateExiting(delta_time);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Animación de entrada: interpola zoom y ángulo con easing
|
||||
void CardSprite::updateEntering(float delta_time) {
|
||||
entry_elapsed_ += delta_time;
|
||||
|
||||
float progress = std::clamp(entry_elapsed_ / entry_duration_s_, 0.0F, 1.0F);
|
||||
double eased = entry_easing_(static_cast<double>(progress));
|
||||
|
||||
// Zoom: de start_zoom_ a 1.0 con rebote
|
||||
auto current_zoom = static_cast<float>(start_zoom_ + (1.0 - start_zoom_) * eased);
|
||||
horizontal_zoom_ = current_zoom;
|
||||
vertical_zoom_ = current_zoom;
|
||||
|
||||
// Ángulo: de start_angle_ a 0 con rebote
|
||||
rotate_.angle = start_angle_ * (1.0 - eased);
|
||||
|
||||
// Offset de sombra escalado con el zoom (perspectiva)
|
||||
// (se aplica en renderShadow)
|
||||
|
||||
// Transición a LANDED cuando termina la animación
|
||||
if (progress >= 1.0F) {
|
||||
horizontal_zoom_ = 1.0F;
|
||||
vertical_zoom_ = 1.0F;
|
||||
rotate_.angle = 0.0;
|
||||
state_ = CardState::LANDED;
|
||||
}
|
||||
}
|
||||
|
||||
// Animación de salida: movimiento + rotación continua
|
||||
void CardSprite::updateExiting(float delta_time) {
|
||||
move(delta_time);
|
||||
rotate(delta_time);
|
||||
|
||||
if (isOffScreen()) {
|
||||
state_ = CardState::FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
// Renderiza el sprite y su sombra
|
||||
void CardSprite::render() {
|
||||
if (state_ == CardState::IDLE || state_ == CardState::FINISHED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sombra primero (debajo de la tarjeta)
|
||||
if (shadow_visible_ && shadow_texture_) {
|
||||
renderShadow();
|
||||
}
|
||||
|
||||
// Tarjeta
|
||||
MovingSprite::render();
|
||||
}
|
||||
|
||||
// Renderiza la sombra con el mismo zoom y rotación que la tarjeta
|
||||
void CardSprite::renderShadow() {
|
||||
// Offset de sombra escalado con el zoom para efecto de perspectiva
|
||||
float scaled_offset_x = shadow_offset_x_ * horizontal_zoom_;
|
||||
float scaled_offset_y = shadow_offset_y_ * vertical_zoom_;
|
||||
|
||||
shadow_texture_->render(
|
||||
pos_.x + scaled_offset_x,
|
||||
pos_.y + scaled_offset_y,
|
||||
&sprite_clip_,
|
||||
horizontal_zoom_,
|
||||
vertical_zoom_,
|
||||
rotate_.angle,
|
||||
&rotate_.center,
|
||||
flip_);
|
||||
}
|
||||
|
||||
// Comprueba si el sprite está fuera de pantalla
|
||||
auto CardSprite::isOffScreen() const -> bool {
|
||||
// Considerar el zoom: el sprite puede ser más grande de lo que indica pos_
|
||||
float effective_width = pos_.w * horizontal_zoom_;
|
||||
float effective_height = pos_.h * vertical_zoom_;
|
||||
return (pos_.x + effective_width < -OFF_SCREEN_MARGIN ||
|
||||
pos_.x > screen_width_ + OFF_SCREEN_MARGIN ||
|
||||
pos_.y + effective_height < -OFF_SCREEN_MARGIN ||
|
||||
pos_.y > screen_height_ + OFF_SCREEN_MARGIN);
|
||||
}
|
||||
|
||||
// --- Consultas de estado ---
|
||||
auto CardSprite::hasLanded() const -> bool {
|
||||
return state_ == CardState::LANDED || state_ == CardState::EXITING || state_ == CardState::FINISHED;
|
||||
}
|
||||
|
||||
auto CardSprite::hasFinished() const -> bool {
|
||||
return state_ == CardState::FINISHED;
|
||||
}
|
||||
|
||||
auto CardSprite::isExiting() const -> bool {
|
||||
return state_ == CardState::EXITING;
|
||||
}
|
||||
|
||||
auto CardSprite::getState() const -> CardState {
|
||||
return state_;
|
||||
}
|
||||
|
||||
// --- Configuración ---
|
||||
void CardSprite::setEntryParams(float start_zoom, double start_angle, float duration_s, std::function<double(double)> easing) {
|
||||
start_zoom_ = start_zoom;
|
||||
start_angle_ = start_angle;
|
||||
entry_duration_s_ = duration_s;
|
||||
entry_easing_ = std::move(easing);
|
||||
}
|
||||
|
||||
void CardSprite::setLandingPosition(float x, float y) {
|
||||
landing_x_ = x;
|
||||
landing_y_ = y;
|
||||
}
|
||||
|
||||
void CardSprite::setExitParams(float vx, float vy, float ax, float ay, double rotate_amount) {
|
||||
exit_vx_ = vx;
|
||||
exit_vy_ = vy;
|
||||
exit_ax_ = ax;
|
||||
exit_ay_ = ay;
|
||||
exit_rotate_amount_ = rotate_amount;
|
||||
}
|
||||
|
||||
void CardSprite::setShadowTexture(std::shared_ptr<Texture> texture) {
|
||||
shadow_texture_ = std::move(texture);
|
||||
}
|
||||
|
||||
void CardSprite::setShadowOffset(float offset_x, float offset_y) {
|
||||
shadow_offset_x_ = offset_x;
|
||||
shadow_offset_y_ = offset_y;
|
||||
}
|
||||
|
||||
void CardSprite::setScreenBounds(float width, float height) {
|
||||
screen_width_ = width;
|
||||
screen_height_ = height;
|
||||
}
|
||||
Reference in New Issue
Block a user