From 48971cd5d150fe0680cfff64d02eb4f4ac3ab479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Valor=20Mart=C3=ADnez?= Date: Mon, 24 Feb 2025 08:52:11 +0100 Subject: [PATCH] canvi de pc --- source/animatedsprite.cpp | 12 +- source/ending.cpp | 8 +- source/item.cpp | 2 +- source/loading_screen.cpp | 10 +- source/logo.cpp | 4 +- source/movingsprite.cpp | 26 +-- source/notifier.cpp | 2 +- source/room.cpp | 6 +- source/sprite.cpp | 205 +++-------------------- source/sprite.h | 128 ++++++--------- source/text.cpp | 2 +- source/texture.cpp | 330 ++++++++++++++++++++++++++++---------- source/texture.h | 71 ++++++-- source/title.cpp | 6 +- 14 files changed, 420 insertions(+), 392 deletions(-) diff --git a/source/animatedsprite.cpp b/source/animatedsprite.cpp index e10e7833..7cfbe329 100644 --- a/source/animatedsprite.cpp +++ b/source/animatedsprite.cpp @@ -226,7 +226,7 @@ int AnimatedSprite::getIndex(std::string name) // Calcula el frame correspondiente a la animación void AnimatedSprite::animate() { - if (!enabled || animation[currentAnimation].speed == 0) + if (!enabled_ || animation[currentAnimation].speed == 0) { return; } @@ -253,7 +253,7 @@ void AnimatedSprite::animate() else { // Escoge el frame correspondiente de la animación - setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]); + setClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]); // Incrementa el contador de la animacion animation[currentAnimation].counter++; @@ -280,7 +280,7 @@ void AnimatedSprite::setCurrentFrame(int num) animation[currentAnimation].counter = 0; // Escoge el frame correspondiente de la animación - setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]); + setClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]); } // Establece el valor del contador @@ -459,13 +459,13 @@ bool AnimatedSprite::loadFromVector(std::vector *source) // Normaliza valores if (framesPerRow == 0 && frameWidth > 0) { - framesPerRow = texture->getWidth() / frameWidth; + framesPerRow = texture_->getWidth() / frameWidth; } if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0) { - const int w = texture->getWidth() / frameWidth; - const int h = texture->getHeight() / frameHeight; + const int w = texture_->getWidth() / frameWidth; + const int h = texture_->getHeight() / frameHeight; maxTiles = w * h; } } diff --git a/source/ending.cpp b/source/ending.cpp index 822a32a4..0bbbfe2f 100644 --- a/source/ending.cpp +++ b/source/ending.cpp @@ -266,7 +266,7 @@ void Ending::iniTexts() // Crea el sprite st.coverSprite = new Sprite({0, 0, st.coverTexture->getWidth(), st.coverTexture->getHeight() - 8}, st.coverTexture, renderer); st.coverSprite->setPos({(GAMECANVAS_WIDTH - st.coverTexture->getWidth()) / 2, t.pos}); - st.coverSprite->setSpriteClip(0, 8, -1, -1); + st.coverSprite->setClip(0, 8, -1, -1); // Inicializa variables st.clipDesp = 8; @@ -354,7 +354,7 @@ void Ending::iniPics() // Crea el sprite sp.coverSprite = new Sprite({0, 0, sp.coverTexture->getWidth(), sp.coverTexture->getHeight() - 8}, sp.coverTexture, renderer); sp.coverSprite->setPos({(GAMECANVAS_WIDTH - sp.coverTexture->getWidth()) / 2, p.pos}); - sp.coverSprite->setSpriteClip(0, 8, -1, -1); + sp.coverSprite->setClip(0, 8, -1, -1); // Inicializa variables sp.clipDesp = 8; @@ -500,7 +500,7 @@ void Ending::updateSpriteCovers() spriteTexts[ti.index].clipHeight -= 2; spriteTexts[ti.index].coverSprite->setPosY(spriteTexts[ti.index].coverSprite->getPosY() + 2); } - spriteTexts[ti.index].coverSprite->setSpriteClip(0, spriteTexts[ti.index].clipDesp, spriteTexts[ti.index].coverSprite->getWidth(), spriteTexts[ti.index].clipHeight); + spriteTexts[ti.index].coverSprite->setClip(0, spriteTexts[ti.index].clipDesp, spriteTexts[ti.index].coverSprite->getWidth(), spriteTexts[ti.index].clipHeight); } } } @@ -521,7 +521,7 @@ void Ending::updateSpriteCovers() } spritePics[scene].coverSprite->setPosY(spritePics[scene].coverSprite->getPosY() + 2); } - spritePics[scene].coverSprite->setSpriteClip(0, spritePics[scene].clipDesp, spritePics[scene].coverSprite->getWidth(), spritePics[scene].clipHeight); + spritePics[scene].coverSprite->setClip(0, spritePics[scene].clipDesp, spritePics[scene].coverSprite->getWidth(), spritePics[scene].clipHeight); } } diff --git a/source/item.cpp b/source/item.cpp index 248b7854..d2107ae8 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -11,7 +11,7 @@ Item::Item(item_t item) sprite = new Sprite(item.x, item.y, itemSize, itemSize, item.texture, item.renderer); // Inicia variables - sprite->setSpriteClip((item.tile % 10) * itemSize, (item.tile / 10) * itemSize, itemSize, itemSize); + sprite->setClip((item.tile % 10) * itemSize, (item.tile / 10) * itemSize, itemSize, itemSize); collider = sprite->getRect(); colorChangeSpeed = 4; counter = item.counter * colorChangeSpeed; diff --git a/source/loading_screen.cpp b/source/loading_screen.cpp index cf338527..dbba6e91 100644 --- a/source/loading_screen.cpp +++ b/source/loading_screen.cpp @@ -107,7 +107,7 @@ void LoadingScreen::updateLoad() { load_rect_.x = step * (counter_ % numSteps); load_rect_.y = line_index_[load_counter_]; - mono_loading_screen_sprite_->setSpriteClip(load_rect_); + mono_loading_screen_sprite_->setClip(load_rect_); mono_loading_screen_sprite_->setRect(load_rect_); } // Una vez actualizadas las 192 lineas, pasa a la segunda fase de la carga @@ -117,7 +117,7 @@ void LoadingScreen::updateLoad() load_counter_ = 0; load_rect_ = {0, 0, 16, 8}; color_loading_screen_sprite_->setRect(load_rect_); - color_loading_screen_sprite_->setSpriteClip(load_rect_); + color_loading_screen_sprite_->setClip(load_rect_); JA_PlayMusic(loading_sound3_); } } @@ -127,7 +127,7 @@ void LoadingScreen::updateLoad() load_counter_ += 2; load_rect_.x = (load_counter_ * 8) % 256; load_rect_.y = (load_counter_ / 32) * 8; - color_loading_screen_sprite_->setSpriteClip(load_rect_); + color_loading_screen_sprite_->setClip(load_rect_); color_loading_screen_sprite_->setRect(load_rect_); // Comprueba si ha terminado la intro @@ -269,7 +269,7 @@ void LoadingScreen::recreateLoadingScreen() load_counter_ = i / numSteps; load_rect_.x = step * (i % numSteps); load_rect_.y = line_index_[load_counter_]; - mono_loading_screen_sprite_->setSpriteClip(load_rect_); + mono_loading_screen_sprite_->setClip(load_rect_); mono_loading_screen_sprite_->setRect(load_rect_); mono_loading_screen_sprite_->render(); } @@ -281,7 +281,7 @@ void LoadingScreen::recreateLoadingScreen() { load_rect_.x = (i * 8) % 256; load_rect_.y = (i / 32) * 8; - color_loading_screen_sprite_->setSpriteClip(load_rect_); + color_loading_screen_sprite_->setClip(load_rect_); color_loading_screen_sprite_->setRect(load_rect_); color_loading_screen_sprite_->render(); } diff --git a/source/logo.cpp b/source/logo.cpp index 00be3c5a..f1eb457c 100644 --- a/source/logo.cpp +++ b/source/logo.cpp @@ -27,14 +27,14 @@ Logo::Logo() jailgames_texture_ = resource_->getTexture("jailgames.png"); since_1998_texture_ = resource_->getTexture("since_1998.png"); since_1998_sprite_ = new Sprite((256 - since_1998_texture_->getWidth()) / 2, 83 + jailgames_texture_->getHeight() + 5, since_1998_texture_->getWidth(), since_1998_texture_->getHeight(), since_1998_texture_, renderer_); - since_1998_sprite_->setSpriteClip(0, 0, since_1998_texture_->getWidth(), since_1998_texture_->getHeight()); + since_1998_sprite_->setClip(0, 0, since_1998_texture_->getWidth(), since_1998_texture_->getHeight()); since_1998_texture_->setColor(0, 0, 0); // Crea los sprites de cada linea for (int i = 0; i < jailgames_texture_->getHeight(); ++i) { jailgames_sprite_.push_back(new Sprite(0, i, jailgames_texture_->getWidth(), 1, jailgames_texture_, renderer_)); - jailgames_sprite_.back()->setSpriteClip(0, i, jailgames_texture_->getWidth(), 1); + jailgames_sprite_.back()->setClip(0, i, jailgames_texture_->getWidth(), 1); if (i % 2 == 0) { jailgames_sprite_[i]->setPosX(256 + (i * 3)); diff --git a/source/movingsprite.cpp b/source/movingsprite.cpp index 5e1d393b..aa5e13bf 100644 --- a/source/movingsprite.cpp +++ b/source/movingsprite.cpp @@ -5,12 +5,12 @@ MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture, SDL_Renderer *renderer) { // Copia los punteros - this->texture = texture; - this->renderer = renderer; + this->texture_ = texture; + this->renderer_ = renderer; // Establece el alto y el ancho del sprite - this->w = w; - this->h = h; + this->w_ = w; + this->h_ = h; // Establece la posición X,Y del sprite this->x = x; @@ -42,7 +42,7 @@ MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vel counter = 0; // Establece el rectangulo de donde coger la imagen - spriteClip = {0, 0, w, h}; + clip_ = {0, 0, w, h}; // Establece el centro de rotación center = nullptr; @@ -81,7 +81,7 @@ void MovingSprite::clear() // Mueve el sprite void MovingSprite::move() { - if (enabled) + if (enabled_) { xPrev = x; yPrev = y; @@ -97,9 +97,9 @@ void MovingSprite::move() // Muestra el sprite por pantalla void MovingSprite::render() { - if (enabled) + if (enabled_) { - texture->render(renderer, (int)x, (int)y, &spriteClip, zoomW, zoomH, angle, center, currentFlip); + texture_->render(renderer_, (int)x, (int)y, &clip_, zoomW, zoomH, angle, center, currentFlip); } } @@ -162,8 +162,8 @@ void MovingSprite::setRect(SDL_Rect rect) { x = (float)rect.x; y = (float)rect.y; - w = rect.w; - h = rect.h; + w_ = rect.w; + h_ = rect.h; } // Establece el valor de la variable @@ -247,7 +247,7 @@ Uint16 MovingSprite::getRotateSpeed() // Establece la rotacion void MovingSprite::rotate() { - if (enabled) + if (enabled_) if (rotateEnabled) { if (counter % rotateSpeed == 0) @@ -295,7 +295,7 @@ void MovingSprite::update() move(); rotate(); - if (enabled) + if (enabled_) { ++counter %= 60000; } @@ -380,7 +380,7 @@ bool MovingSprite::getFlipV() // Devuelve el rectangulo donde está el sprite SDL_Rect MovingSprite::getRect() { - const SDL_Rect rect = {(int)x, (int)y, w, h}; + const SDL_Rect rect = {(int)x, (int)y, w_, h_}; return rect; } diff --git a/source/notifier.cpp b/source/notifier.cpp index 2f8060b1..3958a77b 100644 --- a/source/notifier.cpp +++ b/source/notifier.cpp @@ -271,7 +271,7 @@ void Notifier::show(std::string text1, std::string text2, int icon) { Sprite *sp = new Sprite({0, 0, iconSize, iconSize}, icon_texture_, renderer_); sp->setPos({padding, padding, iconSize, iconSize}); - sp->setSpriteClip({iconSize * (icon % 10), iconSize * (icon / 10), iconSize, iconSize}); + sp->setClip({iconSize * (icon % 10), iconSize * (icon / 10), iconSize, iconSize}); sp->render(); delete sp; } diff --git a/source/room.cpp b/source/room.cpp index 0b954ab4..49cc4af7 100644 --- a/source/room.cpp +++ b/source/room.cpp @@ -1317,7 +1317,7 @@ void Room::setAnimatedTiles() aTile_t at; at.sprite = new Sprite(x, y, 8, 8, texture, renderer); - at.sprite->setSpriteClip(xc, yc, 8, 8); + at.sprite->setClip(xc, yc, 8, 8); at.xcOrig = xc; aTile.push_back(at); } @@ -1340,9 +1340,9 @@ void Room::updateAnimatedTiles() for (auto &a : aTile) { - SDL_Rect rect = a.sprite->getSpriteClip(); + SDL_Rect rect = a.sprite->getClip(); rect.x = a.xcOrig + offset; - a.sprite->setSpriteClip(rect); + a.sprite->setClip(rect); } } diff --git a/source/sprite.cpp b/source/sprite.cpp index cd7a81df..e89f12dd 100644 --- a/source/sprite.cpp +++ b/source/sprite.cpp @@ -2,201 +2,44 @@ #include "texture.h" // Para Texture // Constructor -Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *renderer) -{ - // Establece la posición X,Y del sprite - this->x = x; - this->y = y; +Sprite::Sprite(std::shared_ptr texture, int x, int y, int w, int h) + : texture_(texture), + pos_((SDL_Rect){x, y, w, h}), + clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {} - // Establece el alto y el ancho del sprite - this->w = w; - this->h = h; +Sprite::Sprite(std::shared_ptr texture, SDL_Rect rect) + : texture_(texture), + pos_(rect), + clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {} - // Establece el puntero al renderizador de la ventana - this->renderer = renderer; - - // Establece la textura donde están los gráficos para el sprite - this->texture = texture; - - // Establece el rectangulo de donde coger la imagen - spriteClip = {0, 0, w, h}; - - // Inicializa variables - enabled = true; -} - -Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer) -{ - // Establece la posición X,Y del sprite - this->x = rect.x; - this->y = rect.y; - - // Establece el alto y el ancho del sprite - this->w = rect.w; - this->h = rect.h; - - // Establece el puntero al renderizador de la ventana - this->renderer = renderer; - - // Establece la textura donde están los gráficos para el sprite - this->texture = texture; - - // Establece el rectangulo de donde coger la imagen - spriteClip = {0, 0, w, h}; - - // Inicializa variables - enabled = true; -} +Sprite::Sprite(std::shared_ptr texture) + : texture_(texture), + pos_({0, 0, texture_->getWidth(), texture_->getHeight()}), + clip_(pos_) {} // Muestra el sprite por pantalla void Sprite::render() { - if (enabled) - { - texture->render(renderer, x, y, &spriteClip); - } -} - -// Obten el valor de la variable -int Sprite::getPosX() -{ - return x; -} - -// Obten el valor de la variable -int Sprite::getPosY() -{ - return y; -} - -// Obten el valor de la variable -int Sprite::getWidth() -{ - return w; -} - -// Obten el valor de la variable -int Sprite::getHeight() -{ - return h; + texture_->render(pos_.x, pos_.y, &clip_, zoom_, zoom_); } // Establece la posición del objeto -void Sprite::setPos(SDL_Rect rect) +void Sprite::setPosition(int x, int y) { - this->x = rect.x; - this->y = rect.y; + pos_.x = x; + pos_.y = y; } -// Establece el valor de la variable -void Sprite::setPosX(int x) +// Establece la posición del objeto +void Sprite::setPosition(SDL_Point p) { - this->x = x; + pos_.x = p.x; + pos_.y = p.y; } -// Establece el valor de la variable -void Sprite::setPosY(int y) +// Reinicia las variables a cero +void Sprite::clear() { - this->y = y; -} - -// Incrementa el valor de la variable -void Sprite::incPosX(int value) -{ - x += value; -} - -// Incrementa el valor de la variable -void Sprite::incPosY(int value) -{ - y += value; -} - -// Establece el valor de la variable -void Sprite::setWidth(int w) -{ - this->w = w; -} - -// Establece el valor de la variable -void Sprite::setHeight(int h) -{ - this->h = h; -} - -// Obten el valor de la variable -SDL_Rect Sprite::getSpriteClip() -{ - return spriteClip; -} - -// Establece el valor de la variable -void Sprite::setSpriteClip(SDL_Rect rect) -{ - spriteClip = rect; -} - -// Establece el valor de la variable -void Sprite::setSpriteClip(int x, int y, int w, int h) -{ - if (w == -1 || h == -1) - { - spriteClip = {x, y, this->w, this->h}; - } - else - { - spriteClip = {x, y, w, h}; - } -} - -// Obten el valor de la variable -Texture *Sprite::getTexture() -{ - return texture; -} - -// Establece el valor de la variable -void Sprite::setTexture(Texture *texture) -{ - this->texture = texture; -} - -// Establece el valor de la variable -void Sprite::setRenderer(SDL_Renderer *renderer) -{ - this->renderer = renderer; -} - -// Obten el valor de la variable -SDL_Renderer *Sprite::getRenderer() -{ - return renderer; -} - -// Establece el valor de la variable -void Sprite::setEnabled(bool value) -{ - enabled = value; -} - -// Comprueba si el objeto está habilitado -bool Sprite::isEnabled() -{ - return enabled; -} - -// Devuelve el rectangulo donde está el sprite -SDL_Rect Sprite::getRect() -{ - SDL_Rect rect = {x, y, w, h}; - return rect; -} - -// Establece los valores de posición y tamaño del sprite -void Sprite::setRect(SDL_Rect rect) -{ - x = rect.x; - y = rect.y; - w = rect.w; - h = rect.h; + pos_ = {0, 0, 0, 0}; + clip_ = {0, 0, 0, 0}; } \ No newline at end of file diff --git a/source/sprite.h b/source/sprite.h index d57e4542..2cde4cce 100644 --- a/source/sprite.h +++ b/source/sprite.h @@ -1,96 +1,72 @@ #pragma once -#include // Para SDL_Rect -#include // Para SDL_Renderer +#include // Para SDL_Rect, SDL_Point +#include // Para shared_ptr class Texture; // Clase sprite class Sprite { protected: - // Objetos y punteros - SDL_Renderer *renderer; // Puntero al renderizador de la ventana - Texture *texture; // Textura donde estan todos los dibujos del sprite - // Variables - int x; // Posición en el eje X donde dibujar el sprite - int y; // Posición en el eje Y donde dibujar el sprite - int w; // Ancho del sprite - int h; // Alto del sprite - SDL_Rect spriteClip; // Rectangulo de origen de la textura que se dibujará en pantalla - bool enabled; // Indica si el sprite esta habilitado + std::shared_ptr texture_; // Textura donde estan todos los dibujos del sprite + SDL_Rect pos_; // Posición y tamaño donde dibujar el sprite + SDL_Rect clip_; // Rectangulo de origen de la textura que se dibujará en pantalla + double zoom_ = 1.0f; // Zoom aplicado a la textura public: // Constructor - Sprite(int x = 0, int y = 0, int w = 0, int h = 0, Texture *texture = nullptr, SDL_Renderer *renderer = nullptr); - Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer); + Sprite(std::shared_ptr, int x, int y, int w, int h); + Sprite(std::shared_ptr, SDL_Rect rect); + explicit Sprite(std::shared_ptr); + + // Destructor + virtual ~Sprite() = default; // Muestra el sprite por pantalla - void render(); + virtual void render(); - // Obten el valor de la variable - int getPosX(); + // Reinicia las variables a cero + virtual void clear(); - // Obten el valor de la variable - int getPosY(); - - // Obten el valor de la variable - int getWidth(); - - // Obten el valor de la variable - int getHeight(); - - // Establece la posición del objeto - void setPos(SDL_Rect rect); - - // Establece el valor de la variable - void setPosX(int x); - - // Establece el valor de la variable - void setPosY(int y); - - // Incrementa el valor de la variable - void incPosX(int value); - - // Incrementa el valor de la variable - void incPosY(int value); - - // Establece el valor de la variable - void setWidth(int w); - - // Establece el valor de la variable - void setHeight(int h); - - // Obten el valor de la variable - SDL_Rect getSpriteClip(); - - // Establece el valor de la variable - void setSpriteClip(SDL_Rect rect); - - // Establece el valor de la variable - void setSpriteClip(int x, int y, int w, int h); - - // Obten el valor de la variable - Texture *getTexture(); - - // Establece el valor de la variable - void setTexture(Texture *texture); - - // Establece el valor de la variable - void setRenderer(SDL_Renderer *renderer); - - // Obten el valor de la variable - SDL_Renderer *getRenderer(); - - // Establece el valor de la variable - void setEnabled(bool value); - - // Comprueba si el objeto está habilitado - bool isEnabled(); + // Obtiene la posición y el tamaño + int getX() const { return pos_.x; } + int getY() const { return pos_.y; } + int getWidth() const { return pos_.w; } + int getHeight() const { return pos_.h; } // Devuelve el rectangulo donde está el sprite - SDL_Rect getRect(); + SDL_Rect getPosition() const { return pos_; } + SDL_Rect &getRect() { return pos_; } - // Establece los valores de posición y tamaño del sprite - void setRect(SDL_Rect rect); + // Establece la posición y el tamaño + void setX(int x) { pos_.x = x; } + void setY(int y) { pos_.y = y; } + void setWidth(int w) { pos_.w = w; } + void setHeight(int h) { pos_.h = h; } + + // Establece la posición del objeto + void setPosition(int x, int y); + void setPosition(SDL_Point p); + void setPosition(SDL_Rect r) { pos_ = r; } + + // Establece el nivel de zoom + void setZoom(float zoom) { zoom_ = zoom; } + + // Aumenta o disminuye la posición + void incX(int value) { pos_.x += value; } + void incY(int value) { pos_.y += value; } + + // Obtiene el rectangulo que se dibuja de la textura + SDL_Rect getClip() const { return clip_; } + + // Establece el rectangulo que se dibuja de la textura + void setClip(SDL_Rect rect) { clip_ = rect; } + void setClip(int x, int y, int w, int h) { clip_ = (SDL_Rect){x, y, w, h}; } + + // Obtiene un puntero a la textura + std::shared_ptr getTexture() const { return texture_; } + + // Establece la textura a utilizar + void setTexture(std::shared_ptr texture) { texture_ = texture; } }; \ No newline at end of file diff --git a/source/text.cpp b/source/text.cpp index 6623c23e..6a70bff2 100644 --- a/source/text.cpp +++ b/source/text.cpp @@ -137,7 +137,7 @@ void Text::write(int x, int y, std::string text, int kerning, int lenght) for (int i = 0; i < lenght; ++i) { - sprite->setSpriteClip(offset[int(text[i])].x, offset[int(text[i])].y, sprite->getWidth(), sprite->getHeight()); + sprite->setClip(offset[int(text[i])].x, offset[int(text[i])].y, sprite->getWidth(), sprite->getHeight()); sprite->setPosX(x + shift); sprite->setPosY(y); sprite->render(); diff --git a/source/texture.cpp b/source/texture.cpp index 59ad804b..4eaacea1 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -1,105 +1,113 @@ + #include "texture.h" #include // Para SDL_GetError -#include // Para SDL_Log -#include // Para SDL_PIXELFORMAT_RGB24, SDL_PIXELFORMAT... #include // Para SDL_CreateRGBSurfaceWithFormatFrom -#include // Para exit -#include // Para basic_ostream, operator<<, cout, endl +#include // Para basic_ostream, operator<<, basic_ifstream +#include // Para cerr, cout +#include // Para runtime_error +#include // Para char_traits, operator<<, operator+ +#include // Para vector +#include "gif.c" // Para LoadGif, LoadPalette +#include "stb_image.h" // Para stbi_image_free, stbi_load, STBI_rgb_a... +#include "utils.h" // Para getFileName, printWithDots + #define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" // Para stbi_failure_reason, stbi_image_free +#include "stb_image.h" // para stbi_failure_reason, stbi_image_free // Constructor -Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose) +Texture::Texture(SDL_Renderer *renderer, const std::string &path) + : renderer_(renderer), + path_(path) { - // Copia punteros - this->renderer = renderer; - this->path = path; - - // Inicializa - texture = nullptr; - width = 0; - height = 0; - // Carga el fichero en la textura - if (path != "") + if (!path_.empty()) { - loadFromFile(path, renderer, verbose); + // Obtiene la extensión + const std::string extension = path_.substr(path_.find_last_of(".") + 1); + + // .png + if (extension == "png") + { + loadFromFile(path_); + } + + // .gif + else if (extension == "gif") + { + // Crea la surface desde un fichero + surface_ = loadSurface(path_); + + // Añade la propia paleta del fichero a la lista + addPaletteFromFile(path_); + // setPaletteColor(0, 0, 0x00000000); + + // Crea la textura, establece el BlendMode y copia la surface a la textura + createBlank(width_, height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING); + SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND); + flipSurface(); + } } } // Destructor Texture::~Texture() { - // Libera memoria - unload(); + unloadTexture(); + unloadSurface(); + palettes_.clear(); } // Carga una imagen desde un fichero -bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose) +bool Texture::loadFromFile(const std::string &file_path) { - const std::string filename = path.substr(path.find_last_of("\\/") + 1); + if (file_path.empty()) + return false; + int req_format = STBI_rgb_alpha; int width, height, orig_format; - unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format); - if (data == nullptr) + unsigned char *data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format); + if (!data) { - SDL_Log("Loading image failed: %s", stbi_failure_reason()); - exit(1); + std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl; + throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path)); } else { - if (verbose) - { - std::cout << "Image loaded: " << filename.c_str() << std::endl; - } + printWithDots("Image : ", getFileName(file_path), "[ LOADED ]"); } int depth, pitch; Uint32 pixel_format; - if (req_format == STBI_rgb) - { - depth = 24; - pitch = 3 * width; // 3 bytes por pixel * pixels per linea - pixel_format = SDL_PIXELFORMAT_RGB24; - } - else - { // STBI_rgb_alpha (RGBA) - depth = 32; - pitch = 4 * width; - pixel_format = SDL_PIXELFORMAT_RGBA32; - } + // STBI_rgb_alpha (RGBA) + depth = 32; + pitch = 4 * width; + pixel_format = SDL_PIXELFORMAT_RGBA32; // Limpia - unload(); + unloadTexture(); // La textura final SDL_Texture *newTexture = nullptr; // Carga la imagen desde una ruta específica - SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format); + auto loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom(static_cast(data), width, height, depth, pitch, pixel_format); if (loadedSurface == nullptr) { - if (verbose) - { - std::cout << "Unable to load image " << path.c_str() << std::endl; - } + std::cout << "Unable to load image " << file_path << std::endl; } else { // Crea la textura desde los pixels de la surface - newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface); + newTexture = SDL_CreateTextureFromSurface(renderer_, loadedSurface); if (newTexture == nullptr) { - if (verbose) - { - std::cout << "Unable to create texture from " << path.c_str() << "! SDL Error: " << SDL_GetError() << std::endl; - } + std::cout << "Unable to create texture from " << file_path << "! SDL Error: " << SDL_GetError() << std::endl; } else { // Obtiene las dimensiones de la imagen - this->width = loadedSurface->w; - this->height = loadedSurface->h; + width_ = loadedSurface->w; + height_ = loadedSurface->h; } // Elimina la textura cargada @@ -108,64 +116,68 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbos // Return success stbi_image_free(data); - texture = newTexture; - return texture != nullptr; + texture_ = newTexture; + return texture_ != nullptr; } // Crea una textura en blanco -bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access) +bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL_TextureAccess access) { // Crea una textura sin inicializar - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height); - if (texture == nullptr) + texture_ = SDL_CreateTexture(renderer_, format, access, width, height); + if (!texture_) { std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl; } else { - this->width = width; - this->height = height; + width_ = width; + height_ = height; } - return texture != nullptr; + return texture_ != nullptr; } // Libera la memoria de la textura -void Texture::unload() +void Texture::unloadTexture() { - // Libera la textura si existe - if (texture != nullptr) + // Libera la textura + if (texture_) { - SDL_DestroyTexture(texture); - texture = nullptr; - width = 0; - height = 0; + SDL_DestroyTexture(texture_); + texture_ = nullptr; + width_ = 0; + height_ = 0; } } // Establece el color para la modulacion void Texture::setColor(Uint8 red, Uint8 green, Uint8 blue) { - SDL_SetTextureColorMod(texture, red, green, blue); + SDL_SetTextureColorMod(texture_, red, green, blue); +} +void Texture::setColor(Color color) +{ + SDL_SetTextureColorMod(texture_, color.r, color.g, color.b); } // Establece el blending void Texture::setBlendMode(SDL_BlendMode blending) { - SDL_SetTextureBlendMode(texture, blending); + SDL_SetTextureBlendMode(texture_, blending); } // Establece el alpha para la modulación void Texture::setAlpha(Uint8 alpha) { - SDL_SetTextureAlphaMod(texture, alpha); + SDL_SetTextureAlphaMod(texture_, alpha); } // Renderiza la textura en un punto específico -void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_RendererFlip flip) +void Texture::render(int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_RendererFlip flip) { // Establece el destino de renderizado en la pantalla - SDL_Rect renderQuad = {x, y, width, height}; + SDL_Rect renderQuad = {x, y, width_, height_}; // Obtiene las dimesiones del clip de renderizado if (clip != nullptr) @@ -174,39 +186,193 @@ void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float renderQuad.h = clip->h; } - renderQuad.w = renderQuad.w * zoomW; - renderQuad.h = renderQuad.h * zoomH; + // Calcula el zoom y las coordenadas + if (zoomH != 1.0f || zoomW != 1.0f) + { + renderQuad.x = renderQuad.x + (renderQuad.w / 2); + renderQuad.y = renderQuad.y + (renderQuad.h / 2); + renderQuad.w = renderQuad.w * zoomW; + renderQuad.h = renderQuad.h * zoomH; + renderQuad.x = renderQuad.x - (renderQuad.w / 2); + renderQuad.y = renderQuad.y - (renderQuad.h / 2); + } // Renderiza a pantalla - SDL_RenderCopyEx(renderer, texture, clip, &renderQuad, angle, center, flip); + SDL_RenderCopyEx(renderer_, texture_, clip, &renderQuad, angle, center, flip); } // Establece la textura como objetivo de renderizado void Texture::setAsRenderTarget(SDL_Renderer *renderer) { - SDL_SetRenderTarget(renderer, texture); + SDL_SetRenderTarget(renderer, texture_); } // Obtiene el ancho de la imagen int Texture::getWidth() { - return width; + return width_; } // Obtiene el alto de la imagen int Texture::getHeight() { - return height; + return height_; } // Recarga la textura bool Texture::reLoad() { - return loadFromFile(path, renderer); + return loadFromFile(path_); } // Obtiene la textura SDL_Texture *Texture::getSDLTexture() { - return texture; + return texture_; +} + +// Desencadenar la superficie actual +void Texture::unloadSurface() +{ + surface_.reset(); // Resetea el shared_ptr + width_ = 0; + height_ = 0; +} + +// Crea una surface desde un fichero .gif +std::shared_ptr Texture::loadSurface(const std::string &file_path) +{ + // Desencadenar la superficie actual + unloadSurface(); + + // Abrir el archivo usando std::ifstream para manejo automático del recurso + std::ifstream file(file_path, std::ios::binary | std::ios::ate); + if (!file) + { + std::cerr << "Error: Fichero no encontrado " << file_path << std::endl; + throw std::runtime_error("Fichero no encontrado: " + file_path); + } + + // Obtener el tamaño del archivo + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + + // Leer el contenido del archivo en un buffer + std::vector buffer(size); + if (!file.read(reinterpret_cast(buffer.data()), size)) + { + std::cerr << "Error al leer el fichero " << file_path << std::endl; + throw std::runtime_error("Error al leer el fichero: " + file_path); + } + + // Cerrar el archivo (automáticamente manejado por std::ifstream) + file.close(); + + // Llamar a la función LoadGif + Uint16 w, h; + Uint8 *rawPixels = LoadGif(buffer.data(), &w, &h); + if (!rawPixels) + { + return nullptr; + } + + // Crear un std::shared_ptr con std::make_shared para pixels + auto pixels = std::shared_ptr(rawPixels, std::default_delete()); + auto surface = std::make_shared(w, h, pixels); + + // Actualizar la anchura y altura + width_ = w; + height_ = h; + + return surface; +} + +// Vuelca la surface en la textura +void Texture::flipSurface() +{ + // Limpia la textura + auto temp = SDL_GetRenderTarget(renderer_); + SDL_SetRenderTarget(renderer_, texture_); + SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0); + SDL_RenderClear(renderer_); + SDL_SetRenderTarget(renderer_, temp); + + // Vuelca los datos + Uint32 *pixels; + int pitch; + SDL_LockTexture(texture_, nullptr, reinterpret_cast(&pixels), &pitch); + for (int i = 0; i < width_ * height_; ++i) + { + pixels[i] = palettes_[current_palette_][surface_->data[i]]; + } + SDL_UnlockTexture(texture_); +} + +// Establece un color de la paleta +void Texture::setPaletteColor(int palette, int index, Uint32 color) +{ + palettes_.at(palette)[index] = color; +} + +// Carga una paleta desde un fichero +std::vector Texture::loadPaletteFromFile(const std::string &file_path) +{ + std::vector palette; + + std::ifstream file(file_path, std::ios::binary | std::ios::ate); + if (!file) + { + std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl; + throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path)); + } + else + { + printWithDots("Image : ", getFileName(file_path), "[ LOADED ]"); + } + + auto size = file.tellg(); + file.seekg(0, std::ios::beg); + + std::vector buffer(size); + if (!file.read(reinterpret_cast(buffer.data()), size)) + { + std::cerr << "Error: No se pudo leer completamente el fichero " << getFileName(file_path) << std::endl; + throw std::runtime_error("Error al leer el fichero: " + getFileName(file_path)); + } + + const auto pal = LoadPalette(buffer.data()); + if (!pal) + { + return palette; + } + + for (int i = 0; i < 256; ++i) + { + palette.push_back((pal[i] << 8) + 255); + } + + return palette; +} + +// Añade una paleta a la lista +void Texture::addPaletteFromFile(const std::string &path) +{ + palettes_.emplace_back(loadPaletteFromFile(path)); + setPaletteColor((int)palettes_.size() - 1, 0, 0x00000000); +} + +// Cambia la paleta de la textura +void Texture::setPalette(int palette) +{ + if (palette < (int)palettes_.size()) + { + current_palette_ = palette; + flipSurface(); + } +} + +// Obtiene el renderizador +SDL_Renderer *Texture::getRenderer() +{ + return renderer_; } \ No newline at end of file diff --git a/source/texture.h b/source/texture.h index 5fefe7c8..16cc4e6e 100644 --- a/source/texture.h +++ b/source/texture.h @@ -1,41 +1,72 @@ #pragma once #include // Para SDL_BlendMode +#include // Para SDL_PIXELFORMAT_RGBA8888, SDL_PixelF... #include // Para SDL_Point, SDL_Rect #include // Para SDL_Renderer, SDL_FLIP_NONE, SDL_TEX... -#include // Para Uint8 -#include // Para basic_string, string +#include // Para Uint8, Uint16, Uint32 +#include // Para shared_ptr +#include // Para string +#include // Para vector +struct Color; + +// Definiciones de tipos +struct Surface +{ + std::shared_ptr data; + Uint16 w, h; + + // Constructor + Surface(Uint16 width, Uint16 height, std::shared_ptr pixels) + : data(pixels), w(width), h(height) {} +}; class Texture { private: // Objetos y punteros - SDL_Texture *texture; // La textura - SDL_Renderer *renderer; // Renderizador donde dibujar la textura + SDL_Renderer *renderer_; // Renderizador donde dibujar la textura + SDL_Texture *texture_ = nullptr; // La textura + std::shared_ptr surface_ = nullptr; // Surface para usar imagenes en formato gif con paleta // Variables - int width; // Ancho de la imagen - int height; // Alto de la imagen - std::string path; // Ruta de la imagen de la textura + std::string path_; // Ruta de la imagen de la textura + int width_ = 0; // Ancho de la imagen + int height_ = 0; // Alto de la imagen + std::vector> palettes_; // Vector con las diferentes paletas + int current_palette_ = 0; // Indice de la paleta en uso + + // Crea una surface desde un fichero .gif + std::shared_ptr loadSurface(const std::string &file_name); + + // Vuelca la surface en la textura + void flipSurface(); + + // Carga una paleta desde un fichero + std::vector loadPaletteFromFile(const std::string &file_name); + + // Libera la memoria de la textura + void unloadTexture(); + + // Desencadenar la superficie actual + void unloadSurface(); public: // Constructor - Texture(SDL_Renderer *renderer, std::string path = "", bool verbose = false); + explicit Texture(SDL_Renderer *renderer, const std::string &path = std::string()); // Destructor ~Texture(); // Carga una imagen desde un fichero - bool loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose = false); + bool loadFromFile(const std::string &path); // Crea una textura en blanco - bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); - - // Libera la memoria de la textura - void unload(); + bool createBlank(int width, int height, SDL_PixelFormatEnum format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); // Establece el color para la modulacion void setColor(Uint8 red, Uint8 green, Uint8 blue); + void setColor(Color color); // Establece el blending void setBlendMode(SDL_BlendMode blending); @@ -44,7 +75,7 @@ public: void setAlpha(Uint8 alpha); // Renderiza la textura en un punto específico - void render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip = nullptr, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_Point *center = nullptr, SDL_RendererFlip flip = SDL_FLIP_NONE); + void render(int x, int y, SDL_Rect *clip = nullptr, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_Point *center = nullptr, SDL_RendererFlip flip = SDL_FLIP_NONE); // Establece la textura como objetivo de renderizado void setAsRenderTarget(SDL_Renderer *renderer); @@ -60,4 +91,16 @@ public: // Obtiene la textura SDL_Texture *getSDLTexture(); + + // Añade una paleta a la lista + void addPaletteFromFile(const std::string &path); + + // Establece un color de la paleta + void setPaletteColor(int palette, int index, Uint32 color); + + // Cambia la paleta de la textura + void setPalette(int palette); + + // Obtiene el renderizador + SDL_Renderer *getRenderer(); }; \ No newline at end of file diff --git a/source/title.cpp b/source/title.cpp index 9243866a..213b9f56 100644 --- a/source/title.cpp +++ b/source/title.cpp @@ -367,7 +367,7 @@ void Title::moveCheevosList(int direction) cheevos_texture_view_.y = bottom; } - cheevos_sprite_->setSpriteClip(cheevos_texture_view_); + cheevos_sprite_->setClip(cheevos_texture_view_); } // Rellena la textura de fondo con todos los gráficos @@ -445,7 +445,7 @@ void Title::createCheevosTexture() // Crea el sprite para el listado de logros cheevos_sprite_ = new Sprite((GAMECANVAS_WIDTH - cheevos_texture_->getWidth()) / 2, cheevosTexturePosY, cheevos_texture_->getWidth(), cheevos_texture_->getHeight(), cheevos_texture_, renderer_); cheevos_texture_view_ = {0, 0, cheevos_texture_->getWidth(), cheevosTextureViewHeight}; - cheevos_sprite_->setSpriteClip(cheevos_texture_view_); + cheevos_sprite_->setClip(cheevos_texture_view_); } // Oculta la lista de logros @@ -453,5 +453,5 @@ void Title::hideCheevosList() { show_cheevos_ = false; cheevos_texture_view_.y = 0; - cheevos_sprite_->setSpriteClip(cheevos_texture_view_); + cheevos_sprite_->setClip(cheevos_texture_view_); } \ No newline at end of file