129 lines
4.1 KiB
C++
129 lines
4.1 KiB
C++
#include "tiled_bg.h"
|
|
|
|
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_CreateTexture, SDL_DestroyTexture, SDL_FRect, SDL_GetRenderTarget, SDL_RenderTexture, SDL_PixelFormat, SDL_TextureAccess
|
|
#include <cmath> // Para sin
|
|
#include <cstdlib> // Para rand
|
|
#include <memory> // Para allocator, unique_ptr, make_unique
|
|
#include <numbers> // Para pi
|
|
|
|
#include "resource.h" // Para Resource
|
|
#include "screen.h" // Para Screen
|
|
#include "sprite.h" // Para Sprite
|
|
|
|
// Constructor
|
|
TiledBG::TiledBG(SDL_FRect pos, TiledBGMode mode)
|
|
: renderer_(Screen::get()->getRenderer()),
|
|
pos_(pos),
|
|
mode_(mode == TiledBGMode::RANDOM ? static_cast<TiledBGMode>(rand() % 2) : mode) {
|
|
// Crea la textura para el mosaico de fondo
|
|
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, pos_.w * 2, pos_.h * 2);
|
|
|
|
// Rellena la textura con el contenido
|
|
fillTexture();
|
|
|
|
// Inicializa variables
|
|
switch (mode_) {
|
|
case TiledBGMode::STATIC:
|
|
window_ = {0, 0, pos_.w, pos_.h};
|
|
speed_ = 0.0F;
|
|
break;
|
|
case TiledBGMode::DIAGONAL:
|
|
window_ = {0, 0, pos_.w, pos_.h};
|
|
break;
|
|
case TiledBGMode::CIRCLE:
|
|
window_ = {128, 128, pos_.w, pos_.h};
|
|
break;
|
|
default:
|
|
window_ = {0, 0, pos_.w, pos_.h};
|
|
break;
|
|
}
|
|
|
|
// Inicializa los valores del vector con los valores del seno
|
|
for (int i = 0; i < 360; ++i) {
|
|
sin_[i] = std::sin(i * std::numbers::pi / 180.0); // Convierte grados a radianes y calcula el seno
|
|
}
|
|
}
|
|
|
|
// Destructor
|
|
TiledBG::~TiledBG() {
|
|
SDL_DestroyTexture(canvas_);
|
|
}
|
|
|
|
// Rellena la textura con el contenido
|
|
void TiledBG::fillTexture() {
|
|
// Crea los objetos para pintar en la textura de fondo
|
|
auto tile = std::make_unique<Sprite>(Resource::get()->getTexture("title_bg_tile.png"), (SDL_FRect){0, 0, TILE_WIDTH, TILE_HEIGHT});
|
|
|
|
// Prepara para dibujar sobre la textura
|
|
auto *temp = SDL_GetRenderTarget(renderer_);
|
|
SDL_SetRenderTarget(renderer_, canvas_);
|
|
|
|
// Rellena la textura con el tile
|
|
const auto I_MAX = pos_.w * 2 / TILE_WIDTH;
|
|
const auto J_MAX = pos_.h * 2 / TILE_HEIGHT;
|
|
tile->setSpriteClip(0, 0, TILE_WIDTH, TILE_HEIGHT);
|
|
for (int i = 0; i < I_MAX; ++i) {
|
|
for (int j = 0; j < J_MAX; ++j) {
|
|
tile->setX(i * TILE_WIDTH);
|
|
tile->setY(j * TILE_HEIGHT);
|
|
tile->render();
|
|
}
|
|
}
|
|
|
|
// Vuelve a colocar el renderizador como estaba
|
|
SDL_SetRenderTarget(renderer_, temp);
|
|
}
|
|
|
|
// Pinta la clase en pantalla
|
|
void TiledBG::render() {
|
|
SDL_RenderTexture(renderer_, canvas_, &window_, &pos_);
|
|
}
|
|
|
|
// Actualiza la lógica de la clase
|
|
void TiledBG::update() {
|
|
updateDesp();
|
|
updateStop();
|
|
|
|
switch (mode_) {
|
|
case TiledBGMode::DIAGONAL: {
|
|
// El tileado de fondo se desplaza en diagonal
|
|
window_.x = static_cast<int>(desp_) % TILE_WIDTH;
|
|
window_.y = static_cast<int>(desp_) % TILE_HEIGHT;
|
|
|
|
break;
|
|
}
|
|
case TiledBGMode::CIRCLE: {
|
|
// El tileado de fondo se desplaza en circulo
|
|
const int INDEX = static_cast<int>(desp_) % 360;
|
|
|
|
window_.x = 128 + (static_cast<int>(sin_[(INDEX + 270) % 360] * 128));
|
|
window_.y = 128 + (static_cast<int>(sin_[(360 - INDEX) % 360] * 96));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Detiene el desplazamiento de forma ordenada
|
|
void TiledBG::updateStop() {
|
|
if (stopping_) {
|
|
const int UMBRAL = 20 * speed_; // Ajusta este valor según la precisión deseada
|
|
|
|
// Desacelerar si estamos cerca de completar el ciclo (ventana a punto de regresar a 0)
|
|
if (window_.x >= TILE_WIDTH - UMBRAL) {
|
|
speed_ /= 1.05F; // Reduce gradualmente la velocidad
|
|
|
|
// Asegura que no baje demasiado
|
|
if (speed_ < 0.1F) {
|
|
speed_ = 0.1F;
|
|
}
|
|
}
|
|
|
|
// Si estamos en 0, detener
|
|
if (window_.x == 0) {
|
|
speed_ = 0.0F;
|
|
stopping_ = false; // Desactivamos el estado de "stopping"
|
|
}
|
|
}
|
|
} |