gonna fer un commit per si reventa algo: estic a meitat implementar surfaces
This commit is contained in:
BIN
data/test.gif
Normal file
BIN
data/test.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 630 B |
@@ -396,6 +396,9 @@ bool Director::setFileList()
|
||||
// Datos
|
||||
Asset::get()->add(prefix + "/data/input/gamecontrollerdb.txt", AssetType::DATA);
|
||||
|
||||
// Test
|
||||
Asset::get()->add(prefix + "/data/test.gif", AssetType::DATA);
|
||||
|
||||
// Ficheros de sistema
|
||||
Asset::get()->add(system_folder_ + "/config.txt", AssetType::DATA, false, true);
|
||||
Asset::get()->add(system_folder_ + "/stats_buffer.csv", AssetType::DATA, false, true);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "notifier.h"
|
||||
#include "global_inputs.h"
|
||||
#include "global_events.h"
|
||||
#include "surface.h"
|
||||
|
||||
// Constructor
|
||||
Game::Game()
|
||||
@@ -36,6 +37,7 @@ Game::Game()
|
||||
cheevos_(Cheevos::get())
|
||||
{
|
||||
// Inicia algunas variables
|
||||
std::make_shared<Surface>(Screen::get()->getGameSurface(), "test.gif");
|
||||
board_ = std::make_shared<ScoreboardData>();
|
||||
board_->ini_clock = SDL_GetTicks();
|
||||
#ifdef DEBUG
|
||||
@@ -258,8 +260,10 @@ void Game::update()
|
||||
// Pinta los objetos en pantalla
|
||||
void Game::render()
|
||||
{
|
||||
|
||||
// Prepara para dibujar el frame
|
||||
screen_->start();
|
||||
test_surface_->render(0, 0, 10, 10, 64, 64);
|
||||
|
||||
// Dibuja los elementos del juego en orden
|
||||
room_->renderMap();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "player.h" // Para playerSpawn_t
|
||||
#include "scoreboard.h" // Para board_t
|
||||
#include "room.h"
|
||||
#include "surface.h"
|
||||
class Asset;
|
||||
class Cheevos;
|
||||
class Debug;
|
||||
@@ -42,6 +43,7 @@ private:
|
||||
std::shared_ptr<Scoreboard> scoreboard_; // Objeto encargado de gestionar el marcador
|
||||
std::shared_ptr<Stats> stats_; // Objeto encargado de gestionar las estadísticas
|
||||
SDL_Texture *room_name_texture_; // Textura para escribir el nombre de la habitación
|
||||
std::shared_ptr<Surface> test_surface_;
|
||||
|
||||
// Variables
|
||||
JA_Music_t *music_; // Musica que suena durante el juego
|
||||
|
||||
@@ -1,94 +1,9 @@
|
||||
#include "gif.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define EXTENSION_INTRODUCER 0x21
|
||||
#define IMAGE_DESCRIPTOR 0x2C
|
||||
#define TRAILER 0x3B
|
||||
|
||||
#define GRAPHIC_CONTROL 0xF9
|
||||
#define APPLICATION_EXTENSION 0xFF
|
||||
#define COMMENT_EXTENSION 0xFE
|
||||
#define PLAINTEXT_EXTENSION 0x01
|
||||
|
||||
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
unsigned char fields;
|
||||
unsigned char background_color_index;
|
||||
unsigned char pixel_aspect_ratio;
|
||||
}
|
||||
screen_descriptor_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
}
|
||||
rgb;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short image_left_position;
|
||||
unsigned short image_top_position;
|
||||
unsigned short image_width;
|
||||
unsigned short image_height;
|
||||
unsigned char fields;
|
||||
}
|
||||
image_descriptor_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char byte;
|
||||
int prev;
|
||||
int len;
|
||||
}
|
||||
dictionary_entry_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char extension_code;
|
||||
unsigned char block_size;
|
||||
}
|
||||
extension_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char fields;
|
||||
unsigned short delay_time;
|
||||
unsigned char transparent_color_index;
|
||||
}
|
||||
graphic_control_extension_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char application_id[ 8 ];
|
||||
unsigned char version[ 3 ];
|
||||
}
|
||||
application_extension_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short left;
|
||||
unsigned short top;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
unsigned char cell_width;
|
||||
unsigned char cell_height;
|
||||
unsigned char foreground_color;
|
||||
unsigned char background_color;
|
||||
}
|
||||
plaintext_extension_t;
|
||||
|
||||
//static unsigned short width = 0;
|
||||
//static unsigned short height = 0;
|
||||
//static unsigned char* uncompressed_data = NULL;
|
||||
|
||||
void uncompress( int code_length,
|
||||
const unsigned char *input,
|
||||
int input_length,
|
||||
65
source/gif.h
Normal file
65
source/gif.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define EXTENSION_INTRODUCER 0x21
|
||||
#define IMAGE_DESCRIPTOR 0x2C
|
||||
#define TRAILER 0x3B
|
||||
#define GRAPHIC_CONTROL 0xF9
|
||||
#define APPLICATION_EXTENSION 0xFF
|
||||
#define COMMENT_EXTENSION 0xFE
|
||||
#define PLAINTEXT_EXTENSION 0x01
|
||||
|
||||
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
|
||||
|
||||
typedef struct {
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
unsigned char fields;
|
||||
unsigned char background_color_index;
|
||||
unsigned char pixel_aspect_ratio;
|
||||
} screen_descriptor_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char r, g, b;
|
||||
} rgb;
|
||||
|
||||
typedef struct {
|
||||
unsigned short image_left_position;
|
||||
unsigned short image_top_position;
|
||||
unsigned short image_width;
|
||||
unsigned short image_height;
|
||||
unsigned char fields;
|
||||
} image_descriptor_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char byte;
|
||||
int prev;
|
||||
int len;
|
||||
} dictionary_entry_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char extension_code;
|
||||
unsigned char block_size;
|
||||
} extension_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char fields;
|
||||
unsigned short delay_time;
|
||||
unsigned char transparent_color_index;
|
||||
} graphic_control_extension_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char application_id[8];
|
||||
unsigned char version[3];
|
||||
} application_extension_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned short left, top, width, height;
|
||||
unsigned char cell_width, cell_height;
|
||||
unsigned char foreground_color, background_color;
|
||||
} plaintext_extension_t;
|
||||
|
||||
void uncompress(int code_length, const unsigned char *input, int input_length, unsigned char *out);
|
||||
uint32_t* LoadPalette(unsigned char *buffer);
|
||||
unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h);
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <fcntl.h> // Para SEEK_END, SEEK_SET
|
||||
#include <stdio.h> // Para NULL, fseek, fclose, fopen, fread, ftell
|
||||
#include <stdlib.h> // Para malloc, free
|
||||
#include "gif.c" // Para LoadGif, LoadPalette
|
||||
#include "gif.h" // Para LoadGif, LoadPalette
|
||||
|
||||
struct jSurface_s
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "notifier.h" // Para Notify
|
||||
#include "options.h"
|
||||
#include "mouse.h"
|
||||
#include "surface.h"
|
||||
|
||||
// [SINGLETON]
|
||||
Screen *Screen::screen_ = nullptr;
|
||||
@@ -50,27 +51,41 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
|
||||
// Establece el modo de escalado
|
||||
SDL_RenderSetIntegerScale(renderer_, options.video.integer_scale ? SDL_TRUE : SDL_FALSE);
|
||||
|
||||
// Crea la textura donde se dibujan los graficos del juego
|
||||
game_canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width, options.game.height);
|
||||
if (game_canvas_ == nullptr)
|
||||
// Crea la textura donde se vuelcan las surfaces
|
||||
surface_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, options.game.width, options.game.height);
|
||||
if (surface_texture_ == nullptr)
|
||||
{
|
||||
if (options.console)
|
||||
{
|
||||
std::cout << "gameCanvas could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||
std::cout << "surface_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Crea la textura donde se dibujan los graficos del juego
|
||||
game_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width, options.game.height);
|
||||
if (game_texture_ == nullptr)
|
||||
{
|
||||
if (options.console)
|
||||
{
|
||||
std::cout << "game_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Crea la textura donde se dibuja el borde que rodea el area de juego
|
||||
border_canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width + options.video.border.width * 2, options.game.height + options.video.border.height * 2);
|
||||
if (border_canvas_ == nullptr)
|
||||
border_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options.game.width + options.video.border.width * 2, options.game.height + options.video.border.height * 2);
|
||||
if (border_texture_ == nullptr)
|
||||
{
|
||||
if (options.console)
|
||||
{
|
||||
std::cout << "borderCanvas could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||
std::cout << "border_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
||||
}
|
||||
}
|
||||
setBorderColor(border_color_);
|
||||
|
||||
// Crea la surface donde se pinta el juego
|
||||
surface_ = std::make_shared<Surface>(nullptr, options.game.width, options.game.height);
|
||||
surface_->loadPalette(Asset::get()->get("test.gif"));
|
||||
|
||||
// Establece el modo de video
|
||||
setVideoMode(options.video.mode);
|
||||
|
||||
@@ -82,8 +97,9 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
|
||||
// Destructor
|
||||
Screen::~Screen()
|
||||
{
|
||||
SDL_DestroyTexture(game_canvas_);
|
||||
SDL_DestroyTexture(border_canvas_);
|
||||
SDL_DestroyTexture(surface_texture_);
|
||||
SDL_DestroyTexture(game_texture_);
|
||||
SDL_DestroyTexture(border_texture_);
|
||||
}
|
||||
|
||||
// Limpia la pantalla
|
||||
@@ -96,13 +112,14 @@ void Screen::clean(Color color)
|
||||
// Prepara para empezar a dibujar en la textura de juego
|
||||
void Screen::start()
|
||||
{
|
||||
SDL_SetRenderTarget(renderer_, game_canvas_);
|
||||
surface_->clear(surface_->getSurface(), surface_->getTransparentColor());
|
||||
SDL_SetRenderTarget(renderer_, game_texture_);
|
||||
}
|
||||
|
||||
// Prepara para empezar a dibujar en la textura del borde
|
||||
void Screen::startDrawOnBorder()
|
||||
{
|
||||
SDL_SetRenderTarget(renderer_, border_canvas_);
|
||||
SDL_SetRenderTarget(renderer_, border_texture_);
|
||||
}
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
@@ -111,6 +128,8 @@ void Screen::render()
|
||||
// Renderiza sobre gameCanvas los overlays
|
||||
renderNotifications();
|
||||
|
||||
surface_->copyToTexture(renderer_, game_texture_);
|
||||
|
||||
// Si está el borde activo, vuelca gameCanvas sobre borderCanvas
|
||||
if (options.video.border.enabled)
|
||||
{
|
||||
@@ -174,11 +193,11 @@ void Screen::setVideoMode(int videoMode)
|
||||
|
||||
if (options.video.border.enabled)
|
||||
{
|
||||
shader::init(window_, border_canvas_, source.c_str());
|
||||
shader::init(window_, border_texture_, source.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
shader::init(window_, game_canvas_, source.c_str());
|
||||
shader::init(window_, game_texture_, source.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,7 +252,7 @@ void Screen::setBorderColor(Color color)
|
||||
{
|
||||
border_color_ = color;
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, border_canvas_);
|
||||
SDL_SetRenderTarget(renderer_, border_texture_);
|
||||
SDL_SetRenderDrawColor(renderer_, border_color_.r, border_color_.g, border_color_.b, 0xFF);
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
@@ -279,8 +298,8 @@ void Screen::renderNotifications()
|
||||
void Screen::gameCanvasToBorderCanvas()
|
||||
{
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, border_canvas_);
|
||||
SDL_RenderCopy(renderer_, game_canvas_, nullptr, &game_canvas_rect_);
|
||||
SDL_SetRenderTarget(renderer_, border_texture_);
|
||||
SDL_RenderCopy(renderer_, game_texture_, nullptr, &game_texture_rect_);
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
}
|
||||
|
||||
@@ -300,11 +319,11 @@ void Screen::renderPresent()
|
||||
{
|
||||
if (options.video.border.enabled)
|
||||
{
|
||||
SDL_RenderCopy(renderer_, border_canvas_, nullptr, nullptr);
|
||||
SDL_RenderCopy(renderer_, border_texture_, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_RenderCopy(renderer_, game_canvas_, nullptr, &game_canvas_rect_);
|
||||
SDL_RenderCopy(renderer_, game_texture_, nullptr, &game_texture_rect_);
|
||||
}
|
||||
SDL_RenderPresent(renderer_);
|
||||
}
|
||||
@@ -364,7 +383,7 @@ void Screen::adjustWindowSize()
|
||||
// Ajusta game_canvas_rect_
|
||||
void Screen::adjustGameCanvasRect()
|
||||
{
|
||||
game_canvas_rect_ = {
|
||||
game_texture_rect_ = {
|
||||
options.video.border.enabled ? options.video.border.width : 0,
|
||||
options.video.border.enabled ? options.video.border.height : 0,
|
||||
options.game.width,
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#include <SDL2/SDL_stdinc.h> // for Uint32
|
||||
#include <SDL2/SDL_video.h> // for SDL_Window
|
||||
#include <vector> // for vector
|
||||
#include <memory> // for shared_ptr
|
||||
#include "utils.h" // for Color
|
||||
#include "surface.h"
|
||||
|
||||
// Tipos de filtro
|
||||
enum class ScreenFilter : Uint32
|
||||
@@ -27,13 +29,15 @@ private:
|
||||
// Objetos y punteros
|
||||
SDL_Window *window_; // Ventana de la aplicación
|
||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||
SDL_Texture *game_canvas_; // Textura donde se dibuja el juego
|
||||
SDL_Texture *border_canvas_; // Textura donde se dibuja el borde del juego
|
||||
SDL_Texture *surface_texture_; // Textura donde se dibuja el juego
|
||||
SDL_Texture *game_texture_; // Textura donde se dibuja el juego
|
||||
SDL_Texture *border_texture_; // Textura donde se dibuja el borde del juego
|
||||
std::shared_ptr<Surface> surface_; // Objeto para trabajar con surfaces
|
||||
|
||||
// Variables
|
||||
int window_width_; // Ancho de la pantalla o ventana
|
||||
int window_height_; // Alto de la pantalla o ventana
|
||||
SDL_Rect game_canvas_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
|
||||
SDL_Rect game_texture_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
|
||||
Color border_color_; // Color del borde añadido a la textura de juego para rellenar la pantalla
|
||||
|
||||
// Dibuja las notificaciones
|
||||
@@ -131,4 +135,7 @@ public:
|
||||
|
||||
// Getters
|
||||
SDL_Renderer *getRenderer() { return renderer_; }
|
||||
std::shared_ptr<SurfaceData> getGameSurface() { return surface_->getSurface(); }
|
||||
SDL_Texture *getGameTexture() { return game_texture_; };
|
||||
SDL_Texture *getBorderTexture() { return border_texture_; }
|
||||
};
|
||||
230
source/surface.cpp
Normal file
230
source/surface.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#include "surface.h"
|
||||
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_ARGB8888
|
||||
#include <SDL2/SDL_rect.h> // Para SDL_Rect
|
||||
#include <fstream> // Para std::ifstream
|
||||
#include <iostream> // Para std::cerr
|
||||
#include <vector> // Para std::vector
|
||||
#include <stdexcept> // For exceptions
|
||||
#include "gif.h" // Para LoadGif, LoadPalette
|
||||
#include <memory> // Para std::shared_ptr
|
||||
#include <algorithm> // Para std::copy
|
||||
#include "asset.h"
|
||||
|
||||
Surface::Surface(std::shared_ptr<SurfaceData> surface_dest, int w, int h)
|
||||
: surface_dest_(surface_dest),
|
||||
surface_(std::make_shared<SurfaceData>(w, h)),
|
||||
transparent_color_(0) {}
|
||||
|
||||
Surface::Surface(std::shared_ptr<SurfaceData> surface_dest, std::string file_path)
|
||||
: surface_dest_(surface_dest),
|
||||
surface_(std::make_shared<SurfaceData>(loadSurface(Asset::get()->get(file_path)))),
|
||||
transparent_color_(0) {}
|
||||
|
||||
Surface::~Surface() {}
|
||||
|
||||
// Carga una superficie desde un archivo
|
||||
SurfaceData Surface::loadSurface(const std::string &file_path)
|
||||
{
|
||||
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
|
||||
|
||||
if (!file.is_open())
|
||||
{
|
||||
std::cerr << "Error opening file: " << file_path << std::endl;
|
||||
throw std::runtime_error("Error opening file");
|
||||
}
|
||||
|
||||
std::streamsize size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<Uint8> buffer(size);
|
||||
if (!file.read((char *)buffer.data(), size))
|
||||
{
|
||||
std::cerr << "Error reading file: " << file_path << std::endl;
|
||||
throw std::runtime_error("Error reading file");
|
||||
}
|
||||
|
||||
Uint16 w, h;
|
||||
Uint8 *pixels = LoadGif(buffer.data(), &w, &h);
|
||||
if (pixels == nullptr)
|
||||
{
|
||||
std::cerr << "Error loading GIF from file: " << file_path << std::endl;
|
||||
throw std::runtime_error("Error loading GIF");
|
||||
}
|
||||
|
||||
// Crear y devolver directamente el objeto SurfaceData
|
||||
return SurfaceData(w, h, pixels);
|
||||
}
|
||||
|
||||
// Carga una paleta desde un archivo
|
||||
void Surface::loadPalette(const std::string &file_path)
|
||||
{
|
||||
// Abrir el archivo en modo binario
|
||||
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
|
||||
if (!file.is_open())
|
||||
{
|
||||
throw std::runtime_error("Error opening file: " + file_path);
|
||||
}
|
||||
|
||||
// Leer el contenido del archivo en un buffer
|
||||
std::streamsize size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<Uint8> buffer(size);
|
||||
if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
|
||||
{
|
||||
throw std::runtime_error("Error reading file: " + file_path);
|
||||
}
|
||||
|
||||
// Cargar la paleta usando los datos del buffer
|
||||
std::unique_ptr<Uint32[]> pal(LoadPalette(buffer.data()));
|
||||
if (pal == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Error loading palette from file: " + file_path);
|
||||
}
|
||||
|
||||
// Copiar los datos de la paleta al std::array
|
||||
std::copy(pal.get(), pal.get() + palette_.size(), palette_.begin());
|
||||
}
|
||||
|
||||
// Establece un color en la paleta
|
||||
void Surface::setColor(int index, Uint32 color)
|
||||
{
|
||||
palette_.at(index) = color;
|
||||
}
|
||||
|
||||
// Limpia la superficie de destino con un color
|
||||
void Surface::clear(std::shared_ptr<SurfaceData> surface, Uint8 color)
|
||||
{
|
||||
const size_t total_pixels = surface->width * surface->height;
|
||||
std::fill(surface->data, surface->data + total_pixels, color);
|
||||
}
|
||||
|
||||
// Pone un pixel en la superficie de destino
|
||||
void Surface::putPixel(int x, int y, Uint8 color)
|
||||
{
|
||||
if (color == transparent_color_)
|
||||
{
|
||||
return; // Color transparente, no dibujar
|
||||
}
|
||||
|
||||
if (x < 0 || y < 0 || x >= surface_dest_->width || y >= surface_dest_->height)
|
||||
{
|
||||
return; // Coordenadas fuera de rango
|
||||
}
|
||||
|
||||
const int index = x + y * surface_dest_->width;
|
||||
surface_dest_->data[index] = color;
|
||||
}
|
||||
|
||||
// Obtiene el color de un pixel de la superficie de origen
|
||||
Uint8 Surface::getPixel(int x, int y)
|
||||
{
|
||||
return surface_->data[x + y * surface_->width];
|
||||
}
|
||||
|
||||
// Copia una región de la superficie de origen a la de destino
|
||||
void Surface::render(int dx, int dy, int sx, int sy, int w, int h)
|
||||
{
|
||||
// Limitar la región para evitar accesos fuera de rango
|
||||
w = std::min(w, surface_->width - sx);
|
||||
h = std::min(h, surface_->height - sy);
|
||||
w = std::min(w, surface_dest_->width - dx);
|
||||
h = std::min(h, surface_dest_->height - dy);
|
||||
|
||||
for (int iy = 0; iy < h; ++iy)
|
||||
{
|
||||
for (int ix = 0; ix < w; ++ix)
|
||||
{
|
||||
Uint8 color = surface_->data[(sx + ix) + (sy + iy) * surface_->width];
|
||||
if (color != transparent_color_) // Opcional: Ignorar píxeles transparentes
|
||||
{
|
||||
surface_dest_->data[(dx + ix) + (dy + iy) * surface_dest_->width] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Vuelca la superficie a una textura
|
||||
void Surface::flip(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
Uint32 *pixels;
|
||||
int pitch;
|
||||
SDL_LockTexture(texture, nullptr, (void **)&pixels, &pitch);
|
||||
for (int i = 0; i < surface_.width * surface_.height; ++i)
|
||||
{
|
||||
pixels[i] = palette_[surface_.data[i]];
|
||||
}
|
||||
SDL_UnlockTexture(texture);
|
||||
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
|
||||
}
|
||||
*/
|
||||
|
||||
// Vuelca la superficie a una textura
|
||||
void Surface::copyToTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
if (!renderer || !texture)
|
||||
{
|
||||
throw std::runtime_error("Renderer or texture is null.");
|
||||
}
|
||||
|
||||
if (surface_->width <= 0 || surface_->height <= 0 || !surface_->data)
|
||||
{
|
||||
throw std::runtime_error("Invalid surface dimensions or data.");
|
||||
}
|
||||
|
||||
Uint32 *pixels = nullptr;
|
||||
int pitch = 0;
|
||||
|
||||
// Bloquea la textura para modificar los píxeles directamente
|
||||
if (SDL_LockTexture(texture, nullptr, (void **)&pixels, &pitch) != 0)
|
||||
{
|
||||
throw std::runtime_error("Failed to lock texture: " + std::string(SDL_GetError()));
|
||||
}
|
||||
|
||||
// Convertir `pitch` de bytes a Uint32 (asegurando alineación correcta en hardware)
|
||||
int row_stride = pitch / sizeof(Uint32);
|
||||
|
||||
for (int y = 0; y < surface_->height; ++y)
|
||||
{
|
||||
for (int x = 0; x < surface_->width; ++x)
|
||||
{
|
||||
// Calcular la posición correcta en la textura teniendo en cuenta el stride
|
||||
int texture_index = y * row_stride + x;
|
||||
int surface_index = y * surface_->width + x;
|
||||
|
||||
pixels[texture_index] = palette_[surface_->data[surface_index]];
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockTexture(texture); // Desbloquea la textura
|
||||
|
||||
// Renderiza la textura en la pantalla completa
|
||||
if (SDL_RenderCopy(renderer, texture, nullptr, nullptr) != 0)
|
||||
{
|
||||
throw std::runtime_error("Failed to copy texture to renderer: " + std::string(SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
// Realiza un efecto de fundido en la paleta
|
||||
bool Surface::fadePalette()
|
||||
{
|
||||
// Verificar que el tamaño mínimo de palette_ sea adecuado
|
||||
static constexpr int palette_size = 19;
|
||||
if (sizeof(palette_) / sizeof(palette_[0]) < palette_size)
|
||||
{
|
||||
throw std::runtime_error("Palette size is insufficient for fadePalette operation.");
|
||||
}
|
||||
|
||||
// Desplazar colores (pares e impares)
|
||||
for (int i = 18; i > 1; --i)
|
||||
{
|
||||
palette_[i] = palette_[i - 2];
|
||||
}
|
||||
|
||||
// Ajustar el primer color
|
||||
palette_[1] = palette_[0];
|
||||
|
||||
// Devolver si el índice 15 coincide con el índice 0
|
||||
return palette_[15] == palette_[0];
|
||||
}
|
||||
108
source/surface.h
Normal file
108
source/surface.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_render.h> // Para SDL_Renderer
|
||||
#include <SDL2/SDL_stdinc.h> // Para Uint8, Uint32
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
struct SurfaceData
|
||||
{
|
||||
Uint8 *data;
|
||||
Uint16 width;
|
||||
Uint16 height;
|
||||
|
||||
// Constructor por defecto
|
||||
SurfaceData() : data(nullptr), width(0), height(0) {}
|
||||
|
||||
// Constructor que inicializa dimensiones y asigna memoria
|
||||
SurfaceData(Uint16 w, Uint16 h)
|
||||
: data(new Uint8[w * h]()), width(w), height(h) {}
|
||||
|
||||
// Constructor para inicializar directamente con datos
|
||||
SurfaceData(Uint16 w, Uint16 h, Uint8 *pixels)
|
||||
: data(pixels), width(w), height(h) {}
|
||||
|
||||
// Destructor para liberar memoria
|
||||
~SurfaceData() { delete[] data; }
|
||||
|
||||
// Evita copias accidentales (opcional para mayor seguridad)
|
||||
SurfaceData(const SurfaceData &) = delete;
|
||||
SurfaceData &operator=(const SurfaceData &) = delete;
|
||||
|
||||
// Permite movimiento para evitar copias costosas
|
||||
SurfaceData(SurfaceData &&other) noexcept
|
||||
: data(other.data), width(other.width), height(other.height)
|
||||
{
|
||||
other.data = nullptr;
|
||||
other.width = 0;
|
||||
other.height = 0;
|
||||
}
|
||||
|
||||
SurfaceData &operator=(SurfaceData &&other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
delete[] data;
|
||||
|
||||
data = other.data;
|
||||
width = other.width;
|
||||
height = other.height;
|
||||
|
||||
other.data = nullptr;
|
||||
other.width = 0;
|
||||
other.height = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class Surface
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<SurfaceData> surface_dest_;
|
||||
std::shared_ptr<SurfaceData> surface_;
|
||||
std::array<Uint32, 256> palette_;
|
||||
int transparent_color_;
|
||||
|
||||
// Pone un pixel en la superficie de destino
|
||||
void putPixel(int x, int y, Uint8 color);
|
||||
|
||||
// Obtiene el color de un pixel de la superficie de origen
|
||||
Uint8 getPixel(int x, int y);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Surface(std::shared_ptr<SurfaceData> surface_dest, int w, int h);
|
||||
Surface(std::shared_ptr<SurfaceData> surface_dest, std::string file_path);
|
||||
|
||||
// Destructor
|
||||
~Surface();
|
||||
|
||||
// Carga una superficie desde un archivo
|
||||
SurfaceData loadSurface(const std::string &file_path);
|
||||
|
||||
// Carga una paleta desde un archivo
|
||||
void loadPalette(const std::string &file_path);
|
||||
|
||||
// Copia una región de la superficie de origen a la de destino
|
||||
void render(int dx, int dy, int sx, int sy, int w, int h);
|
||||
|
||||
// Establece un color en la paleta
|
||||
void setColor(int index, Uint32 color);
|
||||
|
||||
// Limpia la superficie de destino con un color
|
||||
void clear(std::shared_ptr<SurfaceData> surface, Uint8 color);
|
||||
|
||||
// Vuelca la superficie a una textura
|
||||
void copyToTexture(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||
|
||||
// Realiza un efecto de fundido en la paleta
|
||||
bool fadePalette();
|
||||
|
||||
// Getters
|
||||
std::shared_ptr<SurfaceData> getSurface() const { return surface_; }
|
||||
// std::shared_ptr<SurfaceData> getSurfaceDest() const { return surface_dest_; }
|
||||
// std::array<Uint32, 256> getPalette() const { return palette_; }
|
||||
int getTransparentColor() const { return transparent_color_; }
|
||||
};
|
||||
@@ -11,7 +11,7 @@
|
||||
struct Color;
|
||||
|
||||
// Definiciones de tipos
|
||||
struct Surface
|
||||
/*struct Surface
|
||||
{
|
||||
std::shared_ptr<Uint8[]> data;
|
||||
Uint16 w, h;
|
||||
@@ -19,7 +19,7 @@ struct Surface
|
||||
// Constructor
|
||||
Surface(Uint16 width, Uint16 height, std::shared_ptr<Uint8[]> pixels)
|
||||
: data(pixels), w(width), h(height) {}
|
||||
};
|
||||
};*/
|
||||
|
||||
class Texture
|
||||
{
|
||||
@@ -27,7 +27,7 @@ private:
|
||||
// Objetos y punteros
|
||||
SDL_Renderer *renderer_; // Renderizador donde dibujar la textura
|
||||
SDL_Texture *texture_ = nullptr; // La textura
|
||||
std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imagenes en formato gif con paleta
|
||||
//std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imagenes en formato gif con paleta
|
||||
|
||||
// Variables
|
||||
std::string path_; // Ruta de la imagen de la textura
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
|
||||
#include "texture.h" // for Texture
|
||||
#include "utils.h" // for Color, stringToColor, Palette
|
||||
#include "paleta.h"
|
||||
|
||||
// Constructor
|
||||
Title::Title()
|
||||
|
||||
Reference in New Issue
Block a user