347 lines
11 KiB
C++
347 lines
11 KiB
C++
#include "background.h"
|
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
|
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
|
|
#include <algorithm> // for max, min
|
|
#include <string> // for basic_string
|
|
#include "asset.h" // for Asset
|
|
#include "moving_sprite.h" // for MovingSprite
|
|
#include "param.h" // for param
|
|
#include "sprite.h" // for Sprite
|
|
#include "texture.h" // for Texture
|
|
|
|
// Constructor
|
|
Background::Background(SDL_Renderer *renderer)
|
|
{
|
|
// Copia los punteros
|
|
this->renderer = renderer;
|
|
asset = Asset::get();
|
|
|
|
// Carga las texturas
|
|
buildingsTexture = new Texture(renderer, asset->get("game_buildings.png"));
|
|
topCloudsTexture = new Texture(renderer, asset->get("game_clouds1.png"));
|
|
bottomCloudsTexture = new Texture(renderer, asset->get("game_clouds2.png"));
|
|
grassTexture = new Texture(renderer, asset->get("game_grass.png"));
|
|
gradientsTexture = new Texture(renderer, asset->get("game_sky_colors.png"));
|
|
|
|
// Inicializa variables
|
|
gradientNumber = 0;
|
|
alpha = 0;
|
|
cloudsSpeed = 0;
|
|
transition = 0;
|
|
counter = 0;
|
|
|
|
rect = {0, 0, gradientsTexture->getWidth() / 2, gradientsTexture->getHeight() / 2};
|
|
srcRect = {0, 0, 320, 240};
|
|
dstRect = {0, 0, 320, 240};
|
|
|
|
base = rect.h;
|
|
color = {param.background.attenuateColor.r, param.background.attenuateColor.g, param.background.attenuateColor.b};
|
|
alphaColorText = alphaColorTextTemp = param.background.attenuateAlpha;
|
|
|
|
gradientRect[0] = {0, 0, rect.w, rect.h};
|
|
gradientRect[1] = {rect.w, 0, rect.w, rect.h};
|
|
gradientRect[2] = {0, rect.h, rect.w, rect.h};
|
|
gradientRect[3] = {rect.w, rect.h, rect.w, rect.h};
|
|
|
|
const int topCloudsTextureHeight = topCloudsTexture->getHeight() / 4;
|
|
const int bottomCloudsTextureHeight = bottomCloudsTexture->getHeight() / 4;
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
topCloudsRect[i] = {0, i * topCloudsTextureHeight, topCloudsTexture->getWidth(), topCloudsTextureHeight};
|
|
bottomCloudsRect[i] = {0, i * bottomCloudsTextureHeight, bottomCloudsTexture->getWidth(), bottomCloudsTextureHeight};
|
|
}
|
|
|
|
// Crea los sprites
|
|
const int topClouds_y = base - 165;
|
|
const int bottomClouds_y = base - 101;
|
|
const float topCloudsSpeed = 0.1f;
|
|
const float bottomCloudsSpeed = 0.05f;
|
|
topCloudsSprite_A = new MovingSprite(0, topClouds_y, rect.w, topCloudsTexture->getHeight(), -topCloudsSpeed, 0.0f, 0.0f, 0.0f, topCloudsTexture);
|
|
topCloudsSprite_B = new MovingSprite(rect.w, topClouds_y, rect.w, topCloudsTexture->getHeight(), -topCloudsSpeed, 0.0f, 0.0f, 0.0f, topCloudsTexture);
|
|
|
|
bottomCloudsSprite_A = new MovingSprite(0, bottomClouds_y, rect.w, bottomCloudsTexture->getHeight(), -bottomCloudsSpeed, 0.0f, 0.0f, 0.0f, bottomCloudsTexture);
|
|
bottomCloudsSprite_B = new MovingSprite(rect.w, bottomClouds_y, rect.w, bottomCloudsTexture->getHeight(), -bottomCloudsSpeed, 0.0f, 0.0f, 0.0f, bottomCloudsTexture);
|
|
|
|
buildingsSprite = new Sprite(0, 0, buildingsTexture->getWidth(), buildingsTexture->getHeight(), buildingsTexture);
|
|
gradientSprite = new Sprite(0, 0, rect.w, rect.h, gradientsTexture);
|
|
grassSprite = new Sprite(0, 0, grassTexture->getWidth(), grassTexture->getHeight() / 2, grassTexture);
|
|
|
|
// Inicializa objetos
|
|
topCloudsSprite_A->setSpriteClip(0, 0, topCloudsTexture->getWidth(), topCloudsTexture->getHeight());
|
|
topCloudsSprite_B->setSpriteClip(0, 0, topCloudsTexture->getWidth(), topCloudsTexture->getHeight());
|
|
bottomCloudsSprite_A->setSpriteClip(0, 0, bottomCloudsTexture->getWidth(), bottomCloudsTexture->getHeight());
|
|
bottomCloudsSprite_B->setSpriteClip(0, 0, bottomCloudsTexture->getWidth(), bottomCloudsTexture->getHeight());
|
|
buildingsSprite->setPosY(base - buildingsSprite->getHeight());
|
|
grassSprite->setPosY(base - grassSprite->getHeight());
|
|
|
|
// Crea la textura para componer el fondo
|
|
canvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect.w, rect.h);
|
|
SDL_SetTextureBlendMode(canvas, SDL_BLENDMODE_BLEND);
|
|
|
|
// Crea la textura para atenuar el fondo
|
|
colorTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect.w, rect.h);
|
|
SDL_SetTextureBlendMode(colorTexture, SDL_BLENDMODE_BLEND);
|
|
setColor(color);
|
|
SDL_SetTextureAlphaMod(colorTexture, alphaColorText);
|
|
}
|
|
|
|
// Destructor
|
|
Background::~Background()
|
|
{
|
|
delete buildingsTexture;
|
|
delete topCloudsTexture;
|
|
delete bottomCloudsTexture;
|
|
delete grassTexture;
|
|
delete gradientsTexture;
|
|
|
|
delete topCloudsSprite_A;
|
|
delete topCloudsSprite_B;
|
|
delete bottomCloudsSprite_A;
|
|
delete bottomCloudsSprite_B;
|
|
delete buildingsSprite;
|
|
delete gradientSprite;
|
|
delete grassSprite;
|
|
SDL_DestroyTexture(canvas);
|
|
SDL_DestroyTexture(colorTexture);
|
|
}
|
|
|
|
// Actualiza la lógica del objeto
|
|
void Background::update()
|
|
{
|
|
// Actualiza el valor de alpha
|
|
updateAlphaColorText();
|
|
|
|
// Actualiza las nubes
|
|
updateClouds();
|
|
|
|
// Calcula el frame de la hierba
|
|
grassSprite->setSpriteClip(0, (10 * (counter / 20 % 2)), 320, 10);
|
|
|
|
// Calcula el valor de alpha
|
|
alpha = std::max((255 - (int)(255 * transition)), 0);
|
|
|
|
// Incrementa el contador
|
|
counter++;
|
|
|
|
fillCanvas();
|
|
}
|
|
|
|
// Dibuja el gradiente de fondo
|
|
void Background::renderGradient()
|
|
{
|
|
// Dibuja el gradiente 2
|
|
gradientsTexture->setAlpha(255);
|
|
gradientSprite->setSpriteClip(gradientRect[(gradientNumber + 1) % 4]);
|
|
gradientSprite->render();
|
|
|
|
// Dibuja el gradiente 1 con una opacidad cada vez menor
|
|
gradientsTexture->setAlpha(alpha);
|
|
gradientSprite->setSpriteClip(gradientRect[gradientNumber]);
|
|
gradientSprite->render();
|
|
}
|
|
|
|
// Dibuja las nubes de arriba
|
|
void Background::renderTopClouds()
|
|
{
|
|
// Dibuja el primer conjunto de nubes
|
|
topCloudsTexture->setAlpha(255);
|
|
topCloudsSprite_A->setSpriteClip(topCloudsRect[(gradientNumber + 1) % 4]);
|
|
topCloudsSprite_A->render();
|
|
topCloudsSprite_B->setSpriteClip(topCloudsRect[(gradientNumber + 1) % 4]);
|
|
topCloudsSprite_B->render();
|
|
|
|
// Dibuja el segundo conjunto de nubes
|
|
topCloudsTexture->setAlpha(alpha);
|
|
topCloudsSprite_A->setSpriteClip(topCloudsRect[gradientNumber]);
|
|
topCloudsSprite_A->render();
|
|
topCloudsSprite_B->setSpriteClip(topCloudsRect[gradientNumber]);
|
|
topCloudsSprite_B->render();
|
|
}
|
|
|
|
// Dibuja las nubes de abajo
|
|
void Background::renderBottomClouds()
|
|
{
|
|
// Dibuja el primer conjunto de nubes
|
|
bottomCloudsTexture->setAlpha(255);
|
|
bottomCloudsSprite_A->setSpriteClip(bottomCloudsRect[(gradientNumber + 1) % 4]);
|
|
bottomCloudsSprite_A->render();
|
|
bottomCloudsSprite_B->setSpriteClip(bottomCloudsRect[(gradientNumber + 1) % 4]);
|
|
bottomCloudsSprite_B->render();
|
|
|
|
// Dibuja el segundo conjunto de nubes
|
|
bottomCloudsTexture->setAlpha(alpha);
|
|
bottomCloudsSprite_A->setSpriteClip(bottomCloudsRect[gradientNumber]);
|
|
bottomCloudsSprite_A->render();
|
|
bottomCloudsSprite_B->setSpriteClip(bottomCloudsRect[gradientNumber]);
|
|
bottomCloudsSprite_B->render();
|
|
}
|
|
|
|
// Compone todos los elementos del fondo en la textura
|
|
void Background::fillCanvas()
|
|
{
|
|
// Cambia el destino del renderizador
|
|
SDL_Texture *temp = SDL_GetRenderTarget(renderer);
|
|
SDL_SetRenderTarget(renderer, canvas);
|
|
|
|
// Dibuja el gradiente de fondo
|
|
renderGradient();
|
|
|
|
// Dibuja las nubes de arriba
|
|
renderTopClouds();
|
|
|
|
// Dibuja las nubes de abajo
|
|
renderBottomClouds();
|
|
|
|
// Dibuja los edificios
|
|
buildingsSprite->render();
|
|
|
|
// Dibuja la hierba
|
|
grassSprite->render();
|
|
|
|
// Deja el renderizador apuntando donde estaba
|
|
SDL_SetRenderTarget(renderer, temp);
|
|
}
|
|
|
|
// Dibuja el objeto
|
|
void Background::render()
|
|
{
|
|
// Fondo
|
|
SDL_RenderCopy(renderer, canvas, &srcRect, &dstRect);
|
|
|
|
// Atenuación
|
|
SDL_RenderCopy(renderer, colorTexture, &srcRect, &dstRect);
|
|
}
|
|
|
|
// Vuelve a cargar las texturas
|
|
void Background::reloadTextures()
|
|
{
|
|
buildingsTexture->reLoad();
|
|
topCloudsTexture->reLoad();
|
|
bottomCloudsTexture->reLoad();
|
|
grassTexture->reLoad();
|
|
gradientsTexture->reLoad();
|
|
}
|
|
|
|
// Ajusta el valor de la variable
|
|
void Background::setCloudsSpeed(float value)
|
|
{
|
|
cloudsSpeed = value;
|
|
}
|
|
|
|
// Ajusta el valor de la variable
|
|
void Background::setGradientNumber(int value)
|
|
{
|
|
gradientNumber = value % 4;
|
|
}
|
|
|
|
// Ajusta el valor de la variable
|
|
void Background::setTransition(float value)
|
|
{
|
|
value = std::min(value, 1.0f);
|
|
value = std::max(value, 0.0f);
|
|
transition = value;
|
|
}
|
|
|
|
// Establece la posición del objeto
|
|
void Background::setPos(SDL_Rect pos)
|
|
{
|
|
this->dstRect = pos;
|
|
|
|
// Si cambian las medidas del destino, hay que cambiar las del origen para evitar deformar la imagen
|
|
this->srcRect.x = 0;
|
|
this->srcRect.y = rect.h - pos.h;
|
|
this->srcRect.w = pos.w;
|
|
this->srcRect.h = pos.h;
|
|
}
|
|
|
|
// Ajusta el valor de la variable
|
|
void Background::setSrcRect(SDL_Rect value)
|
|
{
|
|
srcRect = value;
|
|
}
|
|
|
|
// Ajusta el valor de la variable
|
|
void Background::setDstRect(SDL_Rect value)
|
|
{
|
|
dstRect = value;
|
|
}
|
|
|
|
// Establece el color de atenuación
|
|
void Background::setColor(color_t color)
|
|
{
|
|
this->color = color;
|
|
|
|
// Colorea la textura
|
|
SDL_Texture *temp = SDL_GetRenderTarget(renderer);
|
|
SDL_SetRenderTarget(renderer, colorTexture);
|
|
|
|
SDL_SetRenderDrawColor(renderer, color.r, color.g, 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::min(alpha, 255);
|
|
alpha = std::max(alpha, 0);
|
|
|
|
// Guarda el valor actual
|
|
alphaColorTextTemp = alphaColorText;
|
|
|
|
// Establece el nuevo valor
|
|
alphaColorText = alpha;
|
|
}
|
|
|
|
// Actualiza el valor de alpha
|
|
void Background::updateAlphaColorText()
|
|
{
|
|
if (alphaColorText == alphaColorTextTemp)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
alphaColorText > alphaColorTextTemp ? alphaColorTextTemp++ : alphaColorTextTemp--;
|
|
SDL_SetTextureAlphaMod(colorTexture, alphaColorTextTemp);
|
|
}
|
|
}
|
|
|
|
// Actualiza las nubes
|
|
void Background::updateClouds()
|
|
{
|
|
// Aplica la velocidad calculada a las nubes
|
|
topCloudsSprite_A->setVelX(cloudsSpeed);
|
|
topCloudsSprite_B->setVelX(cloudsSpeed);
|
|
bottomCloudsSprite_A->setVelX(cloudsSpeed / 2);
|
|
bottomCloudsSprite_B->setVelX(cloudsSpeed / 2);
|
|
|
|
// Mueve las nubes
|
|
topCloudsSprite_A->move();
|
|
topCloudsSprite_B->move();
|
|
bottomCloudsSprite_A->move();
|
|
bottomCloudsSprite_B->move();
|
|
|
|
// Calcula el offset de las nubes
|
|
if (topCloudsSprite_A->getPosX() < -topCloudsSprite_A->getWidth())
|
|
{
|
|
topCloudsSprite_A->setPosX(topCloudsSprite_A->getWidth());
|
|
}
|
|
|
|
if (topCloudsSprite_B->getPosX() < -topCloudsSprite_B->getWidth())
|
|
{
|
|
topCloudsSprite_B->setPosX(topCloudsSprite_B->getWidth());
|
|
}
|
|
|
|
if (bottomCloudsSprite_A->getPosX() < -bottomCloudsSprite_A->getWidth())
|
|
{
|
|
bottomCloudsSprite_A->setPosX(bottomCloudsSprite_A->getWidth());
|
|
}
|
|
|
|
if (bottomCloudsSprite_B->getPosX() < -bottomCloudsSprite_B->getWidth())
|
|
{
|
|
bottomCloudsSprite_B->setPosX(bottomCloudsSprite_B->getWidth());
|
|
}
|
|
} |