549 lines
22 KiB
C++
549 lines
22 KiB
C++
#define _USE_MATH_DEFINES
|
|
#include "background.h"
|
|
|
|
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_SetRenderTarget, SDL_CreateTexture, SDL_DestroyTexture, SDL_GetRenderTarget, SDL_RenderTexture, SDL_SetTextureAlphaMod, SDL_SetTextureBlendMode, SDL_BLENDMODE_BLEND, SDL_PixelFormat, SDL_RenderClear, SDL_SetRenderDrawColor, SDL_TextureAccess, SDL_FPoint
|
|
|
|
#include <algorithm> // Para clamp, max
|
|
#include <cmath> // Para M_PI, cos, sin
|
|
#include <utility>
|
|
|
|
#include "animated_sprite.h" // Para MovingSprite
|
|
#include "moving_sprite.h" // Para MovingSprite
|
|
#include "param.h" // Para Param, ParamBackground, param
|
|
#include "resource.h" // Para Resource
|
|
#include "screen.h" // Para Screen
|
|
#include "sprite.h" // Para Sprite
|
|
#include "texture.h" // Para Texture
|
|
#include "utils.h" // Para funciones de easing
|
|
|
|
// Constructor
|
|
Background::Background(float total_progress_to_complete)
|
|
: renderer_(Screen::get()->getRenderer()),
|
|
|
|
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
|
|
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
|
|
bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")),
|
|
gradients_texture_(Resource::get()->getTexture("game_sky_colors.png")),
|
|
sun_texture_(Resource::get()->getTexture("game_sun.png")),
|
|
moon_texture_(Resource::get()->getTexture("game_moon.png")),
|
|
grass_sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("game_grass.png"), Resource::get()->getAnimation("game_grass.ani"))),
|
|
|
|
total_progress_to_complete_(total_progress_to_complete),
|
|
progress_per_stage_(total_progress_to_complete_ / STAGES),
|
|
sun_completion_progress_(total_progress_to_complete_ * SUN_COMPLETION_FACTOR),
|
|
minimum_completed_progress_(total_progress_to_complete_ * MINIMUM_COMPLETED_PROGRESS_PERCENTAGE),
|
|
|
|
rect_(SDL_FRect{0, 0, static_cast<float>(gradients_texture_->getWidth() / 2), static_cast<float>(gradients_texture_->getHeight() / 2)}),
|
|
src_rect_({.x = 0, .y = 0, .w = 320, .h = 240}),
|
|
dst_rect_({.x = 0, .y = 0, .w = 320, .h = 240}),
|
|
attenuate_color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
|
|
|
|
alpha_color_texture_(param.background.attenuate_color.a),
|
|
previous_alpha_color_texture_(param.background.attenuate_color.a),
|
|
base_(rect_.h) {
|
|
initializePaths();
|
|
initializeRects();
|
|
initializeSprites();
|
|
initializeSpriteProperties();
|
|
initializeTextures();
|
|
}
|
|
|
|
// Destructor
|
|
Background::~Background() {
|
|
SDL_DestroyTexture(canvas_);
|
|
SDL_DestroyTexture(color_texture_);
|
|
}
|
|
|
|
// Inicializa las rutas del sol y la luna
|
|
void Background::initializePaths() {
|
|
createSunPath();
|
|
createMoonPath();
|
|
}
|
|
|
|
// Inicializa los rectángulos de gradientes y nubes
|
|
void Background::initializeRects() {
|
|
gradient_rect_[0] = {.x = 0, .y = 0, .w = rect_.w, .h = rect_.h};
|
|
gradient_rect_[1] = {.x = rect_.w, .y = 0, .w = rect_.w, .h = rect_.h};
|
|
gradient_rect_[2] = {.x = 0, .y = rect_.h, .w = rect_.w, .h = rect_.h};
|
|
gradient_rect_[3] = {.x = rect_.w, .y = rect_.h, .w = rect_.w, .h = rect_.h};
|
|
|
|
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
|
|
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
top_clouds_rect_[i] = {.x = 0, .y = i * TOP_CLOUDS_TEXTURE_HEIGHT, .w = static_cast<float>(top_clouds_texture_->getWidth()), .h = TOP_CLOUDS_TEXTURE_HEIGHT};
|
|
bottom_clouds_rect_[i] = {.x = 0, .y = i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, .w = static_cast<float>(bottom_clouds_texture_->getWidth()), .h = BOTTOM_CLOUDS_TEXTURE_HEIGHT};
|
|
}
|
|
}
|
|
|
|
// Crea los sprites
|
|
void Background::initializeSprites() {
|
|
const float TOP_CLOUDS_Y = base_ - 165;
|
|
const float BOTTOM_CLOUDS_Y = base_ - 101;
|
|
|
|
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){0, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
|
|
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){rect_.w, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
|
|
|
|
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){0, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
|
|
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){rect_.w, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
|
|
|
|
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_);
|
|
gradient_sprite_ = std::make_unique<Sprite>(gradients_texture_, 0, 0, rect_.w, rect_.h);
|
|
sun_sprite_ = std::make_unique<Sprite>(sun_texture_);
|
|
moon_sprite_ = std::make_unique<Sprite>(moon_texture_);
|
|
}
|
|
|
|
// Configura las propiedades iniciales de los sprites
|
|
void Background::initializeSpriteProperties() {
|
|
// Velocidades iniciales que coinciden con updateCloudsSpeed() cuando progress=0
|
|
constexpr float INITIAL_TOP_CLOUDS_SPEED_PX_PER_S = 0.05F * 60.0F; // 3.0 píxeles/segundo (coincide con CLOUDS_INITIAL_SPEED)
|
|
constexpr float INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S = 0.05F * 60.0F / 2.0F; // 1.5 píxeles/segundo (mitad de velocidad)
|
|
|
|
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
|
|
top_clouds_sprite_a_->setVelX(-INITIAL_TOP_CLOUDS_SPEED_PX_PER_S);
|
|
|
|
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
|
|
top_clouds_sprite_b_->setVelX(-INITIAL_TOP_CLOUDS_SPEED_PX_PER_S);
|
|
|
|
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
|
|
bottom_clouds_sprite_a_->setVelX(-INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S);
|
|
|
|
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
|
|
bottom_clouds_sprite_b_->setVelX(-INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S);
|
|
|
|
// grass_sprite_->setY(base_ - grass_sprite_->getHeight());
|
|
// grass_sprite_->resetAnimation();
|
|
grass_sprite_->setPos(0.0F, base_ - 10.0F);
|
|
grass_sprite_->setWidth(320.0F);
|
|
grass_sprite_->setHeight(10.0F);
|
|
//grass_sprite_->setCurrentAnimation(0);
|
|
|
|
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
|
|
sun_sprite_->setPosition(sun_path_.front());
|
|
moon_sprite_->setPosition(moon_path_.front());
|
|
}
|
|
|
|
// Inicializa las texturas de renderizado
|
|
void Background::initializeTextures() {
|
|
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
|
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
|
|
|
|
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
|
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
|
|
setColor(attenuate_color_);
|
|
SDL_SetTextureAlphaMod(color_texture_, alpha_color_texture_);
|
|
}
|
|
|
|
// Actualiza la lógica del objeto
|
|
void Background::update(float delta_time) {
|
|
// Actualiza la progresión y calcula transiciones
|
|
if (!manual_mode_) {
|
|
updateProgression(delta_time);
|
|
}
|
|
|
|
// Actualiza el valor de alpha
|
|
updateAlphaColorTexture();
|
|
|
|
// Actualiza las nubes
|
|
updateClouds(delta_time);
|
|
|
|
// Actualiza el sprite con la hierba
|
|
grass_sprite_->update(delta_time);
|
|
|
|
// Calcula el valor de alpha
|
|
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
|
|
|
|
// Mueve el sol y la luna según la progresión
|
|
sun_sprite_->setPosition(sun_path_.at(sun_index_));
|
|
moon_sprite_->setPosition(moon_path_.at(moon_index_));
|
|
|
|
// Compone todos los elementos del fondo en la textura
|
|
fillCanvas();
|
|
}
|
|
|
|
// Incrementa la progresión interna
|
|
void Background::incrementProgress(float amount) {
|
|
if (state_ == State::NORMAL) {
|
|
float old_progress = progress_;
|
|
progress_ += amount;
|
|
progress_ = std::min(progress_, total_progress_to_complete_);
|
|
|
|
// Notifica el cambio si hay callback y el progreso cambió
|
|
if (progress_callback_ && progress_ != old_progress) {
|
|
progress_callback_(progress_);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Establece la progresión absoluta
|
|
void Background::setProgress(float absolute_progress) {
|
|
float old_progress = progress_;
|
|
progress_ = std::clamp(absolute_progress, 0.0F, total_progress_to_complete_);
|
|
|
|
// Notifica el cambio si hay callback y el progreso cambió
|
|
if (progress_callback_ && progress_ != old_progress) {
|
|
progress_callback_(progress_);
|
|
}
|
|
}
|
|
|
|
// Cambia el estado del fondo
|
|
void Background::setState(State new_state) {
|
|
// Si entra en estado completado, inicializar variables de transición
|
|
if (new_state == State::COMPLETED && state_ != State::COMPLETED) {
|
|
completion_initial_progress_ = progress_;
|
|
completion_transition_timer_ = 0.0f;
|
|
}
|
|
|
|
state_ = new_state;
|
|
}
|
|
|
|
// Reinicia la progresión
|
|
void Background::reset() {
|
|
float old_progress = progress_;
|
|
progress_ = 0.0F;
|
|
state_ = State::NORMAL;
|
|
manual_mode_ = false;
|
|
gradient_number_ = 0;
|
|
transition_ = 0.0F;
|
|
sun_index_ = 0;
|
|
moon_index_ = 0;
|
|
|
|
// Resetear variables de transición de completado
|
|
completion_transition_timer_ = 0.0f;
|
|
completion_initial_progress_ = 0.0f;
|
|
|
|
// Notifica el cambio si hay callback
|
|
if (progress_callback_ && progress_ != old_progress) {
|
|
progress_callback_(progress_);
|
|
}
|
|
}
|
|
|
|
// Activa/desactiva el modo manual
|
|
void Background::setManualMode(bool manual) {
|
|
manual_mode_ = manual;
|
|
}
|
|
|
|
// Establece callback para sincronización automática
|
|
void Background::setProgressCallback(ProgressCallback callback) {
|
|
progress_callback_ = std::move(callback);
|
|
}
|
|
|
|
// Elimina el callback
|
|
void Background::removeProgressCallback() {
|
|
progress_callback_ = nullptr;
|
|
}
|
|
|
|
// Ajusta la velocidad de las nubes
|
|
void Background::setCloudsSpeed(float value) {
|
|
clouds_speed_ = value;
|
|
|
|
// En modo manual, aplicar la velocidad directamente
|
|
// Las nubes inferiores van a la mitad de velocidad que las superiores
|
|
top_clouds_sprite_a_->setVelX(value);
|
|
top_clouds_sprite_b_->setVelX(value);
|
|
bottom_clouds_sprite_a_->setVelX(value / 2.0F);
|
|
bottom_clouds_sprite_b_->setVelX(value / 2.0F);
|
|
}
|
|
|
|
// Establece el degradado de fondo
|
|
void Background::setGradientNumber(int value) {
|
|
gradient_number_ = value % STAGES;
|
|
}
|
|
|
|
// Ajusta la transición entre texturas
|
|
void Background::setTransition(float value) {
|
|
transition_ = std::clamp(value, 0.0F, 1.0F);
|
|
}
|
|
|
|
// Establece la posición del sol
|
|
void Background::setSunProgression(float progress) {
|
|
progress = std::clamp(progress, 0.0F, 1.0F);
|
|
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
|
|
}
|
|
|
|
// Establece la posición de la luna
|
|
void Background::setMoonProgression(float progress) {
|
|
progress = std::clamp(progress, 0.0F, 1.0F);
|
|
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
|
|
}
|
|
|
|
// Actualiza la progresión y calcula las transiciones
|
|
void Background::updateProgression(float delta_time) {
|
|
// Si el juego está completado, hacer transición suave con easing
|
|
if (state_ == State::COMPLETED) {
|
|
completion_transition_timer_ += delta_time;
|
|
|
|
// Calcular progreso normalizado de la transición (0.0 a 1.0)
|
|
float t = std::min(completion_transition_timer_ / COMPLETION_TRANSITION_DURATION_S, 1.0f);
|
|
|
|
if (t < 1.0f) {
|
|
// Usar easeOutCubic para transición suave (rápido al inicio, lento al final)
|
|
float eased_t = easeOutCubic(static_cast<double>(t));
|
|
|
|
// Interpolación desde progreso inicial hasta mínimo
|
|
float progress_range = completion_initial_progress_ - minimum_completed_progress_;
|
|
progress_ = completion_initial_progress_ - (progress_range * eased_t);
|
|
} else {
|
|
// Transición completada, fijar al valor mínimo
|
|
progress_ = minimum_completed_progress_;
|
|
}
|
|
}
|
|
|
|
// Calcula la transición de los diferentes fondos
|
|
const float GRADIENT_NUMBER_FLOAT = std::min(progress_ / progress_per_stage_, 3.0F);
|
|
const float PERCENT = GRADIENT_NUMBER_FLOAT - static_cast<int>(GRADIENT_NUMBER_FLOAT);
|
|
|
|
gradient_number_ = static_cast<size_t>(GRADIENT_NUMBER_FLOAT);
|
|
transition_ = PERCENT;
|
|
|
|
// Calcula la posición del sol
|
|
const float SUN_PROGRESSION = std::min(progress_ / sun_completion_progress_, 1.0F);
|
|
sun_index_ = static_cast<size_t>(SUN_PROGRESSION * (sun_path_.size() - 1));
|
|
|
|
// Calcula la posición de la luna
|
|
const float MOON_PROGRESSION = std::min(progress_ / total_progress_to_complete_, 1.0F);
|
|
moon_index_ = static_cast<size_t>(MOON_PROGRESSION * (moon_path_.size() - 1));
|
|
|
|
// Actualiza la velocidad de las nubes
|
|
updateCloudsSpeed();
|
|
}
|
|
|
|
// Actualiza la velocidad de las nubes según el estado y progresión
|
|
void Background::updateCloudsSpeed() {
|
|
// Cálculo de velocidad según progreso (convertido de frame-based a time-based)
|
|
constexpr float CLOUDS_INITIAL_SPEED_PX_PER_S = 0.05F * 60.0F; // 3.0 píxeles/segundo (era 0.05 px/frame @ 60fps)
|
|
constexpr float CLOUDS_TOTAL_SPEED_PX_PER_S = 2.00F * 60.0F; // 120.0 píxeles/segundo (era 2.00 px/frame @ 60fps)
|
|
constexpr float CLOUDS_FINAL_SPEED_RANGE_PX_PER_S = CLOUDS_TOTAL_SPEED_PX_PER_S - CLOUDS_INITIAL_SPEED_PX_PER_S; // 117.0 píxeles/segundo
|
|
|
|
// Velocidad base según progreso (de -3.0 a -120.0 píxeles/segundo, igual que la versión original)
|
|
float base_clouds_speed = (-CLOUDS_INITIAL_SPEED_PX_PER_S) +
|
|
(-CLOUDS_FINAL_SPEED_RANGE_PX_PER_S * (progress_ / total_progress_to_complete_));
|
|
|
|
// En estado completado, las nubes se ralentizan gradualmente
|
|
if (state_ == State::COMPLETED) {
|
|
float completion_factor = (progress_ - minimum_completed_progress_) /
|
|
(total_progress_to_complete_ - minimum_completed_progress_);
|
|
completion_factor = std::max(0.1F, completion_factor);
|
|
base_clouds_speed *= completion_factor;
|
|
}
|
|
|
|
// Aplicar velocidades diferentes para nubes superiores e inferiores
|
|
const float TOP_CLOUDS_SPEED = base_clouds_speed;
|
|
const float BOTTOM_CLOUDS_SPEED = base_clouds_speed / 2.0F;
|
|
|
|
// Aplicar las velocidades a los sprites correspondientes
|
|
top_clouds_sprite_a_->setVelX(TOP_CLOUDS_SPEED);
|
|
top_clouds_sprite_b_->setVelX(TOP_CLOUDS_SPEED);
|
|
bottom_clouds_sprite_a_->setVelX(BOTTOM_CLOUDS_SPEED);
|
|
bottom_clouds_sprite_b_->setVelX(BOTTOM_CLOUDS_SPEED);
|
|
|
|
// Guardar la velocidad principal
|
|
clouds_speed_ = TOP_CLOUDS_SPEED;
|
|
}
|
|
|
|
// Actualiza las nubes
|
|
void Background::updateClouds(float deltaTime) {
|
|
// Mueve las nubes
|
|
top_clouds_sprite_a_->update(deltaTime);
|
|
top_clouds_sprite_b_->update(deltaTime);
|
|
bottom_clouds_sprite_a_->update(deltaTime);
|
|
bottom_clouds_sprite_b_->update(deltaTime);
|
|
|
|
// Calcula el offset de las nubes
|
|
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
|
|
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
|
|
}
|
|
|
|
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
|
|
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
|
|
}
|
|
|
|
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
|
|
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
|
|
}
|
|
|
|
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
|
|
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
|
|
}
|
|
}
|
|
|
|
// Dibuja el gradiente de fondo
|
|
void Background::renderGradient() {
|
|
// Dibuja el gradiente de detras
|
|
gradients_texture_->setAlpha(255);
|
|
gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]);
|
|
gradient_sprite_->render();
|
|
|
|
// Dibuja el gradiente de delante con una opacidad cada vez menor
|
|
gradients_texture_->setAlpha(alpha_);
|
|
gradient_sprite_->setSpriteClip(gradient_rect_[gradient_number_]);
|
|
gradient_sprite_->render();
|
|
}
|
|
|
|
// Dibuja las nubes de arriba
|
|
void Background::renderTopClouds() {
|
|
// Dibuja el primer conjunto de nubes, las de detras
|
|
top_clouds_texture_->setAlpha(255);
|
|
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
|
|
top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
|
|
top_clouds_sprite_a_->render();
|
|
top_clouds_sprite_b_->render();
|
|
|
|
// Dibuja el segundo conjunto de nubes, las de delante
|
|
top_clouds_texture_->setAlpha(alpha_);
|
|
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[gradient_number_]);
|
|
top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[gradient_number_]);
|
|
top_clouds_sprite_a_->render();
|
|
top_clouds_sprite_b_->render();
|
|
}
|
|
|
|
// Dibuja las nubes de abajo
|
|
void Background::renderBottomClouds() {
|
|
// Dibuja el primer conjunto de nubes, las de detras
|
|
bottom_clouds_texture_->setAlpha(255);
|
|
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
|
|
bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
|
|
bottom_clouds_sprite_a_->render();
|
|
bottom_clouds_sprite_b_->render();
|
|
|
|
// Dibuja el segundo conjunto de nubes, las de delante
|
|
bottom_clouds_texture_->setAlpha(alpha_);
|
|
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
|
|
bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
|
|
bottom_clouds_sprite_a_->render();
|
|
bottom_clouds_sprite_b_->render();
|
|
}
|
|
|
|
// Compone todos los elementos del fondo en la textura
|
|
void Background::fillCanvas() {
|
|
// Cambia el destino del renderizador
|
|
auto* temp = SDL_GetRenderTarget(renderer_);
|
|
SDL_SetRenderTarget(renderer_, canvas_);
|
|
|
|
// Dibuja el gradiente de fondo
|
|
renderGradient();
|
|
|
|
// Dibuja los astros
|
|
sun_sprite_->render();
|
|
moon_sprite_->render();
|
|
|
|
// Dibuja las nubes de arriba
|
|
renderTopClouds();
|
|
|
|
// Dibuja las nubes de abajo
|
|
renderBottomClouds();
|
|
|
|
// Dibuja los edificios
|
|
buildings_sprite_->render();
|
|
|
|
// Dibuja la hierba
|
|
grass_sprite_->render();
|
|
|
|
// Deja el renderizador apuntando donde estaba
|
|
SDL_SetRenderTarget(renderer_, temp);
|
|
}
|
|
|
|
// Dibuja el objeto
|
|
void Background::render() {
|
|
// Fondo
|
|
SDL_RenderTexture(renderer_, canvas_, &src_rect_, &dst_rect_);
|
|
|
|
// Atenuación
|
|
SDL_RenderTexture(renderer_, color_texture_, &src_rect_, &dst_rect_);
|
|
}
|
|
|
|
// Establece la posición del objeto
|
|
void Background::setPos(SDL_FRect pos) {
|
|
dst_rect_ = pos;
|
|
|
|
// Si cambian las medidas del destino, hay que cambiar las del origen para evitar deformar la imagen
|
|
src_rect_.x = 0;
|
|
src_rect_.y = rect_.h - pos.h;
|
|
src_rect_.w = pos.w;
|
|
src_rect_.h = pos.h;
|
|
}
|
|
|
|
// Establece el color de atenuación
|
|
void Background::setColor(Color color) {
|
|
attenuate_color_ = color;
|
|
|
|
// Colorea la textura
|
|
auto* temp = SDL_GetRenderTarget(renderer_);
|
|
SDL_SetRenderTarget(renderer_, color_texture_);
|
|
|
|
SDL_SetRenderDrawColor(renderer_, attenuate_color_.r, attenuate_color_.g, attenuate_color_.b, 255);
|
|
SDL_RenderClear(renderer_);
|
|
|
|
SDL_SetRenderTarget(renderer_, temp);
|
|
}
|
|
|
|
// Establece la transparencia de la atenuación
|
|
void Background::setAlpha(int alpha) {
|
|
// Evita que se asignen valores fuera de rango
|
|
alpha = std::clamp(alpha, 0, 255);
|
|
|
|
// Guarda el valor actual y establece el nuevo valor
|
|
previous_alpha_color_texture_ = alpha_color_texture_;
|
|
alpha_color_texture_ = alpha;
|
|
}
|
|
|
|
// Actualiza el valor de alpha
|
|
void Background::updateAlphaColorTexture() {
|
|
if (alpha_color_texture_ == previous_alpha_color_texture_) {
|
|
return;
|
|
}
|
|
alpha_color_texture_ > previous_alpha_color_texture_ ? ++previous_alpha_color_texture_ : --previous_alpha_color_texture_;
|
|
SDL_SetTextureAlphaMod(color_texture_, previous_alpha_color_texture_);
|
|
}
|
|
|
|
// Precalcula el vector con el recorrido del sol
|
|
void Background::createSunPath() {
|
|
constexpr float CENTER_X = 170;
|
|
const float CENTER_Y = base_ - 80;
|
|
constexpr float RADIUS = 120;
|
|
|
|
// Generar puntos de la curva desde 90 a 180 grados
|
|
constexpr double STEP = 0.01;
|
|
const int NUM_STEPS = static_cast<int>((M_PI - M_PI / 2) / STEP) + 1;
|
|
|
|
for (int i = 0; i < NUM_STEPS; ++i) {
|
|
double theta = M_PI / 2 + (i * STEP);
|
|
float x = CENTER_X + (RADIUS * cos(theta));
|
|
float y = CENTER_Y - (RADIUS * sin(theta));
|
|
sun_path_.push_back({x, y});
|
|
}
|
|
|
|
// Agregar puntos en línea recta después de la curva
|
|
constexpr int EXTRA_PIXELS = 40;
|
|
SDL_FPoint last_point = sun_path_.back();
|
|
for (int i = 1; i <= EXTRA_PIXELS; ++i) {
|
|
sun_path_.push_back({last_point.x, last_point.y + i});
|
|
}
|
|
}
|
|
|
|
// Precalcula el vector con el recorrido de la luna
|
|
void Background::createMoonPath() {
|
|
constexpr float CENTER_X = 100;
|
|
const float CENTER_Y = base_ - 50;
|
|
constexpr float RADIUS = 140;
|
|
|
|
constexpr double STEP = 0.01;
|
|
const int NUM_STEPS = static_cast<int>((M_PI / 2) / STEP) + 1;
|
|
|
|
constexpr float FREEZE_PERCENTAGE = 0.2F; // Porcentaje final del recorrido que se mantiene fijo
|
|
|
|
const int FREEZE_START_INDEX = static_cast<int>(NUM_STEPS * (1.0F - FREEZE_PERCENTAGE));
|
|
|
|
for (int i = 0; i < NUM_STEPS; ++i) {
|
|
double theta = i * STEP;
|
|
float x = CENTER_X + (RADIUS * cos(theta));
|
|
float y = CENTER_Y - (RADIUS * sin(theta));
|
|
|
|
if (i >= FREEZE_START_INDEX && !moon_path_.empty()) {
|
|
moon_path_.push_back(moon_path_.back()); // Repite el último punto válido
|
|
} else {
|
|
moon_path_.push_back({x, y});
|
|
}
|
|
}
|
|
}
|