From f647a225f995b03d39d5c93dd7c00939e5d53bd3 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Wed, 21 Sep 2022 17:31:35 +0200 Subject: [PATCH] Actualizadas librerias comunes a las ultimas versiones --- source/actor.cpp | 3 +- source/const.h | 24 ++- source/enemy.cpp | 5 +- source/intro.cpp | 3 +- source/logo.cpp | 5 +- source/ltexture.cpp | 118 ++++++----- source/ltexture.h | 56 +++-- source/map.cpp | 5 +- source/player.cpp | 4 +- source/screen.cpp | 210 ++++++++++++++++++- source/screen.h | 67 +++++- source/text.cpp | 4 +- source/title.cpp | 3 +- source/utils.cpp | 498 +++++++++++++++++++++++++++++++++++++------- source/utils.h | 79 ++++--- 15 files changed, 873 insertions(+), 211 deletions(-) diff --git a/source/actor.cpp b/source/actor.cpp index e494e04..15e86cf 100644 --- a/source/actor.cpp +++ b/source/actor.cpp @@ -15,8 +15,7 @@ Actor::Actor(actor_t actor) renderer = actor.renderer; // Crea objetos - texture = new LTexture(); - loadTextureFromFile(texture, asset->get(actor.tileset), renderer); + texture = new LTexture(renderer, asset->get(actor.tileset)); sprite = new AnimatedSprite(texture, renderer, asset->get(actor.animation)); // Obten el resto de valores diff --git a/source/const.h b/source/const.h index b7c8ad8..60d8f00 100644 --- a/source/const.h +++ b/source/const.h @@ -8,7 +8,7 @@ // Textos #define WINDOW_CAPTION "Volcano" #define TEXT_COPYRIGHT "2016,2022 JAILDESIGNER & JAILBROTHER" -#define VERSION "0.5" +#define VERSION "0.6" // Tamaño de bloque #define BLOCK 8 @@ -20,9 +20,9 @@ // Zona de juego const int PLAY_AREA_TOP = (0 * BLOCK); -const int PLAY_AREA_BOTTOM = (16 * BLOCK); +const int PLAY_AREA_BOTTOM = (26 * BLOCK); const int PLAY_AREA_LEFT = (0 * BLOCK); -const int PLAY_AREA_RIGHT = (32 * BLOCK); +const int PLAY_AREA_RIGHT = (40 * BLOCK); const int PLAY_AREA_WIDTH = PLAY_AREA_RIGHT - PLAY_AREA_LEFT; const int PLAY_AREA_HEIGHT = PLAY_AREA_BOTTOM - PLAY_AREA_TOP; const int PLAY_AREA_CENTER_X = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2); @@ -40,8 +40,24 @@ const int GAMECANVAS_CENTER_Y = GAMECANVAS_HEIGHT / 2; const int GAMECANVAS_FIRST_QUARTER_Y = GAMECANVAS_HEIGHT / 4; const int GAMECANVAS_THIRD_QUARTER_Y = (GAMECANVAS_HEIGHT / 4) * 3; +// Secciones del programa +#define SECTION_PROG_LOGO 0 +#define SECTION_PROG_INTRO 1 +#define SECTION_PROG_TITLE 2 +#define SECTION_PROG_CREDITS 3 +#define SECTION_PROG_GAME 4 +#define SECTION_PROG_QUIT 5 + +// Subsecciones +#define SUBSECTION_GAME_PLAY 0 +#define SUBSECTION_GAME_PAUSE 1 +#define SUBSECTION_GAME_GAMEOVER 2 +#define SUBSECTION_TITLE_1 3 +#define SUBSECTION_TITLE_2 4 +#define SUBSECTION_TITLE_3 5 +#define SUBSECTION_TITLE_INSTRUCTIONS 6 + // Colores const color_t borderColor = {0x27, 0x27, 0x36}; -const color_t black = {0xFF, 0xFF, 0xFF}; #endif \ No newline at end of file diff --git a/source/enemy.cpp b/source/enemy.cpp index da2c66e..5240768 100644 --- a/source/enemy.cpp +++ b/source/enemy.cpp @@ -15,8 +15,7 @@ Enemy::Enemy(enemy_t enemy) renderer = enemy.renderer; // Crea objetos - texture = new LTexture(); - loadTextureFromFile(texture, asset->get(enemy.tileset), renderer); + texture = new LTexture(renderer, asset->get(enemy.tileset)); sprite = new AnimatedSprite(texture, renderer, asset->get(enemy.animation)); // Obten el resto de valores @@ -24,7 +23,7 @@ Enemy::Enemy(enemy_t enemy) sprite->setPosY(enemy.y); sprite->setWidth(enemy.w); sprite->setHeight(enemy.h); - + sprite->setVelX(enemy.vx); sprite->setVelY(enemy.vy); sprite->setFlip(enemy.vx > 0 ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL); diff --git a/source/intro.cpp b/source/intro.cpp index 30a91ba..327fcfc 100644 --- a/source/intro.cpp +++ b/source/intro.cpp @@ -10,8 +10,7 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset) // Reserva memoria para los punteros eventHandler = new SDL_Event(); - texture = new LTexture(); - loadTextureFromFile(texture, asset->get("intro.png"), renderer); + texture = new LTexture(renderer, asset->get("intro.png")); sprite = new AnimatedSprite(texture, renderer, asset->get("intro.ani")); // Inicializa variables diff --git a/source/logo.cpp b/source/logo.cpp index 661ca2d..a58aed0 100644 --- a/source/logo.cpp +++ b/source/logo.cpp @@ -10,8 +10,7 @@ Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset) // Reserva memoria para los punteros eventHandler = new SDL_Event(); - texture = new LTexture(); - loadTextureFromFile(texture, asset->get("logo.png"), renderer); + texture = new LTexture(renderer, asset->get("logo.png")); sprite = new Sprite(0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT, texture, renderer); // Crea un backbuffer para el renderizador @@ -78,7 +77,7 @@ void Logo::update() } } - counter++; + counter++; // Comprueba si ha terminado el logo if (counter == endLogo + postLogo) diff --git a/source/ltexture.cpp b/source/ltexture.cpp index 0e6fd17..d9c74cb 100644 --- a/source/ltexture.cpp +++ b/source/ltexture.cpp @@ -1,22 +1,35 @@ -#include "const.h" + #include "ltexture.h" #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" -LTexture::LTexture() +// Constructor +LTexture::LTexture(SDL_Renderer *renderer, std::string path) { - // Initialize - mTexture = NULL; - mWidth = 0; - mHeight = 0; + // Copia punteros + this->renderer = renderer; + this->path = path; + + // Inicializa + texture = NULL; + width = 0; + height = 0; + + // Carga el fichero en la textura + if (path != "") + { + loadFromFile(path, renderer); + } } +// Destructor LTexture::~LTexture() { - // Deallocate + // Libera memoria unload(); } +// Carga una imagen desde un fichero bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer) { int req_format = STBI_rgb_alpha; @@ -33,7 +46,7 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer) if (req_format == STBI_rgb) { depth = 24; - pitch = 3 * width; // 3 bytes per pixel * pixels per row + pitch = 3 * width; // 3 bytes por pixel * pixels per linea pixel_format = SDL_PIXELFORMAT_RGB24; } else @@ -43,14 +56,13 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer) pixel_format = SDL_PIXELFORMAT_RGBA32; } - // Get rid of preexisting texture + // Limpia unload(); - // The final texture + // La textura final SDL_Texture *newTexture = NULL; - // Load image at specified path - //SDL_Surface *loadedSurface = IMG_Load(path.c_str()); + // Carga la imagen desde una ruta específica SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format); if (loadedSurface == NULL) { @@ -58,10 +70,7 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer) } else { - // Color key image - //SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, COLOR_KEY_R, COLOR_KEY_G, COLOR_KEY_B)); - - // Create texture from surface pixels + // Crea la textura desde los pixels de la surface newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface); if (newTexture == NULL) { @@ -69,73 +78,76 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer) } else { - // Get image dimensions - mWidth = loadedSurface->w; - mHeight = loadedSurface->h; + // Obtiene las dimensiones de la imagen + this->width = loadedSurface->w; + this->height = loadedSurface->h; } - // Get rid of old loaded surface + // Elimina la textura cargada SDL_FreeSurface(loadedSurface); } // Return success - mTexture = newTexture; - return mTexture != NULL; + texture = newTexture; + return texture != NULL; } +// Crea una textura en blanco bool LTexture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access) { - // Create uninitialized texture - mTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height); - if (mTexture == NULL) + // Crea una textura sin inicializar + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height); + if (texture == NULL) { printf("Unable to create blank texture! SDL Error: %s\n", SDL_GetError()); } else { - mWidth = width; - mHeight = height; + this->width = width; + this->height = height; } - return mTexture != NULL; + return texture != NULL; } +// Libera la memoria de la textura void LTexture::unload() { - // Free texture if it exists - if (mTexture != NULL) + // Libera la textura si existe + if (texture != NULL) { - SDL_DestroyTexture(mTexture); - mTexture = NULL; - mWidth = 0; - mHeight = 0; + SDL_DestroyTexture(texture); + texture = NULL; + width = 0; + height = 0; } } +// Establece el color para la modulacion void LTexture::setColor(Uint8 red, Uint8 green, Uint8 blue) { - // Modulate texture rgb - SDL_SetTextureColorMod(mTexture, red, green, blue); + SDL_SetTextureColorMod(texture, red, green, blue); } +// Establece el blending void LTexture::setBlendMode(SDL_BlendMode blending) { - // Set blending function - SDL_SetTextureBlendMode(mTexture, blending); + SDL_SetTextureBlendMode(texture, blending); } +// Establece el alpha para la modulación void LTexture::setAlpha(Uint8 alpha) { - // Modulate texture alpha - SDL_SetTextureAlphaMod(mTexture, alpha); + SDL_SetTextureAlphaMod(texture, alpha); } +// Renderiza la textura en un punto específico void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_RendererFlip flip) { - // Set rendering space and render to screen - SDL_Rect renderQuad = {x, y, mWidth, mHeight}; + // Establece el destini de renderizado en la pantalla + SDL_Rect renderQuad = {x, y, width, height}; - // Set clip rendering dimensions + // Obtiene las dimesiones del clip de renderizado if (clip != NULL) { renderQuad.w = clip->w; @@ -145,22 +157,30 @@ void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, floa renderQuad.w = renderQuad.w * zoomW; renderQuad.h = renderQuad.h * zoomH; - // Render to screen - SDL_RenderCopyEx(renderer, mTexture, clip, &renderQuad, angle, center, flip); + // Renderiza a pantalla + SDL_RenderCopyEx(renderer, texture, clip, &renderQuad, angle, center, flip); } +// Establece la textura como objetivo de renderizado void LTexture::setAsRenderTarget(SDL_Renderer *renderer) { - // Make self render target - SDL_SetRenderTarget(renderer, mTexture); + SDL_SetRenderTarget(renderer, texture); } +// Obtiene el ancho de la imagen int LTexture::getWidth() { - return mWidth; + return width; } +// Obtiene el alto de la imagen int LTexture::getHeight() { - return mHeight; + return height; } + +// Recarga la textura +bool LTexture::reLoad() +{ + return loadFromFile(path, renderer); +} \ No newline at end of file diff --git a/source/ltexture.h b/source/ltexture.h index c03a3aa..ff23c6f 100644 --- a/source/ltexture.h +++ b/source/ltexture.h @@ -7,61 +7,55 @@ #ifndef LTEXTURE_H #define LTEXTURE_H -// Texture wrapper class +// Clase LTexture class LTexture { -public: - // Initializes variables - LTexture(); +private: + SDL_Texture *texture; // La textura + SDL_Renderer *renderer; // Renderizador donde dibujar la textura + int width; // Ancho de la imagen + int height; // Alto de la imagen + std::string path; // Ruta de la imagen de la textura - // Deallocates memory +public: + // Constructor + LTexture(SDL_Renderer *renderer, std::string path = ""); + + // Destructor ~LTexture(); - // Loads image at specified path + // Carga una imagen desde un fichero bool loadFromFile(std::string path, SDL_Renderer *renderer); - // Creates blank texture + // Crea una textura en blanco bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); - // Deallocates texture + // Libera la memoria de la textura void unload(); - // Set color modulation + // Establece el color para la modulacion void setColor(Uint8 red, Uint8 green, Uint8 blue); - // Set blending + // Establece el blending void setBlendMode(SDL_BlendMode blending); - // Set alpha modulation + // Establece el alpha para la modulación void setAlpha(Uint8 alpha); - // Renders texture at given point + // Renderiza la textura en un punto específico void render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip = NULL, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_Point *center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE); - // Set self as render target + // Establece la textura como objetivo de renderizado void setAsRenderTarget(SDL_Renderer *renderer); - // Gets image dimensions + // Obtiene el ancho de la imagen int getWidth(); + + // Obtiene el alto de la imagen int getHeight(); - // Pixel manipulators - bool lockTexture(); - bool unlockTexture(); - void *getPixels(); - void copyPixels(void *pixels); - int getPitch(); - Uint32 getPixel32(unsigned int x, unsigned int y); - -private: - // The actual hardware texture - SDL_Texture *mTexture; - void *mPixels; - int mPitch; - - // Image dimensions - int mWidth; - int mHeight; + // Recarga la textura + bool reLoad(); }; #endif diff --git a/source/map.cpp b/source/map.cpp index 9c3ca05..b0980ef 100644 --- a/source/map.cpp +++ b/source/map.cpp @@ -17,9 +17,8 @@ Map::Map(std::string file, SDL_Renderer *renderer, Asset *asset, ItemTracker *it this->itemTracker = itemTracker; // Crea los objetos - texture_tile = new LTexture(); load(file); - loadTextureFromFile(texture_tile, asset->get(tileset_img), renderer); + texture_tile = new LTexture(renderer, asset->get(tileset_img)); tileset_width = texture_tile->getWidth() / tile_size; // Crea la textura para el mapa de tiles de la habitación @@ -456,7 +455,7 @@ e_tile_map Map::getTile(SDL_Point p) { return nothing; } - + else if (tile == 5627) { return wall; diff --git a/source/player.cpp b/source/player.cpp index 8bae1c9..34e0180 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -12,9 +12,7 @@ Player::Player(SDL_Renderer *renderer, Asset *asset, Input *input, Map *map) sound_death = JA_LoadSound(asset->get("sound_player_death.wav").c_str()); sound_coin = JA_LoadSound(asset->get("sound_player_coin.wav").c_str()); - texture = new LTexture(); - loadTextureFromFile(texture, asset->get("player.png"), renderer); - + texture = new LTexture(renderer, asset->get("player.png")); sprite = new AnimatedSprite(texture, renderer, asset->get("player.ani")); w = 16; diff --git a/source/screen.cpp b/source/screen.cpp index 1c8aee7..e5f4ac2 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -13,11 +13,10 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options, i gameCanvasWidth = gameInternalResX; gameCanvasHeight = gameInternalResY; - // Establece el modo de video - setVideoMode(options->fullScreenMode); + iniFade(); + iniSpectrumFade(); // Define el color del borde para el modo de pantalla completa - borderColor = {0x27, 0x27, 0x36}; borderColor = {0x00, 0x00, 0x00}; // Crea la textura donde se dibujan los graficos del juego @@ -25,6 +24,9 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options, i if (gameCanvas == NULL) printf("TitleSurface could not be created!\nSDL Error: %s\n", SDL_GetError()); + // Establece el modo de video + setVideoMode(options->fullScreenMode); + // Calcula los anclajes anchor.left = 0; anchor.right = gameCanvasWidth; @@ -79,9 +81,21 @@ void Screen::setVideoMode(int fullScreenMode) // Si está activo el modo ventana quita el borde if (fullScreenMode == 0) { - screenWidth = gameCanvasWidth; - screenHeight = gameCanvasHeight; - dest = {0, 0, gameCanvasWidth, gameCanvasHeight}; + if (options->borderEnabled) + { + const int incWidth = gameCanvasWidth * options->borderSize; + const int incHeight = gameCanvasHeight * options->borderSize; + screenWidth = gameCanvasWidth + incWidth; + screenHeight = gameCanvasHeight + incHeight; + dest = {0 + (incWidth / 2), 0 + (incHeight / 2), gameCanvasWidth, gameCanvasHeight}; + } + + else + { + screenWidth = gameCanvasWidth; + screenHeight = gameCanvasHeight; + dest = {0, 0, gameCanvasWidth, gameCanvasHeight}; + } // Modifica el tamaño del renderizador y de la ventana SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight); @@ -147,12 +161,14 @@ void Screen::switchVideoMode() { if (options->fullScreenMode == 0) { - setVideoMode(SDL_WINDOW_FULLSCREEN_DESKTOP); + options->fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP; } else { - setVideoMode(0); + options->fullScreenMode = 0; } + + setVideoMode(options->fullScreenMode); } // Cambia el tamaño de la ventana @@ -166,4 +182,182 @@ void Screen::setWindowSize(int size) void Screen::setBorderColor(color_t color) { borderColor = color; +} + +// Cambia el tipo de mezcla +void Screen::setBlendMode(SDL_BlendMode blendMode) +{ + SDL_SetRenderDrawBlendMode(renderer, blendMode); +} + +// Establece el tamaño del borde +void Screen::setBorderSize(float s) +{ + options->borderSize = s; +} + +// Establece si se ha de ver el borde en el modo ventana +void Screen::setBorderEnabled(bool value) +{ + options->borderEnabled = value; +} + +// Cambia entre borde visible y no visible +void Screen::switchBorder() +{ + options->borderEnabled = !options->borderEnabled; + setVideoMode(0); +} + +// Activa el fade +void Screen::setFade() +{ + fade = true; +} + +// Comprueba si ha terminado el fade +bool Screen::fadeEnded() +{ + if (fade || fadeCounter > 0) + { + return false; + } + + return true; +} + +// Activa el spectrum fade +void Screen::setspectrumFade() +{ + spectrumFade = true; +} + +// Comprueba si ha terminado el spectrum fade +bool Screen::spectrumFadeEnded() +{ + if (spectrumFade || spectrumFadeCounter > 0) + { + return false; + } + + return true; +} + +// Inicializa las variables para el fade +void Screen::iniFade() +{ + fade = false; + fadeCounter = 0; + fadeLenght = 200; +} + +// Actualiza el fade +void Screen::updateFade() +{ + if (!fade) + { + return; + } + + fadeCounter++; + if (fadeCounter > fadeLenght) + { + iniFade(); + } +} + +// Dibuja el fade +void Screen::renderFade() +{ + if (!fade) + { + return; + } + + const SDL_Rect rect = {0, 0, gameCanvasWidth, gameCanvasHeight}; + color_t color = {0, 0, 0}; + const float step = (float)fadeCounter / (float)fadeLenght; + const int alpha = 0 + (255 - 0) * step; + SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, alpha); + SDL_RenderFillRect(renderer, &rect); +} + +// Inicializa las variables para el fade spectrum +void Screen::iniSpectrumFade() +{ + spectrumFade = false; + spectrumFadeCounter = 0; + spectrumFadeLenght = 50; + + spectrumColor.clear(); + + color_t c; + c = stringToColor("black"); + spectrumColor.push_back(c); + + c = stringToColor("blue"); + spectrumColor.push_back(c); + + c = stringToColor("red"); + spectrumColor.push_back(c); + + c = stringToColor("magenta"); + spectrumColor.push_back(c); + + c = stringToColor("green"); + spectrumColor.push_back(c); + + c = stringToColor("cyan"); + spectrumColor.push_back(c); + + c = stringToColor("yellow"); + spectrumColor.push_back(c); + + c = stringToColor("bright_white"); + spectrumColor.push_back(c); +} + +// Actualiza el spectrum fade +void Screen::updateSpectrumFade() +{ + if (!spectrumFade) + { + return; + } + + spectrumFadeCounter++; + if (spectrumFadeCounter > spectrumFadeLenght) + { + iniSpectrumFade(); + SDL_SetTextureColorMod(gameCanvas, 255, 255, 255); + } +} + +// Dibuja el spectrum fade +void Screen::renderSpectrumFade() +{ + if (!spectrumFade) + { + return; + } + + const float step = (float)spectrumFadeCounter / (float)spectrumFadeLenght; + const int max = spectrumColor.size() - 1; + const int index = max + (0 - max) * step; + const color_t c = spectrumColor[index]; + SDL_SetTextureColorMod(gameCanvas, c.r, c.g, c.b); +} + +// Actualiza los efectos +void Screen::updateFX() +{ + updateFade(); + updateSpectrumFade(); +} + +// Dibuja los efectos +void Screen::renderFX() +{ + renderFade(); + renderSpectrumFade(); } \ No newline at end of file diff --git a/source/screen.h b/source/screen.h index 5c15402..31fcedf 100644 --- a/source/screen.h +++ b/source/screen.h @@ -2,16 +2,20 @@ #include #include "utils.h" +#include #ifndef SCREEN_H #define SCREEN_H +#define FILTER_NEAREST 0 +#define FILTER_LINEAL 1 + struct anchor_t { - int left; // Parte izquierda de la pantalla de juego - int right; // Parte drecha de la pantalla de juego + int left; // Parte izquierda de la pantalla de juego + int right; // Parte drecha de la pantalla de juego int center; // Parte central horizontal de la pantalla de juego - int top; // Parte superior de la pantalla de juego + int top; // Parte superior de la pantalla de juego int bottom; // Parte infoerior de la pantalla de juego int middle; // Parte central vertical de la pantalla de juego }; @@ -33,6 +37,33 @@ private: SDL_Rect dest; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla + // EFECTOS + bool fade; // Indica si esta activo el efecto de fade + int fadeCounter; // Temporizador para el efecto de fade + int fadeLenght; // Duración del fade + bool spectrumFade; // Indica si esta activo el efecto de fade spectrum + int spectrumFadeCounter; // Temporizador para el efecto de fade spectrum + int spectrumFadeLenght; // Duración del fade spectrum + std::vector spectrumColor; // Colores para el fade spectrum + + // Inicializa las variables para el fade + void iniFade(); + + // Actualiza el fade + void updateFade(); + + // Dibuja el fade + void renderFade(); + + // Inicializa las variables para el fade spectrum + void iniSpectrumFade(); + + // Actualiza el spectrum fade + void updateSpectrumFade(); + + // Dibuja el spectrum fade + void renderSpectrumFade(); + public: // Constructor Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options, int gameInternalResX, int gameInternalResY); @@ -60,6 +91,36 @@ public: // Cambia el color del borde void setBorderColor(color_t color); + + // Cambia el tipo de mezcla + void setBlendMode(SDL_BlendMode blendMode); + + // Establece el tamaño del borde + void setBorderSize(float s); + + // Establece si se ha de ver el borde en el modo ventana + void setBorderEnabled(bool value); + + // Cambia entre borde visible y no visible + void switchBorder(); + + // Activa el fade + void setFade(); + + // Comprueba si ha terminado el fade + bool fadeEnded(); + + // Activa el spectrum fade + void setspectrumFade(); + + // Comprueba si ha terminado el spectrum fade + bool spectrumFadeEnded(); + + // Actualiza los efectos + void updateFX(); + + // Dibuja los efectos + void renderFX(); }; #endif diff --git a/source/text.cpp b/source/text.cpp index 57695d8..6257cd6 100644 --- a/source/text.cpp +++ b/source/text.cpp @@ -6,9 +6,7 @@ // Constructor Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer) { - texture = new LTexture(); - loadTextureFromFile(texture, bitmapFile, renderer); - + texture = new LTexture(renderer, bitmapFile); mSprite = new Sprite({0, 0, 0, 0}, texture, renderer); mSprite->setTexture(texture); mSprite->setRenderer(renderer); diff --git a/source/title.cpp b/source/title.cpp index 70b1d9a..13a64bb 100644 --- a/source/title.cpp +++ b/source/title.cpp @@ -11,8 +11,7 @@ Title::Title(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input) // Reserva memoria para los punteros eventHandler = new SDL_Event(); - texture = new LTexture(); - loadTextureFromFile(texture, asset->get("intro.png"), renderer); + texture = new LTexture(renderer, asset->get("intro.png")); sprite = new AnimatedSprite(texture, renderer, asset->get("intro.ani")); sprite->setCurrentAnimation("menu"); text = new Text(asset->get("debug.png"), asset->get("debug.txt"), renderer); diff --git a/source/utils.cpp b/source/utils.cpp index 36b15cb..bc0117d 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -1,4 +1,5 @@ #include "utils.h" +#include // Calcula el cuadrado de la distancia entre dos puntos double distanceSquared(int x1, int y1, int x2, int y2) @@ -74,19 +75,19 @@ bool checkCollision(circle_t &a, SDL_Rect &b) // Detector de colisiones entre dos rectangulos bool checkCollision(SDL_Rect &a, SDL_Rect &b) { - // Calculate the sides of rect A + // Calcula las caras del rectangulo a const int leftA = a.x; const int rightA = a.x + a.w; const int topA = a.y; const int bottomA = a.y + a.h; - // Calculate the sides of rect B + // Calcula las caras del rectangulo b const int leftB = b.x; const int rightB = b.x + b.w; const int topB = b.y; const int bottomB = b.y + b.h; - // If any of the sides from A are outside of B + // Si cualquiera de las caras de a está fuera de b if (bottomA <= topB) { return false; @@ -107,118 +108,473 @@ bool checkCollision(SDL_Rect &a, SDL_Rect &b) return false; } - // If none of the sides from A are outside B + // Si ninguna de las caras está fuera de b return true; } -// Detector de colisiones entre un punto y u rectangulo +// Detector de colisiones entre un punto y un rectangulo bool checkCollision(SDL_Point &p, SDL_Rect &r) { - // Comprueba si el punto está fuera del rectangulo en el eje X + // Comprueba si el punto está a la izquierda del rectangulo if (p.x < r.x) { return false; } + // Comprueba si el punto está a la derecha del rectangulo if (p.x > r.x + r.w) { return false; } - // Comprueba si el punto está fuera del rectangulo en el eje Y + // Comprueba si el punto está por encima del rectangulo if (p.y < r.y) { return false; } + // Comprueba si el punto está por debajo del rectangulo if (p.y > r.y + r.h) { return false; } - // Si ha llegado hasta aquí, es que está dentro + // Si no está fuera, es que está dentro return true; } -// Carga un archivo de imagen en una textura -bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer) +// Detector de colisiones entre una linea horizontal y un rectangulo +bool checkCollision(h_line_t &l, SDL_Rect &r) { - bool success = true; - if (!texture->loadFromFile(path, renderer)) + // Comprueba si la linea esta por encima del rectangulo + if (l.y < r.y) { - printf("Failed to load %s texture!\n", path.c_str()); - success = false; + return false; } - return success; + + // Comprueba si la linea esta por debajo del rectangulo + if (l.y >= r.y + r.h) + { + return false; + } + + // Comprueba si el inicio de la linea esta a la derecha del rectangulo + if (l.x1 >= r.x + r.w) + { + return false; + } + + // Comprueba si el final de la linea esta a la izquierda del rectangulo + if (l.x2 < r.x) + { + return false; + } + + // Si ha llegado hasta aquí, hay colisión + return true; +} + +// Detector de colisiones entre una linea vertical y un rectangulo +bool checkCollision(v_line_t &l, SDL_Rect &r) +{ + // Comprueba si la linea esta por la izquierda del rectangulo + if (l.x < r.x) + { + return false; + } + + // Comprueba si la linea esta por la derecha del rectangulo + if (l.x >= r.x + r.w) + { + return false; + } + + // Comprueba si el inicio de la linea esta debajo del rectangulo + if (l.y1 >= r.y + r.h) + { + return false; + } + + // Comprueba si el final de la linea esta encima del rectangulo + if (l.y2 < r.y) + { + return false; + } + + // Si ha llegado hasta aquí, hay colisión + return true; +} + +// Detector de colisiones entre una linea horizontal y un punto +bool checkCollision(h_line_t &l, SDL_Point &p) +{ + // Comprueba si el punto esta sobre la linea + if (p.y > l.y) + { + return false; + } + + // Comprueba si el punto esta bajo la linea + if (p.y < l.y) + { + return false; + } + + // Comprueba si el punto esta a la izquierda de la linea + if (p.x < l.x1) + { + return false; + } + + // Comprueba si el punto esta a la derecha de la linea + if (p.x > l.x2) + { + return false; + } + + // Si ha llegado aquí, hay colisión + return true; +} + +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(line_t &l1, line_t &l2) +{ + const float x1 = l1.x1; + const float y1 = l1.y1; + const float x2 = l1.x2; + const float y2 = l1.y2; + + const float x3 = l2.x1; + const float y3 = l2.y1; + const float x4 = l2.x2; + const float y4 = l2.y2; + + // calculate the direction of the lines + float uA = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + float uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + + // if uA and uB are between 0-1, lines are colliding + if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) + { + // Calcula la intersección + const float x = x1 + (uA * (x2 - x1)); + const float y = y1 + (uA * (y2 - y1)); + + return {(int)round(x), (int)round(y)}; + } + return {-1, -1}; +} + +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(d_line_t &l1, v_line_t &l2) +{ + const float x1 = l1.x1; + const float y1 = l1.y1; + const float x2 = l1.x2; + const float y2 = l1.y2; + + const float x3 = l2.x; + const float y3 = l2.y1; + const float x4 = l2.x; + const float y4 = l2.y2; + + // calculate the direction of the lines + float uA = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + float uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + + // if uA and uB are between 0-1, lines are colliding + if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) + { + // Calcula la intersección + const float x = x1 + (uA * (x2 - x1)); + const float y = y1 + (uA * (y2 - y1)); + + return {(int)x, (int)y}; + } + return {-1, -1}; +} + +// Detector de colisiones entre una linea diagonal y una vertical +/*bool checkCollision(d_line_t &l1, v_line_t &l2) +{ + // Normaliza la linea diagonal + normalizeLine(l1); + + // Comprueba si la linea vertical esta a la izquierda de la linea diagonal + if (l2.x < l1.x1) + { + return false; + } + + // Comprueba si la linea vertical esta a la derecha de la linea diagonal + if (l2.x > l1.x2) + { + return false; + } + + // Inacabada + return true; +}*/ + +// Normaliza una linea diagonal +void normalizeLine(d_line_t &l) +{ + // Las lineas diagonales van de izquierda a derecha + // x2 mayor que x1 + if (l.x2 < l.x1) + { + const int x = l.x1; + const int y = l.y1; + l.x1 = l.x2; + l.y1 = l.y2; + l.x2 = x; + l.y2 = y; + } +} + +// Detector de colisiones entre un punto y una linea diagonal +bool checkCollision(SDL_Point &p, d_line_t &l) +{ + // Comprueba si el punto está en alineado con la linea + if (abs(p.x - l.x1) != abs(p.y - l.y1)) + { + return false; + } + + // Comprueba si está a la derecha de la linea + if (p.x > l.x1 && p.x > l.x2) + { + return false; + } + + // Comprueba si está a la izquierda de la linea + if (p.x < l.x1 && p.x < l.x2) + { + return false; + } + + // Comprueba si está por encima de la linea + if (p.y > l.y1 && p.y > l.y2) + { + return false; + } + + // Comprueba si está por debajo de la linea + if (p.y < l.y1 && p.y < l.y2) + { + return false; + } + + // En caso contrario, el punto está en la linea + return true; + + + /*const int m = (l.y2 - l.y1) / (l.x2 - l.x1); + const int c = 0; + + // Comprueba si p cumple la ecuación de la linea + if (p.y == ((m * p.x) + c)) + return true; + + return false;*/ } // Devuelve un color_t a partir de un string color_t stringToColor(std::string str) { - color_t color = {0x00, 0x00, 0x00}; - if (str == "black") + const std::string palette = "spectrum"; + + if (palette == "spectrum") { - color = {0x00, 0x00, 0x00}; + if (str == "black") + { + return {0x00, 0x00, 0x00}; + } + + else if (str == "bright_black") + { + return {0x00, 0x00, 0x00}; + } + + else if (str == "blue") + { + return {0x00, 0x00, 0xd8}; + } + + else if (str == "bright_blue") + { + return {0x00, 0x00, 0xFF}; + } + + else if (str == "red") + { + return {0xd8, 0x00, 0x00}; + } + + else if (str == "bright_red") + { + return {0xFF, 0x00, 0x00}; + } + + else if (str == "magenta") + { + return {0xd8, 0x00, 0xd8}; + } + + else if (str == "bright_magenta") + { + return {0xFF, 0x00, 0xFF}; + } + + else if (str == "green") + { + return {0x00, 0xd8, 0x00}; + } + + else if (str == "bright_green") + { + return {0x00, 0xFF, 0x00}; + } + + else if (str == "cyan") + { + return {0x00, 0xd8, 0xd8}; + } + + else if (str == "bright_cyan") + { + return {0x00, 0xFF, 0xFF}; + } + + else if (str == "yellow") + { + return {0xd8, 0xd8, 0x00}; + } + + else if (str == "bright_yellow") + { + return {0xFF, 0xFF, 0x00}; + } + + else if (str == "white") + { + return {0xd8, 0xd8, 0xd8}; + } + + else if (str == "bright_white") + { + return {0xFF, 0xFF, 0xFF}; + } } - else if (str == "light_black") + + else + { // zxarne + if (str == "black") + { + return {0x00, 0x00, 0x00}; + } + + else if (str == "bright_black") + { + return {0x3C, 0x35, 0x1F}; + } + + else if (str == "blue") + { + return {0x31, 0x33, 0x90}; + } + + else if (str == "bright_blue") + { + return {0x15, 0x59, 0xDB}; + } + + else if (str == "red") + { + return {0xA7, 0x32, 0x11}; + } + + else if (str == "bright_red") + { + return {0xD8, 0x55, 0x25}; + } + + else if (str == "magenta") + { + return {0xA1, 0x55, 0x89}; + } + + else if (str == "bright_magenta") + { + return {0xCD, 0x7A, 0x50}; + } + + else if (str == "green") + { + return {0x62, 0x9A, 0x31}; + } + + else if (str == "bright_green") + { + return {0x9C, 0xD3, 0x3C}; + } + + else if (str == "cyan") + { + return {0x28, 0xA4, 0xCB}; + } + + else if (str == "bright_cyan") + { + return {0x65, 0xDC, 0xD6}; + } + + else if (str == "yellow") + { + return {0xE8, 0xBC, 0x50}; + } + + else if (str == "bright_yellow") + { + return {0xF1, 0xE7, 0x82}; + } + + else if (str == "white") + { + return {0xBF, 0xBF, 0xBD}; + } + + else if (str == "bright_white") + { + return {0xF2, 0xF1, 0xED}; + } + } + + return {0x00, 0x00, 0x00}; +} + +// Convierte una cadena en un valor booleano +bool stringToBool(std::string str) +{ + if (str == "true") { - color = {0x3C, 0x35, 0x1F}; + return true; } - else if (str == "blue") + else { - color = {0x31, 0x33, 0x90}; + return false; } - else if (str == "light_blue") +} + +// Convierte un valor booleano en una cadena +std::string boolToString(bool value) +{ + if (value) { - color = {0x15, 0x59, 0xDB}; + return "true"; } - else if (str == "red") + else { - color = {0xA7, 0x32, 0x11}; + return "false"; } - else if (str == "light_red") - { - color = {0xD8, 0x55, 0x25}; - } - else if (str == "purple") - { - color = {0xA1, 0x55, 0x89}; - } - else if (str == "light_purple") - { - color = {0xCD, 0x7A, 0x50}; - } - else if (str == "green") - { - color = {0x62, 0x9A, 0x31}; - } - else if (str == "light_green") - { - color = {0x9C, 0xD3, 0x3C}; - } - else if (str == "cyan") - { - color = {0x28, 0xA4, 0xCB}; - } - else if (str == "light_cyan") - { - color = {0x65, 0xDC, 0xD6}; - } - else if (str == "yellow") - { - color = {0xE8, 0xBC, 0x50}; - } - else if (str == "light_yellow") - { - color = {0xF1, 0xE7, 0x82}; - } - else if (str == "white") - { - color = {0xBF, 0xBF, 0xBD}; - } - else if (str == "light_white") - { - color = {0xF2, 0xF1, 0xED}; - } - return color; } \ No newline at end of file diff --git a/source/utils.h b/source/utils.h index 2acf21f..da15b0b 100644 --- a/source/utils.h +++ b/source/utils.h @@ -7,25 +7,6 @@ #ifndef UTILS_H #define UTILS_H -#define FILTER_NEAREST 0 -#define FILTER_LINEAL 1 - -// Secciones del programa -#define SECTION_PROG_LOGO 0 -#define SECTION_PROG_INTRO 1 -#define SECTION_PROG_TITLE 2 -#define SECTION_PROG_GAME 3 -#define SECTION_PROG_QUIT 4 - -// Subsecciones -#define SUBSECTION_GAME_PLAY 0 -#define SUBSECTION_GAME_PAUSE 1 -#define SUBSECTION_GAME_GAMEOVER 2 -#define SUBSECTION_TITLE_1 3 -#define SUBSECTION_TITLE_2 4 -#define SUBSECTION_TITLE_3 5 -#define SUBSECTION_TITLE_INSTRUCTIONS 6 - // Estructura para definir un circulo struct circle_t { @@ -34,6 +15,30 @@ struct circle_t int r; }; +// Estructura para definir una linea horizontal +struct h_line_t +{ + int x1, x2, y; +}; + +// Estructura para definir una linea vertical +struct v_line_t +{ + int x, y1, y2; +}; + +// Estructura para definir una linea diagonal +struct d_line_t +{ + int x1, y1, x2, y2; +}; + +// Estructura para definir una linea +struct line_t +{ + int x1, y1, x2, y2; +}; + // Estructura para definir un color struct color_t { @@ -56,10 +61,12 @@ struct options_t int windowSize; // Contiene el valor por el que se multiplica el tamaño de la ventana Uint32 filter; // Filtro usado para el escalado de la imagen bool vSync; // Indica si se quiere usar vsync o no - int screenWidth; // Ancho de la pantalla/ventana - int screenHeight; // Alto de la pantalla/ventana + int screenWidth; // Ancho de la pantalla o ventana + int screenHeight; // Alto de la pantalla o ventana bool integerScale; // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa bool keepAspect; // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa + bool borderEnabled; // Indica si ha de mostrar el borde en el modo de ventana + float borderSize; // Porcentaje de borde que se añade a lo ventana }; // Calcula el cuadrado de la distancia entre dos puntos @@ -74,13 +81,37 @@ bool checkCollision(circle_t &a, SDL_Rect &b); // Detector de colisiones entre un dos rectangulos bool checkCollision(SDL_Rect &a, SDL_Rect &b); -// Detector de colisiones entre un punto y u rectangulo +// Detector de colisiones entre un punto y un rectangulo bool checkCollision(SDL_Point &p, SDL_Rect &r); -// Carga un archivo de imagen en una textura -bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer); +// Detector de colisiones entre una linea horizontal y un rectangulo +bool checkCollision(h_line_t &l, SDL_Rect &r); + +// Detector de colisiones entre una linea vertical y un rectangulo +bool checkCollision(v_line_t &l, SDL_Rect &r); + +// Detector de colisiones entre una linea horizontal y un punto +bool checkCollision(h_line_t &l, SDL_Point &p); + +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(line_t &l1, line_t &l2); + +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(d_line_t &l1, v_line_t &l2); + +// Detector de colisiones entre un punto y una linea diagonal +bool checkCollision(SDL_Point &p, d_line_t &l); + +// Normaliza una linea diagonal +void normalizeLine(d_line_t &l); // Devuelve un color_t a partir de un string color_t stringToColor(std::string str); +// Convierte una cadena en un valor booleano +bool stringToBool(std::string str); + +// Convierte un valor booleano en una cadena +std::string boolToString(bool value); + #endif \ No newline at end of file