canviat Options de struct a namespace

This commit is contained in:
2025-10-26 14:01:08 +01:00
parent 8f49e442de
commit df4965a84b
59 changed files with 1470 additions and 1533 deletions

View File

@@ -5,19 +5,19 @@
#include <string> // Para allocator, operator+, char_traits, string #include <string> // Para allocator, operator+, char_traits, string
#include <vector> // Para vector #include <vector> // Para vector
#include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT #include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
#include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo, Section #include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/screen.hpp" // Para Screen #include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo, Section
#include "game/ui/notifier.hpp" // Para Notifier, NotificationText #include "game/ui/notifier.hpp" // Para Notifier, NotificationText
#include "utils/utils.hpp" // Para stringInVector #include "utils/utils.hpp" // Para stringInVector
namespace globalInputs { namespace globalInputs {
void quit() { void quit() {
const std::string code = options.section.section == Section::GAME ? "PRESS AGAIN TO RETURN TO MENU" : "PRESS AGAIN TO EXIT"; const std::string code = Options::section.section == Options::Scene::GAME ? "PRESS AGAIN TO RETURN TO MENU" : "PRESS AGAIN TO EXIT";
auto code_found = stringInVector(Notifier::get()->getCodes(), code); auto code_found = stringInVector(Notifier::get()->getCodes(), code);
if (code_found) { if (code_found) {
// Si la notificación de salir está activa, cambia de sección // Si la notificación de salir está activa, cambia de sección
options.section.section = options.section.section == Section::GAME ? Section::TITLE : Section::QUIT; Options::section.section = Options::section.section == Options::Scene::GAME ? Options::Scene::TITLE : Options::Scene::QUIT;
} else { } else {
// Si la notificación de salir no está activa, muestra la notificación // Si la notificación de salir no está activa, muestra la notificación
Notifier::get()->show({code}, NotificationText::CENTER, 2000, -1, true, code); Notifier::get()->show({code}, NotificationText::CENTER, 2000, -1, true, code);
@@ -26,16 +26,16 @@ void quit() {
// Cambia de seccion // Cambia de seccion
void skip_section() { void skip_section() {
switch (options.section.section) { switch (Options::section.section) {
case Section::LOGO: case Options::Scene::LOGO:
case Section::LOADING_SCREEN: case Options::Scene::LOADING_SCREEN:
case Section::CREDITS: case Options::Scene::CREDITS:
case Section::DEMO: case Options::Scene::DEMO:
case Section::GAME_OVER: case Options::Scene::GAME_OVER:
case Section::ENDING: case Options::Scene::ENDING:
case Section::ENDING2: case Options::Scene::ENDING2:
options.section.section = Section::TITLE; Options::section.section = Options::Scene::TITLE;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
break; break;
default: default:
@@ -55,45 +55,45 @@ void check() {
else if (Input::get()->checkInput(InputAction::TOGGLE_BORDER, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::TOGGLE_BORDER, INPUT_DO_NOT_ALLOW_REPEAT)) {
Screen::get()->toggleBorder(); Screen::get()->toggleBorder();
Notifier::get()->show({"BORDER " + std::string(options.video.border.enabled ? "ENABLED" : "DISABLED")}, NotificationText::CENTER); Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
} }
else if (Input::get()->checkInput(InputAction::TOGGLE_VIDEOMODE, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::TOGGLE_VIDEOMODE, INPUT_DO_NOT_ALLOW_REPEAT)) {
Screen::get()->toggleVideoMode(); Screen::get()->toggleVideoMode();
Notifier::get()->show({"FULLSCREEN " + std::string(options.video.fullscreen == 0 ? "DISABLED" : "ENABLED")}, NotificationText::CENTER); Notifier::get()->show({"FULLSCREEN " + std::string(Options::video.fullscreen == 0 ? "DISABLED" : "ENABLED")}, NotificationText::CENTER);
} }
else if (Input::get()->checkInput(InputAction::WINDOW_DEC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::WINDOW_DEC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT)) {
if (Screen::get()->decWindowZoom()) { if (Screen::get()->decWindowZoom()) {
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(options.window.zoom)}, NotificationText::CENTER); Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}, NotificationText::CENTER);
} }
} }
else if (Input::get()->checkInput(InputAction::WINDOW_INC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::WINDOW_INC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT)) {
if (Screen::get()->incWindowZoom()) { if (Screen::get()->incWindowZoom()) {
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(options.window.zoom)}, NotificationText::CENTER); Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}, NotificationText::CENTER);
} }
} }
else if (Input::get()->checkInput(InputAction::TOGGLE_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::TOGGLE_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT)) {
Screen::get()->toggleShaders(); Screen::get()->toggleShaders();
Notifier::get()->show({"SHADERS " + std::string(options.video.shaders ? "ENABLED" : "DISABLED")}, NotificationText::CENTER); Notifier::get()->show({"SHADERS " + std::string(Options::video.shaders ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
} }
else if (Input::get()->checkInput(InputAction::NEXT_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::NEXT_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT)) {
Screen::get()->nextPalette(); Screen::get()->nextPalette();
Notifier::get()->show({"PALETTE " + options.video.palette}, NotificationText::CENTER); Notifier::get()->show({"PALETTE " + Options::video.palette}, NotificationText::CENTER);
} }
else if (Input::get()->checkInput(InputAction::PREVIOUS_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::PREVIOUS_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT)) {
Screen::get()->previousPalette(); Screen::get()->previousPalette();
Notifier::get()->show({"PALETTE " + options.video.palette}, NotificationText::CENTER); Notifier::get()->show({"PALETTE " + Options::video.palette}, NotificationText::CENTER);
} }
else if (Input::get()->checkInput(InputAction::TOGGLE_INTEGER_SCALE, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::TOGGLE_INTEGER_SCALE, INPUT_DO_NOT_ALLOW_REPEAT)) {
Screen::get()->toggleIntegerScale(); Screen::get()->toggleIntegerScale();
Screen::get()->setVideoMode(options.video.fullscreen); Screen::get()->setVideoMode(Options::video.fullscreen);
Notifier::get()->show({"INTEGER SCALE " + std::string(options.video.integer_scale ? "ENABLED" : "DISABLED")}, NotificationText::CENTER); Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
} }
else if (Input::get()->checkInput(InputAction::SHOW_DEBUG_INFO, INPUT_DO_NOT_ALLOW_REPEAT)) { else if (Input::get()->checkInput(InputAction::SHOW_DEBUG_INFO, INPUT_DO_NOT_ALLOW_REPEAT)) {

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
namespace globalInputs namespace globalInputs {
{ // Comprueba los inputs que se pueden introducir en cualquier sección del juego
// Comprueba los inputs que se pueden introducir en cualquier sección del juego void check();
void check(); } // namespace globalInputs
}

View File

@@ -1,6 +1,6 @@
#include "core/input/input.hpp" #include "core/input/input.hpp"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <algorithm> // Para find #include <algorithm> // Para find
#include <iostream> // Para basic_ostream, operator<<, cout, endl #include <iostream> // Para basic_ostream, operator<<, cout, endl
@@ -119,7 +119,7 @@ bool Input::checkInput(InputAction input, bool repeat, InputDeviceToUse device,
// Comprueba si hay almenos un input activo // Comprueba si hay almenos un input activo
bool Input::checkAnyInput(InputDeviceToUse device, int controller_index) { bool Input::checkAnyInput(InputDeviceToUse device, int controller_index) {
if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY) { if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY) {
const bool *key_states = SDL_GetKeyboardState(nullptr); const bool* key_states = SDL_GetKeyboardState(nullptr);
for (int i = 0; i < (int)key_bindings_.size(); ++i) { for (int i = 0; i < (int)key_bindings_.size(); ++i) {
if (key_states[key_bindings_[i].scancode] != 0 && !key_bindings_[i].active) { if (key_states[key_bindings_[i].scancode] != 0 && !key_bindings_[i].active) {
@@ -213,7 +213,6 @@ bool Input::discoverGameControllers() {
return found; return found;
} }
// Comprueba si hay algun mando conectado // Comprueba si hay algun mando conectado
bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; } bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; }

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <string> // Para string, basic_string #include <string> // Para string, basic_string
#include <vector> // Para vector #include <vector> // Para vector
@@ -62,8 +62,8 @@ class Input {
struct ControllerBindings { struct ControllerBindings {
SDL_GamepadButton button; // GameControllerButton asociado SDL_GamepadButton button; // GameControllerButton asociado
bool active; // Indica si está activo bool active; // Indica si está activo
bool axis_active; // Estado del eje bool axis_active; // Estado del eje
// Constructor // Constructor
explicit ControllerBindings(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool act = false, bool axis_act = false) explicit ControllerBindings(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool act = false, bool axis_act = false)
@@ -73,7 +73,7 @@ class Input {
}; };
// Variables // Variables
std::vector<SDL_Gamepad*> connected_controllers_; // Vector con todos los mandos conectados std::vector<SDL_Gamepad*> connected_controllers_; // Vector con todos los mandos conectados
std::vector<SDL_Joystick*> joysticks_; // Vector con todos los joysticks conectados std::vector<SDL_Joystick*> joysticks_; // Vector con todos los joysticks conectados
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociadas a los inputs predefinidos para cada mando std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociadas a los inputs predefinidos para cada mando

View File

@@ -1,6 +1,5 @@
#include "core/input/mouse.hpp" #include "core/input/mouse.hpp"
namespace Mouse { namespace Mouse {
Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor
Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
namespace Mouse { namespace Mouse {
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor

View File

@@ -1,316 +1,275 @@
#include "core/rendering/gif.hpp" #include "core/rendering/gif.hpp"
#include <iostream> // Para std::cout
#include <cstring> // Para memcpy, size_t
#include <stdexcept> // Para runtime_error
#include <string> // Para allocator, char_traits, operator==, basic_string
namespace GIF #include <cstring> // Para memcpy, size_t
{ #include <iostream> // Para std::cout
#include <stdexcept> // Para runtime_error
#include <string> // Para allocator, char_traits, operator==, basic_string
// Función inline para reemplazar el macro READ. namespace GIF {
// Actualiza el puntero 'buffer' tras copiar 'size' bytes a 'dst'.
inline void readBytes(const uint8_t *&buffer, void *dst, size_t size) // Función inline para reemplazar el macro READ.
{ // Actualiza el puntero 'buffer' tras copiar 'size' bytes a 'dst'.
std::memcpy(dst, buffer, size); inline void readBytes(const uint8_t*& buffer, void* dst, size_t size) {
buffer += size; std::memcpy(dst, buffer, size);
buffer += size;
}
void Gif::decompress(int code_length, const uint8_t* input, int input_length, uint8_t* out) {
// Verifica que el code_length tenga un rango razonable.
if (code_length < 2 || code_length > 12) {
throw std::runtime_error("Invalid LZW code length");
} }
void Gif::decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out) int i, bit;
{ int prev = -1;
// Verifica que el code_length tenga un rango razonable. std::vector<DictionaryEntry> dictionary;
if (code_length < 2 || code_length > 12) int dictionary_ind;
{ unsigned int mask = 0x01;
throw std::runtime_error("Invalid LZW code length"); int reset_code_length = code_length;
int clear_code = 1 << code_length;
int stop_code = clear_code + 1;
int match_len = 0;
// Inicializamos el diccionario con el tamaño correspondiente.
dictionary.resize(1 << (code_length + 1));
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
dictionary[dictionary_ind].prev = -1;
dictionary[dictionary_ind].len = 1;
}
dictionary_ind += 2; // Reservamos espacio para clear y stop codes
// Bucle principal: procesar el stream comprimido.
while (input_length > 0) {
int code = 0;
// Lee (code_length + 1) bits para formar el código.
for (i = 0; i < (code_length + 1); i++) {
if (input_length <= 0) {
throw std::runtime_error("Unexpected end of input in decompress");
}
bit = ((*input & mask) != 0) ? 1 : 0;
mask <<= 1;
if (mask == 0x100) {
mask = 0x01;
input++;
input_length--;
}
code |= (bit << i);
} }
int i, bit; if (code == clear_code) {
int prev = -1; // Reinicia el diccionario.
std::vector<DictionaryEntry> dictionary; code_length = reset_code_length;
int dictionary_ind; dictionary.resize(1 << (code_length + 1));
unsigned int mask = 0x01; for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
int reset_code_length = code_length; dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
int clear_code = 1 << code_length; dictionary[dictionary_ind].prev = -1;
int stop_code = clear_code + 1; dictionary[dictionary_ind].len = 1;
int match_len = 0; }
dictionary_ind += 2;
// Inicializamos el diccionario con el tamaño correspondiente. prev = -1;
dictionary.resize(1 << (code_length + 1)); continue;
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) } else if (code == stop_code) {
{ break;
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
dictionary[dictionary_ind].prev = -1;
dictionary[dictionary_ind].len = 1;
} }
dictionary_ind += 2; // Reservamos espacio para clear y stop codes
// Bucle principal: procesar el stream comprimido. if (prev > -1 && code_length < 12) {
while (input_length > 0) if (code > dictionary_ind) {
{ std::cerr << "code = " << std::hex << code
int code = 0; << ", but dictionary_ind = " << dictionary_ind << std::endl;
// Lee (code_length + 1) bits para formar el código. throw std::runtime_error("LZW error: code exceeds dictionary_ind.");
for (i = 0; i < (code_length + 1); i++)
{
if (input_length <= 0)
{
throw std::runtime_error("Unexpected end of input in decompress");
}
bit = ((*input & mask) != 0) ? 1 : 0;
mask <<= 1;
if (mask == 0x100)
{
mask = 0x01;
input++;
input_length--;
}
code |= (bit << i);
} }
if (code == clear_code) int ptr;
{ if (code == dictionary_ind) {
// Reinicia el diccionario. ptr = prev;
code_length = reset_code_length; while (dictionary[ptr].prev != -1)
ptr = dictionary[ptr].prev;
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
} else {
ptr = code;
while (dictionary[ptr].prev != -1)
ptr = dictionary[ptr].prev;
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
}
dictionary[dictionary_ind].prev = prev;
dictionary[dictionary_ind].len = dictionary[prev].len + 1;
dictionary_ind++;
if ((dictionary_ind == (1 << (code_length + 1))) && (code_length < 11)) {
code_length++;
dictionary.resize(1 << (code_length + 1)); dictionary.resize(1 << (code_length + 1));
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++)
{
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
dictionary[dictionary_ind].prev = -1;
dictionary[dictionary_ind].len = 1;
}
dictionary_ind += 2;
prev = -1;
continue;
} }
else if (code == stop_code)
{
break;
}
if (prev > -1 && code_length < 12)
{
if (code > dictionary_ind)
{
std::cerr << "code = " << std::hex << code
<< ", but dictionary_ind = " << dictionary_ind << std::endl;
throw std::runtime_error("LZW error: code exceeds dictionary_ind.");
}
int ptr;
if (code == dictionary_ind)
{
ptr = prev;
while (dictionary[ptr].prev != -1)
ptr = dictionary[ptr].prev;
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
}
else
{
ptr = code;
while (dictionary[ptr].prev != -1)
ptr = dictionary[ptr].prev;
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
}
dictionary[dictionary_ind].prev = prev;
dictionary[dictionary_ind].len = dictionary[prev].len + 1;
dictionary_ind++;
if ((dictionary_ind == (1 << (code_length + 1))) && (code_length < 11))
{
code_length++;
dictionary.resize(1 << (code_length + 1));
}
}
prev = code;
// Verifica que 'code' sea un índice válido antes de usarlo.
if (code < 0 || static_cast<size_t>(code) >= dictionary.size())
{
std::cerr << "Invalid LZW code " << code
<< ", dictionary size " << dictionary.size() << std::endl;
throw std::runtime_error("LZW error: invalid code encountered");
}
int curCode = code; // Variable temporal para recorrer la cadena.
match_len = dictionary[curCode].len;
while (curCode != -1)
{
// Se asume que dictionary[curCode].len > 0.
out[dictionary[curCode].len - 1] = dictionary[curCode].byte;
if (dictionary[curCode].prev == curCode)
{
std::cerr << "Internal error; self-reference detected." << std::endl;
throw std::runtime_error("Internal error in decompress: self-reference");
}
curCode = dictionary[curCode].prev;
}
out += match_len;
} }
}
std::vector<uint8_t> Gif::readSubBlocks(const uint8_t *&buffer) prev = code;
{
std::vector<uint8_t> data; // Verifica que 'code' sea un índice válido antes de usarlo.
uint8_t block_size = *buffer; if (code < 0 || static_cast<size_t>(code) >= dictionary.size()) {
std::cerr << "Invalid LZW code " << code
<< ", dictionary size " << dictionary.size() << std::endl;
throw std::runtime_error("LZW error: invalid code encountered");
}
int curCode = code; // Variable temporal para recorrer la cadena.
match_len = dictionary[curCode].len;
while (curCode != -1) {
// Se asume que dictionary[curCode].len > 0.
out[dictionary[curCode].len - 1] = dictionary[curCode].byte;
if (dictionary[curCode].prev == curCode) {
std::cerr << "Internal error; self-reference detected." << std::endl;
throw std::runtime_error("Internal error in decompress: self-reference");
}
curCode = dictionary[curCode].prev;
}
out += match_len;
}
}
std::vector<uint8_t> Gif::readSubBlocks(const uint8_t*& buffer) {
std::vector<uint8_t> data;
uint8_t block_size = *buffer;
buffer++;
while (block_size != 0) {
data.insert(data.end(), buffer, buffer + block_size);
buffer += block_size;
block_size = *buffer;
buffer++; buffer++;
while (block_size != 0) }
{ return data;
data.insert(data.end(), buffer, buffer + block_size); }
buffer += block_size;
block_size = *buffer; std::vector<uint8_t> Gif::processImageDescriptor(const uint8_t*& buffer, const std::vector<RGB>& gct, int resolution_bits) {
buffer++; ImageDescriptor image_descriptor;
// Lee 9 bytes para el image descriptor.
readBytes(buffer, &image_descriptor, sizeof(ImageDescriptor));
uint8_t lzw_code_size;
readBytes(buffer, &lzw_code_size, sizeof(uint8_t));
std::vector<uint8_t> compressed_data = readSubBlocks(buffer);
int uncompressed_data_length = image_descriptor.image_width * image_descriptor.image_height;
std::vector<uint8_t> uncompressed_data(uncompressed_data_length);
decompress(lzw_code_size, compressed_data.data(), static_cast<int>(compressed_data.size()), uncompressed_data.data());
return uncompressed_data;
}
std::vector<uint32_t> Gif::loadPalette(const uint8_t* buffer) {
uint8_t header[6];
std::memcpy(header, buffer, 6);
buffer += 6;
ScreenDescriptor screen_descriptor;
std::memcpy(&screen_descriptor, buffer, sizeof(ScreenDescriptor));
buffer += sizeof(ScreenDescriptor);
std::vector<uint32_t> global_color_table;
if (screen_descriptor.fields & 0x80) {
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
global_color_table.resize(global_color_table_size);
for (int i = 0; i < global_color_table_size; ++i) {
uint8_t r = buffer[0];
uint8_t g = buffer[1];
uint8_t b = buffer[2];
global_color_table[i] = (r << 16) | (g << 8) | b;
buffer += 3;
} }
return data; }
return global_color_table;
}
std::vector<uint8_t> Gif::processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h) {
// Leer la cabecera de 6 bytes ("GIF87a" o "GIF89a")
uint8_t header[6];
std::memcpy(header, buffer, 6);
buffer += 6;
// Opcional: Validar header
std::string headerStr(reinterpret_cast<char*>(header), 6);
if (headerStr != "GIF87a" && headerStr != "GIF89a") {
throw std::runtime_error("Formato de archivo GIF inválido.");
} }
std::vector<uint8_t> Gif::processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits) // Leer el Screen Descriptor (7 bytes, empaquetado sin padding)
{ ScreenDescriptor screen_descriptor;
ImageDescriptor image_descriptor; readBytes(buffer, &screen_descriptor, sizeof(ScreenDescriptor));
// Lee 9 bytes para el image descriptor.
readBytes(buffer, &image_descriptor, sizeof(ImageDescriptor));
uint8_t lzw_code_size; // Asigna ancho y alto
readBytes(buffer, &lzw_code_size, sizeof(uint8_t)); w = screen_descriptor.width;
h = screen_descriptor.height;
std::vector<uint8_t> compressed_data = readSubBlocks(buffer); int color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
int uncompressed_data_length = image_descriptor.image_width * image_descriptor.image_height; std::vector<RGB> global_color_table;
std::vector<uint8_t> uncompressed_data(uncompressed_data_length); if (screen_descriptor.fields & 0x80) {
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
decompress(lzw_code_size, compressed_data.data(), static_cast<int>(compressed_data.size()), uncompressed_data.data()); global_color_table.resize(global_color_table_size);
return uncompressed_data; std::memcpy(global_color_table.data(), buffer, 3 * global_color_table_size);
buffer += 3 * global_color_table_size;
} }
std::vector<uint32_t> Gif::loadPalette(const uint8_t *buffer) // Supongamos que 'buffer' es el puntero actual y TRAILER es 0x3B
{ uint8_t block_type = *buffer++;
uint8_t header[6]; while (block_type != TRAILER) {
std::memcpy(header, buffer, 6); if (block_type == EXTENSION_INTRODUCER) // 0x21
buffer += 6;
ScreenDescriptor screen_descriptor;
std::memcpy(&screen_descriptor, buffer, sizeof(ScreenDescriptor));
buffer += sizeof(ScreenDescriptor);
std::vector<uint32_t> global_color_table;
if (screen_descriptor.fields & 0x80)
{ {
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1)); // Se lee la etiqueta de extensión, la cual indica el tipo de extensión.
global_color_table.resize(global_color_table_size); uint8_t extension_label = *buffer++;
for (int i = 0; i < global_color_table_size; ++i) switch (extension_label) {
{ case GRAPHIC_CONTROL: // 0xF9
uint8_t r = buffer[0];
uint8_t g = buffer[1];
uint8_t b = buffer[2];
global_color_table[i] = (r << 16) | (g << 8) | b;
buffer += 3;
}
}
return global_color_table;
}
std::vector<uint8_t> Gif::processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h)
{
// Leer la cabecera de 6 bytes ("GIF87a" o "GIF89a")
uint8_t header[6];
std::memcpy(header, buffer, 6);
buffer += 6;
// Opcional: Validar header
std::string headerStr(reinterpret_cast<char *>(header), 6);
if (headerStr != "GIF87a" && headerStr != "GIF89a")
{
throw std::runtime_error("Formato de archivo GIF inválido.");
}
// Leer el Screen Descriptor (7 bytes, empaquetado sin padding)
ScreenDescriptor screen_descriptor;
readBytes(buffer, &screen_descriptor, sizeof(ScreenDescriptor));
// Asigna ancho y alto
w = screen_descriptor.width;
h = screen_descriptor.height;
int color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
std::vector<RGB> global_color_table;
if (screen_descriptor.fields & 0x80)
{
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
global_color_table.resize(global_color_table_size);
std::memcpy(global_color_table.data(), buffer, 3 * global_color_table_size);
buffer += 3 * global_color_table_size;
}
// Supongamos que 'buffer' es el puntero actual y TRAILER es 0x3B
uint8_t block_type = *buffer++;
while (block_type != TRAILER)
{
if (block_type == EXTENSION_INTRODUCER) // 0x21
{
// Se lee la etiqueta de extensión, la cual indica el tipo de extensión.
uint8_t extension_label = *buffer++;
switch (extension_label)
{
case GRAPHIC_CONTROL: // 0xF9
{ {
// Procesar Graphic Control Extension: // Procesar Graphic Control Extension:
uint8_t blockSize = *buffer++; // Normalmente, blockSize == 4 uint8_t blockSize = *buffer++; // Normalmente, blockSize == 4
buffer += blockSize; // Saltamos los 4 bytes del bloque fijo buffer += blockSize; // Saltamos los 4 bytes del bloque fijo
// Saltar los sub-bloques // Saltar los sub-bloques
uint8_t subBlockSize = *buffer++; uint8_t subBlockSize = *buffer++;
while (subBlockSize != 0) while (subBlockSize != 0) {
{
buffer += subBlockSize; buffer += subBlockSize;
subBlockSize = *buffer++; subBlockSize = *buffer++;
} }
break; break;
} }
case APPLICATION_EXTENSION: // 0xFF case APPLICATION_EXTENSION: // 0xFF
case COMMENT_EXTENSION: // 0xFE case COMMENT_EXTENSION: // 0xFE
case PLAINTEXT_EXTENSION: // 0x01 case PLAINTEXT_EXTENSION: // 0x01
{ {
// Para estas extensiones, saltamos el bloque fijo y los sub-bloques. // Para estas extensiones, saltamos el bloque fijo y los sub-bloques.
uint8_t blockSize = *buffer++; uint8_t blockSize = *buffer++;
buffer += blockSize; buffer += blockSize;
uint8_t subBlockSize = *buffer++; uint8_t subBlockSize = *buffer++;
while (subBlockSize != 0) while (subBlockSize != 0) {
{
buffer += subBlockSize; buffer += subBlockSize;
subBlockSize = *buffer++; subBlockSize = *buffer++;
} }
break; break;
} }
default: default: {
{
// Si la etiqueta de extensión es desconocida, saltarla también: // Si la etiqueta de extensión es desconocida, saltarla también:
uint8_t blockSize = *buffer++; uint8_t blockSize = *buffer++;
buffer += blockSize; buffer += blockSize;
uint8_t subBlockSize = *buffer++; uint8_t subBlockSize = *buffer++;
while (subBlockSize != 0) while (subBlockSize != 0) {
{
buffer += subBlockSize; buffer += subBlockSize;
subBlockSize = *buffer++; subBlockSize = *buffer++;
} }
break; break;
} }
}
} }
else if (block_type == IMAGE_DESCRIPTOR) } else if (block_type == IMAGE_DESCRIPTOR) {
{ // Procesar el Image Descriptor y retornar los datos de imagen
// Procesar el Image Descriptor y retornar los datos de imagen return processImageDescriptor(buffer, global_color_table, color_resolution_bits);
return processImageDescriptor(buffer, global_color_table, color_resolution_bits); } else {
} std::cerr << "Unrecognized block type " << std::hex << static_cast<int>(block_type) << std::endl;
else return std::vector<uint8_t>{};
{
std::cerr << "Unrecognized block type " << std::hex << static_cast<int>(block_type) << std::endl;
return std::vector<uint8_t>{};
}
block_type = *buffer++;
} }
block_type = *buffer++;
return std::vector<uint8_t>{};
} }
std::vector<uint8_t> Gif::loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h) return std::vector<uint8_t>{};
{ }
return processGifStream(buffer, w, h);
}
} // namespace GIF std::vector<uint8_t> Gif::loadGif(const uint8_t* buffer, uint16_t& w, uint16_t& h) {
return processGifStream(buffer, w, h);
}
} // namespace GIF

View File

@@ -1,102 +1,92 @@
#pragma once #pragma once
#include <cstdint> // Para uint8_t, uint16_t, uint32_t #include <cstdint> // Para uint8_t, uint16_t, uint32_t
#include <vector> // Para vector #include <vector> // Para vector
namespace GIF namespace GIF {
{
// Constantes definidas con constexpr, en lugar de macros // Constantes definidas con constexpr, en lugar de macros
constexpr uint8_t EXTENSION_INTRODUCER = 0x21; constexpr uint8_t EXTENSION_INTRODUCER = 0x21;
constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C; constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C;
constexpr uint8_t TRAILER = 0x3B; constexpr uint8_t TRAILER = 0x3B;
constexpr uint8_t GRAPHIC_CONTROL = 0xF9; constexpr uint8_t GRAPHIC_CONTROL = 0xF9;
constexpr uint8_t APPLICATION_EXTENSION = 0xFF; constexpr uint8_t APPLICATION_EXTENSION = 0xFF;
constexpr uint8_t COMMENT_EXTENSION = 0xFE; constexpr uint8_t COMMENT_EXTENSION = 0xFE;
constexpr uint8_t PLAINTEXT_EXTENSION = 0x01; constexpr uint8_t PLAINTEXT_EXTENSION = 0x01;
#pragma pack(push, 1) #pragma pack(push, 1)
struct ScreenDescriptor struct ScreenDescriptor {
{
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;
uint8_t fields; uint8_t fields;
uint8_t background_color_index; uint8_t background_color_index;
uint8_t pixel_aspect_ratio; uint8_t pixel_aspect_ratio;
}; };
struct RGB struct RGB {
{
uint8_t r, g, b; uint8_t r, g, b;
}; };
struct ImageDescriptor struct ImageDescriptor {
{
uint16_t image_left_position; uint16_t image_left_position;
uint16_t image_top_position; uint16_t image_top_position;
uint16_t image_width; uint16_t image_width;
uint16_t image_height; uint16_t image_height;
uint8_t fields; uint8_t fields;
}; };
#pragma pack(pop) #pragma pack(pop)
struct DictionaryEntry struct DictionaryEntry {
{
uint8_t byte; uint8_t byte;
int prev; int prev;
int len; int len;
}; };
struct Extension struct Extension {
{
uint8_t extension_code; uint8_t extension_code;
uint8_t block_size; uint8_t block_size;
}; };
struct GraphicControlExtension struct GraphicControlExtension {
{
uint8_t fields; uint8_t fields;
uint16_t delay_time; uint16_t delay_time;
uint8_t transparent_color_index; uint8_t transparent_color_index;
}; };
struct ApplicationExtension struct ApplicationExtension {
{
uint8_t application_id[8]; uint8_t application_id[8];
uint8_t version[3]; uint8_t version[3];
}; };
struct PlaintextExtension struct PlaintextExtension {
{
uint16_t left, top, width, height; uint16_t left, top, width, height;
uint8_t cell_width, cell_height; uint8_t cell_width, cell_height;
uint8_t foreground_color, background_color; uint8_t foreground_color, background_color;
}; };
class Gif class Gif {
{
public: public:
// Descompone (uncompress) el bloque comprimido usando LZW. // Descompone (uncompress) el bloque comprimido usando LZW.
// Este método puede lanzar std::runtime_error en caso de error. // Este método puede lanzar std::runtime_error en caso de error.
void decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out); void decompress(int code_length, const uint8_t* input, int input_length, uint8_t* out);
// Carga la paleta (global color table) a partir de un buffer, // Carga la paleta (global color table) a partir de un buffer,
// retornándola en un vector de uint32_t (cada color se compone de R, G, B). // retornándola en un vector de uint32_t (cada color se compone de R, G, B).
std::vector<uint32_t> loadPalette(const uint8_t *buffer); std::vector<uint32_t> loadPalette(const uint8_t* buffer);
// Carga el stream GIF; devuelve un vector con los datos de imagen sin comprimir y // Carga el stream GIF; devuelve un vector con los datos de imagen sin comprimir y
// asigna el ancho y alto mediante referencias. // asigna el ancho y alto mediante referencias.
std::vector<uint8_t> loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h); std::vector<uint8_t> loadGif(const uint8_t* buffer, uint16_t& w, uint16_t& h);
private: private:
// Lee los sub-bloques de datos y los acumula en un std::vector<uint8_t>. // Lee los sub-bloques de datos y los acumula en un std::vector<uint8_t>.
std::vector<uint8_t> readSubBlocks(const uint8_t *&buffer); std::vector<uint8_t> readSubBlocks(const uint8_t*& buffer);
// Procesa el Image Descriptor y retorna el vector de datos sin comprimir. // Procesa el Image Descriptor y retorna el vector de datos sin comprimir.
std::vector<uint8_t> processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits); std::vector<uint8_t> processImageDescriptor(const uint8_t*& buffer, const std::vector<RGB>& gct, int resolution_bits);
// Procesa el stream completo del GIF y devuelve los datos sin comprimir. // Procesa el stream completo del GIF y devuelve los datos sin comprimir.
std::vector<uint8_t> processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h); std::vector<uint8_t> processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h);
}; };
} // namespace GIF } // namespace GIF

View File

@@ -1,6 +1,7 @@
#include "core/rendering/opengl/opengl_shader.hpp" #include "core/rendering/opengl/opengl_shader.hpp"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
@@ -40,12 +41,12 @@ bool OpenGLShader::initGLExtensions() {
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"); glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv && return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram && glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog && glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
glUseProgram && glDeleteProgram && glGetUniformLocation && glUniform2f && glUseProgram && glDeleteProgram && glGetUniformLocation && glUniform2f &&
glGenVertexArrays && glBindVertexArray && glDeleteVertexArrays && glGenVertexArrays && glBindVertexArray && glDeleteVertexArrays &&
glGenBuffers && glBindBuffer && glBufferData && glDeleteBuffers && glGenBuffers && glBindBuffer && glBufferData && glDeleteBuffers &&
glVertexAttribPointer && glEnableVertexAttribArray; glVertexAttribPointer && glEnableVertexAttribArray;
} }
#endif #endif
@@ -53,14 +54,16 @@ void OpenGLShader::checkGLError(const char* operation) {
GLenum error = glGetError(); GLenum error = glGetError();
if (error != GL_NO_ERROR) { if (error != GL_NO_ERROR) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error OpenGL en %s: 0x%x", operation, error); "Error OpenGL en %s: 0x%x",
operation,
error);
} }
} }
GLuint OpenGLShader::compileShader(const std::string& source, GLenum shader_type) { GLuint OpenGLShader::compileShader(const std::string& source, GLenum shader_type) {
if (source.empty()) { if (source.empty()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"ERROR: El código fuente del shader está vacío"); "ERROR: El código fuente del shader está vacío");
return 0; return 0;
} }
@@ -83,14 +86,15 @@ GLuint OpenGLShader::compileShader(const std::string& source, GLenum shader_type
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled); glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled);
if (compiled != GL_TRUE) { if (compiled != GL_TRUE) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error en compilación del shader"); "Error en compilación del shader");
GLint log_length; GLint log_length;
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length); glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) { if (log_length > 0) {
std::vector<char> log(log_length); std::vector<char> log(log_length);
glGetShaderInfoLog(shader_id, log_length, &log_length, log.data()); glGetShaderInfoLog(shader_id, log_length, &log_length, log.data());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Log de compilación: %s", log.data()); "Log de compilación: %s",
log.data());
} }
glDeleteShader(shader_id); glDeleteShader(shader_id);
return 0; return 0;
@@ -103,7 +107,7 @@ GLuint OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) {
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
if (program == 0) { if (program == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al crear programa de shaders"); "Error al crear programa de shaders");
return 0; return 0;
} }
@@ -120,14 +124,15 @@ GLuint OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) {
glGetProgramiv(program, GL_LINK_STATUS, &linked); glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (linked != GL_TRUE) { if (linked != GL_TRUE) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al enlazar programa"); "Error al enlazar programa");
GLint log_length; GLint log_length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) { if (log_length > 0) {
std::vector<char> log(log_length); std::vector<char> log(log_length);
glGetProgramInfoLog(program, log_length, &log_length, log.data()); glGetProgramInfoLog(program, log_length, &log_length, log.data());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Log de enlace: %s", log.data()); "Log de enlace: %s",
log.data());
} }
glDeleteProgram(program); glDeleteProgram(program);
return 0; return 0;
@@ -144,16 +149,32 @@ void OpenGLShader::createQuadGeometry() {
// Formato: x, y, u, v // Formato: x, y, u, v
float vertices[] = { float vertices[] = {
// Posición // TexCoords // Posición // TexCoords
-1.0f, -1.0f, 0.0f, 0.0f, // Inferior izquierda -1.0f,
1.0f, -1.0f, 1.0f, 0.0f, // Inferior derecha -1.0f,
1.0f, 1.0f, 1.0f, 1.0f, // Superior derecha 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f // Superior izquierda 0.0f, // Inferior izquierda
1.0f,
-1.0f,
1.0f,
0.0f, // Inferior derecha
1.0f,
1.0f,
1.0f,
1.0f, // Superior derecha
-1.0f,
1.0f,
0.0f,
1.0f // Superior izquierda
}; };
// Índices para dibujar el quad con dos triángulos // Índices para dibujar el quad con dos triángulos
unsigned int indices[] = { unsigned int indices[] = {
0, 1, 2, // Primer triángulo 0,
2, 3, 0 // Segundo triángulo 1,
2, // Primer triángulo
2,
3,
0 // Segundo triángulo
}; };
// Generar y configurar VAO // Generar y configurar VAO
@@ -207,7 +228,7 @@ GLuint OpenGLShader::getTextureID(SDL_Texture* texture) {
if (texture_id == 0) { if (texture_id == 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"No se pudo obtener ID de textura OpenGL, usando 1 por defecto"); "No se pudo obtener ID de textura OpenGL, usando 1 por defecto");
texture_id = 1; texture_id = 1;
} }
@@ -215,16 +236,16 @@ GLuint OpenGLShader::getTextureID(SDL_Texture* texture) {
} }
bool OpenGLShader::init(SDL_Window* window, bool OpenGLShader::init(SDL_Window* window,
SDL_Texture* texture, SDL_Texture* texture,
const std::string& vertex_source, const std::string& vertex_source,
const std::string& fragment_source) { const std::string& fragment_source) {
window_ = window; window_ = window;
back_buffer_ = texture; back_buffer_ = texture;
renderer_ = SDL_GetRenderer(window); renderer_ = SDL_GetRenderer(window);
if (!renderer_) { if (!renderer_) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error: No se pudo obtener el renderer"); "Error: No se pudo obtener el renderer");
return false; return false;
} }
@@ -233,14 +254,18 @@ bool OpenGLShader::init(SDL_Window* window,
SDL_GetTextureSize(back_buffer_, &texture_width_, &texture_height_); SDL_GetTextureSize(back_buffer_, &texture_width_, &texture_height_);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Inicializando shaders: ventana=%dx%d, textura=%.0fx%.0f", "Inicializando shaders: ventana=%dx%d, textura=%.0fx%.0f",
window_width_, window_height_, texture_width_, texture_height_); window_width_,
window_height_,
texture_width_,
texture_height_);
// Verificar que es OpenGL // Verificar que es OpenGL
const char* renderer_name = SDL_GetRendererName(renderer_); const char* renderer_name = SDL_GetRendererName(renderer_);
if (!renderer_name || strncmp(renderer_name, "opengl", 6) != 0) { if (!renderer_name || strncmp(renderer_name, "opengl", 6) != 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Renderer no es OpenGL: %s", renderer_name ? renderer_name : "unknown"); "Renderer no es OpenGL: %s",
renderer_name ? renderer_name : "unknown");
return false; return false;
} }
@@ -248,7 +273,7 @@ bool OpenGLShader::init(SDL_Window* window,
// Inicializar extensiones OpenGL en Windows/Linux // Inicializar extensiones OpenGL en Windows/Linux
if (!initGLExtensions()) { if (!initGLExtensions()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al inicializar extensiones OpenGL"); "Error al inicializar extensiones OpenGL");
return false; return false;
} }
#endif #endif
@@ -265,7 +290,7 @@ bool OpenGLShader::init(SDL_Window* window,
if (vertex_shader == 0 || fragment_shader == 0) { if (vertex_shader == 0 || fragment_shader == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al compilar shaders"); "Error al compilar shaders");
if (vertex_shader != 0) glDeleteShader(vertex_shader); if (vertex_shader != 0) glDeleteShader(vertex_shader);
if (fragment_shader != 0) glDeleteShader(fragment_shader); if (fragment_shader != 0) glDeleteShader(fragment_shader);
return false; return false;
@@ -280,7 +305,7 @@ bool OpenGLShader::init(SDL_Window* window,
if (program_id_ == 0) { if (program_id_ == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al crear programa de shaders"); "Error al crear programa de shaders");
return false; return false;
} }
@@ -292,19 +317,20 @@ bool OpenGLShader::init(SDL_Window* window,
texture_size_location_ = glGetUniformLocation(program_id_, "TextureSize"); texture_size_location_ = glGetUniformLocation(program_id_, "TextureSize");
if (texture_size_location_ != -1) { if (texture_size_location_ != -1) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Configurando TextureSize uniform: %.0fx%.0f", "Configurando TextureSize uniform: %.0fx%.0f",
texture_width_, texture_height_); texture_width_,
texture_height_);
glUniform2f(texture_size_location_, texture_width_, texture_height_); glUniform2f(texture_size_location_, texture_width_, texture_height_);
checkGLError("glUniform2f(TextureSize)"); checkGLError("glUniform2f(TextureSize)");
} else { } else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Uniform 'TextureSize' no encontrado en shader"); "Uniform 'TextureSize' no encontrado en shader");
} }
glUseProgram(0); glUseProgram(0);
is_initialized_ = true; is_initialized_ = true;
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"** OpenGL 3.3 Shader Backend inicializado correctamente"); "** OpenGL 3.3 Shader Backend inicializado correctamente");
return true; return true;
} }
@@ -459,4 +485,4 @@ void OpenGLShader::cleanup() {
back_buffer_ = nullptr; back_buffer_ = nullptr;
} }
} // namespace Rendering } // namespace Rendering

View File

@@ -19,80 +19,80 @@ namespace Rendering {
* - Shaders GLSL #version 330 core * - Shaders GLSL #version 330 core
*/ */
class OpenGLShader : public ShaderBackend { class OpenGLShader : public ShaderBackend {
public: public:
OpenGLShader() = default; OpenGLShader() = default;
~OpenGLShader() override; ~OpenGLShader() override;
bool init(SDL_Window* window, bool init(SDL_Window* window,
SDL_Texture* texture, SDL_Texture* texture,
const std::string& vertex_source, const std::string& vertex_source,
const std::string& fragment_source) override; const std::string& fragment_source) override;
void render() override; void render() override;
void setTextureSize(float width, float height) override; void setTextureSize(float width, float height) override;
void cleanup() override; void cleanup() override;
bool isHardwareAccelerated() const override { return is_initialized_; } bool isHardwareAccelerated() const override { return is_initialized_; }
private: private:
// Funciones auxiliares // Funciones auxiliares
bool initGLExtensions(); bool initGLExtensions();
GLuint compileShader(const std::string& source, GLenum shader_type); GLuint compileShader(const std::string& source, GLenum shader_type);
GLuint linkProgram(GLuint vertex_shader, GLuint fragment_shader); GLuint linkProgram(GLuint vertex_shader, GLuint fragment_shader);
void createQuadGeometry(); void createQuadGeometry();
GLuint getTextureID(SDL_Texture* texture); GLuint getTextureID(SDL_Texture* texture);
void checkGLError(const char* operation); void checkGLError(const char* operation);
// Estado SDL // Estado SDL
SDL_Window* window_ = nullptr; SDL_Window* window_ = nullptr;
SDL_Renderer* renderer_ = nullptr; SDL_Renderer* renderer_ = nullptr;
SDL_Texture* back_buffer_ = nullptr; SDL_Texture* back_buffer_ = nullptr;
// Estado OpenGL // Estado OpenGL
GLuint program_id_ = 0; GLuint program_id_ = 0;
GLuint vao_ = 0; // Vertex Array Object GLuint vao_ = 0; // Vertex Array Object
GLuint vbo_ = 0; // Vertex Buffer Object GLuint vbo_ = 0; // Vertex Buffer Object
GLuint ebo_ = 0; // Element Buffer Object GLuint ebo_ = 0; // Element Buffer Object
// Ubicaciones de uniforms // Ubicaciones de uniforms
GLint texture_size_location_ = -1; GLint texture_size_location_ = -1;
// Tamaños // Tamaños
int window_width_ = 0; int window_width_ = 0;
int window_height_ = 0; int window_height_ = 0;
float texture_width_ = 0.0f; float texture_width_ = 0.0f;
float texture_height_ = 0.0f; float texture_height_ = 0.0f;
// Estado // Estado
bool is_initialized_ = false; bool is_initialized_ = false;
#ifndef __APPLE__ #ifndef __APPLE__
// Punteros a funciones OpenGL en Windows/Linux // Punteros a funciones OpenGL en Windows/Linux
PFNGLCREATESHADERPROC glCreateShader = nullptr; PFNGLCREATESHADERPROC glCreateShader = nullptr;
PFNGLSHADERSOURCEPROC glShaderSource = nullptr; PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
PFNGLCOMPILESHADERPROC glCompileShader = nullptr; PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
PFNGLGETSHADERIVPROC glGetShaderiv = nullptr; PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr; PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
PFNGLDELETESHADERPROC glDeleteShader = nullptr; PFNGLDELETESHADERPROC glDeleteShader = nullptr;
PFNGLATTACHSHADERPROC glAttachShader = nullptr; PFNGLATTACHSHADERPROC glAttachShader = nullptr;
PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr; PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
PFNGLLINKPROGRAMPROC glLinkProgram = nullptr; PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
PFNGLVALIDATEPROGRAMPROC glValidateProgram = nullptr; PFNGLVALIDATEPROGRAMPROC glValidateProgram = nullptr;
PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr; PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr; PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
PFNGLUSEPROGRAMPROC glUseProgram = nullptr; PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr; PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr; PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr;
PFNGLUNIFORM2FPROC glUniform2f = nullptr; PFNGLUNIFORM2FPROC glUniform2f = nullptr;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr; PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr; PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr;
PFNGLGENBUFFERSPROC glGenBuffers = nullptr; PFNGLGENBUFFERSPROC glGenBuffers = nullptr;
PFNGLBINDBUFFERPROC glBindBuffer = nullptr; PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
PFNGLBUFFERDATAPROC glBufferData = nullptr; PFNGLBUFFERDATAPROC glBufferData = nullptr;
PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr; PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr; PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr; PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
#endif #endif
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -9,13 +9,13 @@
#include <iterator> // Para istreambuf_iterator, operator== #include <iterator> // Para istreambuf_iterator, operator==
#include <string> // Para char_traits, string, operator+, operator== #include <string> // Para char_traits, string, operator+, operator==
#include "core/resources/asset.hpp" // Para Asset, AssetType #include "core/input/mouse.hpp" // Para updateCursorVisibility
#include "core/input/mouse.hpp" // Para updateCursorVisibility
#include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo, Border
#include "core/rendering/opengl/opengl_shader.hpp" // Para OpenGLShader #include "core/rendering/opengl/opengl_shader.hpp" // Para OpenGLShader
#include "core/resources/resource.hpp" // Para Resource #include "core/rendering/surface.hpp" // Para Surface, readPalFile
#include "core/rendering/surface.hpp" // Para Surface, readPalFile #include "core/rendering/text.hpp" // Para Text
#include "core/rendering/text.hpp" // Para Text #include "core/resources/asset.hpp" // Para Asset, AssetType
#include "core/resources/resource.hpp" // Para Resource
#include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo, Border
#include "game/ui/notifier.hpp" // Para Notifier #include "game/ui/notifier.hpp" // Para Notifier
// [SINGLETON] // [SINGLETON]
@@ -43,40 +43,40 @@ Screen::Screen()
initSDLVideo(); initSDLVideo();
// Ajusta los tamaños // Ajusta los tamaños
game_surface_dstrect_ = {options.video.border.width, options.video.border.height, options.game.width, options.game.height}; game_surface_dstrect_ = {Options::video.border.width, Options::video.border.height, Options::game.width, Options::game.height};
//adjustWindowSize(); // adjustWindowSize();
current_palette_ = findPalette(options.video.palette); current_palette_ = findPalette(Options::video.palette);
// Define el color del borde para el modo de pantalla completa // Define el color del borde para el modo de pantalla completa
border_color_ = static_cast<Uint8>(PaletteColor::BLACK); border_color_ = static_cast<Uint8>(PaletteColor::BLACK);
// Crea la textura donde se dibujan los graficos del juego // Crea la textura donde se dibujan los graficos del juego
game_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, options.game.width, options.game.height); game_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, Options::game.width, Options::game.height);
if (!game_texture_) { if (!game_texture_) {
// Registrar el error si está habilitado // Registrar el error si está habilitado
if (options.console) { if (Options::console) {
std::cerr << "Error: game_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl; std::cerr << "Error: game_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
} }
} }
SDL_SetTextureScaleMode(game_texture_, SDL_SCALEMODE_NEAREST); SDL_SetTextureScaleMode(game_texture_, SDL_SCALEMODE_NEAREST);
// Crea la textura donde se dibuja el borde que rodea el area de juego // Crea la textura donde se dibuja el borde que rodea el area de juego
border_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, options.game.width + options.video.border.width * 2, options.game.height + options.video.border.height * 2); border_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, Options::game.width + Options::video.border.width * 2, Options::game.height + Options::video.border.height * 2);
if (!border_texture_) { if (!border_texture_) {
// Registrar el error si está habilitado // Registrar el error si está habilitado
if (options.console) { if (Options::console) {
std::cerr << "Error: border_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl; std::cerr << "Error: border_texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
} }
} }
SDL_SetTextureScaleMode(border_texture_, SDL_SCALEMODE_NEAREST); SDL_SetTextureScaleMode(border_texture_, SDL_SCALEMODE_NEAREST);
// Crea la surface donde se dibujan los graficos del juego // Crea la surface donde se dibujan los graficos del juego
game_surface_ = std::make_shared<Surface>(options.game.width, options.game.height); game_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height);
game_surface_->setPalette(readPalFile(palettes_.at(current_palette_))); game_surface_->setPalette(readPalFile(palettes_.at(current_palette_)));
game_surface_->clear(static_cast<Uint8>(PaletteColor::BLACK)); game_surface_->clear(static_cast<Uint8>(PaletteColor::BLACK));
// Crea la surface para el borde de colores // Crea la surface para el borde de colores
border_surface_ = std::make_shared<Surface>(options.game.width + options.video.border.width * 2, options.game.height + options.video.border.height * 2); border_surface_ = std::make_shared<Surface>(Options::game.width + Options::video.border.width * 2, Options::game.height + Options::video.border.height * 2);
border_surface_->setPalette(readPalFile(palettes_.at(current_palette_))); border_surface_->setPalette(readPalFile(palettes_.at(current_palette_)));
border_surface_->clear(border_color_); border_surface_->clear(border_color_);
@@ -127,29 +127,29 @@ void Screen::render() {
// Establece el modo de video // Establece el modo de video
void Screen::setVideoMode(bool mode) { void Screen::setVideoMode(bool mode) {
// Actualiza las opciones // Actualiza las opciones
options.video.fullscreen = mode; Options::video.fullscreen = mode;
// Configura el modo de pantalla y ajusta la ventana // Configura el modo de pantalla y ajusta la ventana
SDL_SetWindowFullscreen(window_, options.video.fullscreen); SDL_SetWindowFullscreen(window_, Options::video.fullscreen);
adjustWindowSize(); adjustWindowSize();
adjustRenderLogicalSize(); adjustRenderLogicalSize();
} }
// Camibia entre pantalla completa y ventana // Camibia entre pantalla completa y ventana
void Screen::toggleVideoMode() { void Screen::toggleVideoMode() {
options.video.fullscreen = !options.video.fullscreen; Options::video.fullscreen = !Options::video.fullscreen;
setVideoMode(options.video.fullscreen); setVideoMode(Options::video.fullscreen);
} }
// Reduce el tamaño de la ventana // Reduce el tamaño de la ventana
bool Screen::decWindowZoom() { bool Screen::decWindowZoom() {
if (options.video.fullscreen == 0) { if (Options::video.fullscreen == 0) {
const int PREVIOUS_ZOOM = options.window.zoom; const int PREVIOUS_ZOOM = Options::window.zoom;
--options.window.zoom; --Options::window.zoom;
options.window.zoom = std::max(options.window.zoom, 1); Options::window.zoom = std::max(Options::window.zoom, 1);
if (options.window.zoom != PREVIOUS_ZOOM) { if (Options::window.zoom != PREVIOUS_ZOOM) {
setVideoMode(options.video.fullscreen); setVideoMode(Options::video.fullscreen);
return true; return true;
} }
} }
@@ -159,13 +159,13 @@ bool Screen::decWindowZoom() {
// Aumenta el tamaño de la ventana // Aumenta el tamaño de la ventana
bool Screen::incWindowZoom() { bool Screen::incWindowZoom() {
if (options.video.fullscreen == 0) { if (Options::video.fullscreen == 0) {
const int PREVIOUS_ZOOM = options.window.zoom; const int PREVIOUS_ZOOM = Options::window.zoom;
++options.window.zoom; ++Options::window.zoom;
options.window.zoom = std::min(options.window.zoom, options.window.max_zoom); Options::window.zoom = std::min(Options::window.zoom, Options::window.max_zoom);
if (options.window.zoom != PREVIOUS_ZOOM) { if (Options::window.zoom != PREVIOUS_ZOOM) {
setVideoMode(options.video.fullscreen); setVideoMode(Options::video.fullscreen);
return true; return true;
} }
} }
@@ -181,8 +181,8 @@ void Screen::setBorderColor(Uint8 color) {
// Cambia entre borde visible y no visible // Cambia entre borde visible y no visible
void Screen::toggleBorder() { void Screen::toggleBorder() {
options.video.border.enabled = !options.video.border.enabled; Options::video.border.enabled = !Options::video.border.enabled;
setVideoMode(options.video.fullscreen); setVideoMode(Options::video.fullscreen);
initShaders(); initShaders();
} }
@@ -195,7 +195,7 @@ void Screen::renderNotifications() {
// Cambia el estado de los shaders // Cambia el estado de los shaders
void Screen::toggleShaders() { void Screen::toggleShaders() {
options.video.shaders = !options.video.shaders; Options::video.shaders = !Options::video.shaders;
initShaders(); initShaders();
} }
@@ -208,28 +208,28 @@ void Screen::update() {
// Calcula el tamaño de la ventana // Calcula el tamaño de la ventana
void Screen::adjustWindowSize() { void Screen::adjustWindowSize() {
window_width_ = options.game.width + (options.video.border.enabled ? options.video.border.width * 2 : 0); window_width_ = Options::game.width + (Options::video.border.enabled ? Options::video.border.width * 2 : 0);
window_height_ = options.game.height + (options.video.border.enabled ? options.video.border.height * 2 : 0); window_height_ = Options::game.height + (Options::video.border.enabled ? Options::video.border.height * 2 : 0);
// Establece el nuevo tamaño // Establece el nuevo tamaño
if (options.video.fullscreen == 0) { if (Options::video.fullscreen == 0) {
int old_width, old_height; int old_width, old_height;
SDL_GetWindowSize(window_, &old_width, &old_height); SDL_GetWindowSize(window_, &old_width, &old_height);
int old_pos_x, old_pos_y; int old_pos_x, old_pos_y;
SDL_GetWindowPosition(window_, &old_pos_x, &old_pos_y); SDL_GetWindowPosition(window_, &old_pos_x, &old_pos_y);
const int NEW_POS_X = old_pos_x + (old_width - (window_width_ * options.window.zoom)) / 2; const int NEW_POS_X = old_pos_x + (old_width - (window_width_ * Options::window.zoom)) / 2;
const int NEW_POS_Y = old_pos_y + (old_height - (window_height_ * options.window.zoom)) / 2; const int NEW_POS_Y = old_pos_y + (old_height - (window_height_ * Options::window.zoom)) / 2;
SDL_SetWindowSize(window_, window_width_ * options.window.zoom, window_height_ * options.window.zoom); SDL_SetWindowSize(window_, window_width_ * Options::window.zoom, window_height_ * Options::window.zoom);
SDL_SetWindowPosition(window_, std::max(NEW_POS_X, WINDOWS_DECORATIONS), std::max(NEW_POS_Y, 0)); SDL_SetWindowPosition(window_, std::max(NEW_POS_X, WINDOWS_DECORATIONS), std::max(NEW_POS_Y, 0));
} }
} }
// Ajusta el tamaño lógico del renderizador // Ajusta el tamaño lógico del renderizador
void Screen::adjustRenderLogicalSize() { void Screen::adjustRenderLogicalSize() {
SDL_SetRenderLogicalPresentation(renderer_, window_width_, window_height_, options.video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX); SDL_SetRenderLogicalPresentation(renderer_, window_width_, window_height_, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
} }
// Establece el renderizador para las surfaces // Establece el renderizador para las surfaces
@@ -263,16 +263,16 @@ void Screen::setPalete() {
game_surface_->loadPalette(Resource::get()->getPalette(palettes_.at(current_palette_))); game_surface_->loadPalette(Resource::get()->getPalette(palettes_.at(current_palette_)));
border_surface_->loadPalette(Resource::get()->getPalette(palettes_.at(current_palette_))); border_surface_->loadPalette(Resource::get()->getPalette(palettes_.at(current_palette_)));
options.video.palette = palettes_.at(current_palette_); Options::video.palette = palettes_.at(current_palette_);
// Eliminar ".gif" // Eliminar ".gif"
size_t pos = options.video.palette.find(".pal"); size_t pos = Options::video.palette.find(".pal");
if (pos != std::string::npos) { if (pos != std::string::npos) {
options.video.palette.erase(pos, 4); Options::video.palette.erase(pos, 4);
} }
// Convertir a mayúsculas // Convertir a mayúsculas
std::transform(options.video.palette.begin(), options.video.palette.end(), options.video.palette.begin(), ::toupper); std::transform(Options::video.palette.begin(), Options::video.palette.end(), Options::video.palette.begin(), ::toupper);
} }
// Extrae los nombres de las paletas // Extrae los nombres de las paletas
@@ -284,7 +284,7 @@ void Screen::processPaletteList() {
// Copia la surface a la textura // Copia la surface a la textura
void Screen::surfaceToTexture() { void Screen::surfaceToTexture() {
if (options.video.border.enabled) { if (Options::video.border.enabled) {
border_surface_->copyToTexture(renderer_, border_texture_); border_surface_->copyToTexture(renderer_, border_texture_);
game_surface_->copyToTexture(renderer_, border_texture_, nullptr, &game_surface_dstrect_); game_surface_->copyToTexture(renderer_, border_texture_, nullptr, &game_surface_dstrect_);
} else { } else {
@@ -294,9 +294,9 @@ void Screen::surfaceToTexture() {
// Copia la textura al renderizador // Copia la textura al renderizador
void Screen::textureToRenderer() { void Screen::textureToRenderer() {
SDL_Texture* texture_to_render = options.video.border.enabled ? border_texture_ : game_texture_; SDL_Texture* texture_to_render = Options::video.border.enabled ? border_texture_ : game_texture_;
if (options.video.shaders && shader_backend_) { if (Options::video.shaders && shader_backend_) {
shader_backend_->render(); shader_backend_->render();
} else { } else {
SDL_SetRenderTarget(renderer_, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
@@ -333,7 +333,7 @@ void Screen::renderInfo() {
// FPS // FPS
const std::string FPS_TEXT = std::to_string(fps_.lastValue) + " FPS"; const std::string FPS_TEXT = std::to_string(fps_.lastValue) + " FPS";
text->writeColored(options.game.width - text->lenght(FPS_TEXT), 0, FPS_TEXT, color); text->writeColored(Options::game.width - text->lenght(FPS_TEXT), 0, FPS_TEXT, color);
// Resolution // Resolution
text->writeColored(0, 0, info_resolution_, color); text->writeColored(0, 0, info_resolution_, color);
@@ -344,13 +344,13 @@ void Screen::renderInfo() {
void Screen::clearSurface(Uint8 index) { game_surface_->clear(index); } void Screen::clearSurface(Uint8 index) { game_surface_->clear(index); }
// Establece el tamaño del borde // Establece el tamaño del borde
void Screen::setBorderWidth(int width) { options.video.border.width = width; } void Screen::setBorderWidth(int width) { Options::video.border.width = width; }
// Establece el tamaño del borde // Establece el tamaño del borde
void Screen::setBorderHeight(int height) { options.video.border.height = height; } void Screen::setBorderHeight(int height) { Options::video.border.height = height; }
// Establece si se ha de ver el borde en el modo ventana // Establece si se ha de ver el borde en el modo ventana
void Screen::setBorderEnabled(bool value) { options.video.border.enabled = value; } void Screen::setBorderEnabled(bool value) { Options::video.border.enabled = value; }
// Muestra la ventana // Muestra la ventana
void Screen::show() { SDL_ShowWindow(window_); } void Screen::show() { SDL_ShowWindow(window_); }
@@ -366,8 +366,8 @@ void Screen::toggleDebugInfo() { show_debug_info_ = !show_debug_info_; }
// Alterna entre activar y desactivar el escalado entero // Alterna entre activar y desactivar el escalado entero
void Screen::toggleIntegerScale() { void Screen::toggleIntegerScale() {
options.video.integer_scale = !options.video.integer_scale; Options::video.integer_scale = !Options::video.integer_scale;
SDL_SetRenderLogicalPresentation(renderer_, options.game.width, options.game.height, options.video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX); SDL_SetRenderLogicalPresentation(renderer_, Options::game.width, Options::game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
} }
// Getters // Getters
@@ -436,13 +436,13 @@ void Screen::loadShaders() {
// Inicializa los shaders // Inicializa los shaders
void Screen::initShaders() { void Screen::initShaders() {
#ifndef __APPLE__ #ifndef __APPLE__
if (options.video.shaders) { if (Options::video.shaders) {
loadShaders(); loadShaders();
if (!shader_backend_) { if (!shader_backend_) {
shader_backend_ = std::make_unique<Rendering::OpenGLShader>(); shader_backend_ = std::make_unique<Rendering::OpenGLShader>();
} }
shader_backend_->init(window_, options.video.border.enabled ? border_texture_ : game_texture_, vertex_shader_source_, fragment_shader_source_); shader_backend_->init(window_, Options::video.border.enabled ? border_texture_ : game_texture_, vertex_shader_source_, fragment_shader_source_);
//shader_backend_->init(window_, shaders_texture_, vertex_shader_source_, fragment_shader_source_); // shader_backend_->init(window_, shaders_texture_, vertex_shader_source_, fragment_shader_source_);
} }
#else #else
// En macOS, OpenGL está deprecated y rinde mal // En macOS, OpenGL está deprecated y rinde mal
@@ -475,23 +475,23 @@ void Screen::getDisplayInfo() {
display_monitor_.refresh_rate = static_cast<int>(dm->refresh_rate); display_monitor_.refresh_rate = static_cast<int>(dm->refresh_rate);
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla // Calcula el máximo factor de zoom que se puede aplicar a la pantalla
options.window.max_zoom = std::min(dm->w / options.game.width, dm->h / options.game.height); Options::window.max_zoom = std::min(dm->w / Options::game.width, dm->h / Options::game.height);
options.window.zoom = std::min(options.window.zoom, options.window.max_zoom); Options::window.zoom = std::min(Options::window.zoom, Options::window.max_zoom);
// Muestra información sobre el tamaño de la pantalla y de la ventana de juego // Muestra información sobre el tamaño de la pantalla y de la ventana de juego
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Current display mode: %dx%d @ %dHz", static_cast<int>(dm->w), static_cast<int>(dm->h), static_cast<int>(dm->refresh_rate)); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Current display mode: %dx%d @ %dHz", static_cast<int>(dm->w), static_cast<int>(dm->h), static_cast<int>(dm->refresh_rate));
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Window resolution: %dx%d x%d", static_cast<int>(options.game.width), static_cast<int>(options.game.height), options.window.zoom); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Window resolution: %dx%d x%d", static_cast<int>(Options::game.width), static_cast<int>(Options::game.height), Options::window.zoom);
options.video.info = std::to_string(static_cast<int>(dm->w)) + "x" + Options::video.info = std::to_string(static_cast<int>(dm->w)) + "x" +
std::to_string(static_cast<int>(dm->h)) + " @ " + std::to_string(static_cast<int>(dm->h)) + " @ " +
std::to_string(static_cast<int>(dm->refresh_rate)) + " Hz"; std::to_string(static_cast<int>(dm->refresh_rate)) + " Hz";
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla // Calcula el máximo factor de zoom que se puede aplicar a la pantalla
const int MAX_ZOOM = std::min(dm->w / options.game.width, (dm->h - WINDOWS_DECORATIONS) / options.game.height); const int MAX_ZOOM = std::min(dm->w / Options::game.width, (dm->h - WINDOWS_DECORATIONS) / Options::game.height);
// Normaliza los valores de zoom // Normaliza los valores de zoom
options.window.zoom = std::min(options.window.zoom, MAX_ZOOM); Options::window.zoom = std::min(Options::window.zoom, MAX_ZOOM);
SDL_free(displays); SDL_free(displays);
} }
@@ -536,17 +536,17 @@ auto Screen::initSDLVideo() -> bool {
#endif #endif
// Crear ventana // Crear ventana
const auto WINDOW_WIDTH = options.video.border.enabled ? options.game.width + options.video.border.width * 2 : options.game.width; const auto WINDOW_WIDTH = Options::video.border.enabled ? Options::game.width + Options::video.border.width * 2 : Options::game.width;
const auto WINDOW_HEIGHT = options.video.border.enabled ? options.game.height + options.video.border.height * 2 : options.game.height; const auto WINDOW_HEIGHT = Options::video.border.enabled ? Options::game.height + Options::video.border.height * 2 : Options::game.height;
#ifdef __APPLE__ #ifdef __APPLE__
SDL_WindowFlags window_flags = SDL_WINDOW_METAL; SDL_WindowFlags window_flags = SDL_WINDOW_METAL;
#else #else
SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL; SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL;
#endif #endif
if (options.video.fullscreen) { if (Options::video.fullscreen) {
window_flags |= SDL_WINDOW_FULLSCREEN; window_flags |= SDL_WINDOW_FULLSCREEN;
} }
window_ = SDL_CreateWindow(options.window.caption.c_str(), WINDOW_WIDTH * options.window.zoom, WINDOW_HEIGHT * options.window.zoom, window_flags); window_ = SDL_CreateWindow(Options::window.caption.c_str(), WINDOW_WIDTH * Options::window.zoom, WINDOW_HEIGHT * Options::window.zoom, window_flags);
if (window_ == nullptr) { if (window_ == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
@@ -569,16 +569,16 @@ auto Screen::initSDLVideo() -> bool {
} }
// Configurar renderer // Configurar renderer
const int EXTRA_WIDTH = options.video.border.enabled ? options.video.border.width * 2 : 0; const int EXTRA_WIDTH = Options::video.border.enabled ? Options::video.border.width * 2 : 0;
const int EXTRA_HEIGHT = options.video.border.enabled ? options.video.border.height * 2 : 0; const int EXTRA_HEIGHT = Options::video.border.enabled ? Options::video.border.height * 2 : 0;
SDL_SetRenderLogicalPresentation( SDL_SetRenderLogicalPresentation(
renderer_, renderer_,
options.game.width + EXTRA_WIDTH, Options::game.width + EXTRA_WIDTH,
options.game.height + EXTRA_HEIGHT, Options::game.height + EXTRA_HEIGHT,
options.video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX); Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF); SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
SDL_SetRenderVSync(renderer_, options.video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED); SDL_SetRenderVSync(renderer_, Options::video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "** Video system initialized successfully"); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "** Video system initialized successfully");
return true; return true;

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <string> #include <string>
namespace Rendering { namespace Rendering {
@@ -12,44 +13,44 @@ namespace Rendering {
* deben cumplir (OpenGL, Metal, Vulkan, etc.) * deben cumplir (OpenGL, Metal, Vulkan, etc.)
*/ */
class ShaderBackend { class ShaderBackend {
public: public:
virtual ~ShaderBackend() = default; virtual ~ShaderBackend() = default;
/** /**
* @brief Inicializa el backend de shaders * @brief Inicializa el backend de shaders
* @param window Ventana SDL * @param window Ventana SDL
* @param texture Textura de backbuffer a la que aplicar shaders * @param texture Textura de backbuffer a la que aplicar shaders
* @param vertex_source Código fuente del vertex shader * @param vertex_source Código fuente del vertex shader
* @param fragment_source Código fuente del fragment shader * @param fragment_source Código fuente del fragment shader
* @return true si la inicialización fue exitosa * @return true si la inicialización fue exitosa
*/ */
virtual bool init(SDL_Window* window, virtual bool init(SDL_Window* window,
SDL_Texture* texture, SDL_Texture* texture,
const std::string& vertex_source, const std::string& vertex_source,
const std::string& fragment_source) = 0; const std::string& fragment_source) = 0;
/** /**
* @brief Renderiza la textura con los shaders aplicados * @brief Renderiza la textura con los shaders aplicados
*/ */
virtual void render() = 0; virtual void render() = 0;
/** /**
* @brief Establece el tamaño de la textura como parámetro del shader * @brief Establece el tamaño de la textura como parámetro del shader
* @param width Ancho de la textura * @param width Ancho de la textura
* @param height Alto de la textura * @param height Alto de la textura
*/ */
virtual void setTextureSize(float width, float height) = 0; virtual void setTextureSize(float width, float height) = 0;
/** /**
* @brief Limpia y libera recursos del backend * @brief Limpia y libera recursos del backend
*/ */
virtual void cleanup() = 0; virtual void cleanup() = 0;
/** /**
* @brief Verifica si el backend está usando aceleración por hardware * @brief Verifica si el backend está usando aceleración por hardware
* @return true si usa aceleración (OpenGL/Metal/Vulkan) * @return true si usa aceleración (OpenGL/Metal/Vulkan)
*/ */
virtual bool isHardwareAccelerated() const = 0; virtual bool isHardwareAccelerated() const = 0;
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -8,7 +8,7 @@
#include <stdexcept> // Para runtime_error #include <stdexcept> // Para runtime_error
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/surface.hpp" // Para Surface
#include "utils/utils.hpp" // Para printWithDots #include "utils/utils.hpp" // Para printWithDots
// Carga las animaciones en un vector(Animations) desde un fichero // Carga las animaciones en un vector(Animations) desde un fichero
Animations loadAnimationsFromFile(const std::string& file_path) { Animations loadAnimationsFromFile(const std::string& file_path) {

View File

@@ -7,7 +7,7 @@
#include <vector> // Para vector #include <vector> // Para vector
#include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite #include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite
class Surface; // lines 9-9 class Surface; // lines 9-9
struct AnimationData { struct AnimationData {
std::string name; // Nombre de la animacion std::string name; // Nombre de la animacion

View File

@@ -5,7 +5,7 @@
#include <memory> // Para shared_ptr #include <memory> // Para shared_ptr
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
class Surface; // lines 8-8 class Surface; // lines 8-8
// Clase SMovingSprite. Añade movimiento y flip al sprite // Clase SMovingSprite. Añade movimiento y flip al sprite
class SMovingSprite : public SSprite { class SMovingSprite : public SSprite {

View File

@@ -7,10 +7,10 @@
#include <iostream> // Para cerr #include <iostream> // Para cerr
#include <stdexcept> // Para runtime_error #include <stdexcept> // Para runtime_error
#include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface.hpp" // Para Surface
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface #include "utils/utils.hpp" // Para getFileName, stringToColor, printWithDots
#include "utils/utils.hpp" // Para getFileName, stringToColor, printWithDots
// Llena una estructuta TextFile desde un fichero // Llena una estructuta TextFile desde un fichero
std::shared_ptr<TextFile> loadTextFile(const std::string& file_path) { std::shared_ptr<TextFile> loadTextFile(const std::string& file_path) {

View File

@@ -6,7 +6,7 @@
#include <string> // Para string #include <string> // Para string
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
class Surface; // lines 8-8 class Surface; // lines 8-8
constexpr int TEXT_COLOR = 1; constexpr int TEXT_COLOR = 1;
constexpr int TEXT_SHADOW = 2; constexpr int TEXT_SHADOW = 2;

View File

@@ -1,7 +1,7 @@
#include "core/rendering/texture.hpp" #include "core/rendering/texture.hpp"
#include <SDL3/SDL.h>
#include <SDL3/SDL.h>
#include <iostream> // Para basic_ostream, operator<<, endl, cout #include <iostream> // Para basic_ostream, operator<<, endl, cout
#include <stdexcept> // Para runtime_error #include <stdexcept> // Para runtime_error
@@ -64,7 +64,7 @@ bool Texture::loadFromFile(const std::string& file_path) {
SDL_Texture* newTexture = nullptr; SDL_Texture* newTexture = nullptr;
// Carga la imagen desde una ruta específica // Carga la imagen desde una ruta específica
auto *loaded_surface = SDL_CreateSurfaceFrom(width, height, pixel_format, static_cast<void *>(data), pitch); auto* loaded_surface = SDL_CreateSurfaceFrom(width, height, pixel_format, static_cast<void*>(data), pitch);
if (loaded_surface == nullptr) { if (loaded_surface == nullptr) {
std::cout << "Unable to load image " << file_path << std::endl; std::cout << "Unable to load image " << file_path << std::endl;
} else { } else {

View File

@@ -14,8 +14,8 @@ class Texture {
// Variables // Variables
std::string path_; // Ruta de la imagen de la textura std::string path_; // Ruta de la imagen de la textura
float width_ = 0.0F; // Ancho de la imagen float width_ = 0.0F; // Ancho de la imagen
float height_ = 0.0F; // Alto de la imagen float height_ = 0.0F; // Alto de la imagen
std::vector<std::vector<Uint32>> palettes_; // Vector con las diferentes paletas std::vector<std::vector<Uint32>> palettes_; // Vector con las diferentes paletas
// Libera la memoria de la textura // Libera la memoria de la textura

View File

@@ -1,61 +1,52 @@
#include "core/resources/asset.hpp" #include "core/resources/asset.hpp"
#include <algorithm> // Para find_if, max
#include <fstream> // Para basic_ostream, operator<<, basic_ifstream, endl #include <algorithm> // Para find_if, max
#include <iostream> // Para cout #include <fstream> // Para basic_ostream, operator<<, basic_ifstream, endl
#include <string> // Para allocator, char_traits, string, operator+, oper... #include <iostream> // Para cout
#include "utils/utils.hpp" // Para getFileName, printWithDots #include <string> // Para allocator, char_traits, string, operator+, oper...
#include "utils/utils.hpp" // Para getFileName, printWithDots
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Asset *Asset::asset_ = nullptr; Asset* Asset::asset_ = nullptr;
// [SINGLETON] Crearemos el objeto asset con esta función estática // [SINGLETON] Crearemos el objeto asset con esta función estática
void Asset::init(const std::string &executable_path) void Asset::init(const std::string& executable_path) {
{
Asset::asset_ = new Asset(executable_path); Asset::asset_ = new Asset(executable_path);
} }
// [SINGLETON] Destruiremos el objeto asset con esta función estática // [SINGLETON] Destruiremos el objeto asset con esta función estática
void Asset::destroy() void Asset::destroy() {
{
delete Asset::asset_; delete Asset::asset_;
} }
// [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él
Asset *Asset::get() Asset* Asset::get() {
{
return Asset::asset_; return Asset::asset_;
} }
// Añade un elemento a la lista // Añade un elemento a la lista
void Asset::add(const std::string &file, AssetType type, bool required, bool absolute) void Asset::add(const std::string& file, AssetType type, bool required, bool absolute) {
{
file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required); file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required);
longest_name_ = std::max(longest_name_, static_cast<int>(file_list_.back().file.size())); longest_name_ = std::max(longest_name_, static_cast<int>(file_list_.back().file.size()));
} }
// Devuelve la ruta completa a un fichero a partir de una cadena // Devuelve la ruta completa a un fichero a partir de una cadena
std::string Asset::get(const std::string &text) const std::string Asset::get(const std::string& text) const {
{ auto it = std::find_if(file_list_.begin(), file_list_.end(), [&text](const auto& f) {
auto it = std::find_if(file_list_.begin(), file_list_.end(), return getFileName(f.file) == text;
[&text](const auto &f) });
{
return getFileName(f.file) == text;
});
if (it != file_list_.end()) if (it != file_list_.end()) {
{
return it->file; return it->file;
} } else {
else
{
std::cout << "Warning: file " << text << " not found" << std::endl; std::cout << "Warning: file " << text << " not found" << std::endl;
return ""; return "";
} }
} }
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
bool Asset::check() const bool Asset::check() const {
{
bool success = true; bool success = true;
std::cout << "\n** CHECKING FILES" << std::endl; std::cout << "\n** CHECKING FILES" << std::endl;
@@ -64,28 +55,22 @@ bool Asset::check() const
// std::cout << "Sample filepath: " << file_list_.back().file << std::endl; // std::cout << "Sample filepath: " << file_list_.back().file << std::endl;
// Comprueba la lista de ficheros clasificandolos por tipo // Comprueba la lista de ficheros clasificandolos por tipo
for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type) for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type) {
{
// Comprueba si hay ficheros de ese tipo // Comprueba si hay ficheros de ese tipo
bool any = false; bool any = false;
for (const auto &f : file_list_) for (const auto& f : file_list_) {
{ if (f.required && f.type == static_cast<AssetType>(type)) {
if (f.required && f.type == static_cast<AssetType>(type))
{
any = true; any = true;
} }
} }
// Si hay ficheros de ese tipo, comprueba si existen // Si hay ficheros de ese tipo, comprueba si existen
if (any) if (any) {
{
std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl; std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl;
for (const auto &f : file_list_) for (const auto& f : file_list_) {
{ if (f.required && f.type == static_cast<AssetType>(type)) {
if (f.required && f.type == static_cast<AssetType>(type))
{
success &= checkFile(f.file); success &= checkFile(f.file);
} }
} }
@@ -101,14 +86,12 @@ bool Asset::check() const
} }
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool Asset::checkFile(const std::string &path) const bool Asset::checkFile(const std::string& path) const {
{
std::ifstream file(path); std::ifstream file(path);
bool success = file.good(); bool success = file.good();
file.close(); file.close();
if (!success) if (!success) {
{
printWithDots("Checking file : ", getFileName(path), "[ ERROR ]"); printWithDots("Checking file : ", getFileName(path), "[ ERROR ]");
} }
@@ -116,61 +99,56 @@ bool Asset::checkFile(const std::string &path) const
} }
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
std::string Asset::getTypeName(AssetType type) const std::string Asset::getTypeName(AssetType type) const {
{ switch (type) {
switch (type) case AssetType::DATA:
{ return "DATA";
case AssetType::DATA: break;
return "DATA";
break;
case AssetType::BITMAP: case AssetType::BITMAP:
return "BITMAP"; return "BITMAP";
break; break;
case AssetType::ANIMATION: case AssetType::ANIMATION:
return "ANIMATION"; return "ANIMATION";
break; break;
case AssetType::MUSIC: case AssetType::MUSIC:
return "MUSIC"; return "MUSIC";
break; break;
case AssetType::SOUND: case AssetType::SOUND:
return "SOUND"; return "SOUND";
break; break;
case AssetType::FONT: case AssetType::FONT:
return "FONT"; return "FONT";
break; break;
case AssetType::ROOM: case AssetType::ROOM:
return "ROOM"; return "ROOM";
break; break;
case AssetType::TILEMAP: case AssetType::TILEMAP:
return "TILEMAP"; return "TILEMAP";
break; break;
case AssetType::PALETTE: case AssetType::PALETTE:
return "PALETTE"; return "PALETTE";
break; break;
default: default:
return "ERROR"; return "ERROR";
break; break;
} }
} }
// Devuelve la lista de recursos de un tipo // Devuelve la lista de recursos de un tipo
std::vector<std::string> Asset::getListByType(AssetType type) const std::vector<std::string> Asset::getListByType(AssetType type) const {
{
std::vector<std::string> list; std::vector<std::string> list;
for (auto f : file_list_) for (auto f : file_list_) {
{ if (f.type == type) {
if (f.type == type)
{
list.push_back(f.file); list.push_back(f.file);
} }
} }

View File

@@ -1,79 +1,79 @@
#pragma once #pragma once
#include <string> // para string, basic_string #include <string> // para string, basic_string
#include <vector> // para vector #include <vector> // para vector
#include "utils/utils.hpp" #include "utils/utils.hpp"
enum class AssetType : int enum class AssetType : int {
{ DATA,
DATA, BITMAP,
BITMAP, ANIMATION,
ANIMATION, MUSIC,
MUSIC, SOUND,
SOUND, FONT,
FONT, ROOM,
ROOM, TILEMAP,
TILEMAP, PALETTE,
PALETTE, MAX_ASSET_TYPE
MAX_ASSET_TYPE
}; };
// Clase Asset // Clase Asset
class Asset class Asset {
{ private:
private: // [SINGLETON] Objeto asset privado para Don Melitón
// [SINGLETON] Objeto asset privado para Don Melitón static Asset* asset_;
static Asset *asset_;
// Estructura para definir un item // Estructura para definir un item
struct AssetItem struct AssetItem {
{ std::string file; // Ruta del fichero desde la raíz del directorio
std::string file; // Ruta del fichero desde la raíz del directorio AssetType type; // Indica el tipo de recurso
AssetType type; // Indica el tipo de recurso bool required; // Indica si es un fichero que debe de existir
bool required; // Indica si es un fichero que debe de existir
// Constructor // Constructor
AssetItem(const std::string &filePath, AssetType assetType, bool isRequired) AssetItem(const std::string& filePath, AssetType assetType, bool isRequired)
: file(filePath), type(assetType), required(isRequired) {} : file(filePath),
}; type(assetType),
required(isRequired) {}
};
// Variables // Variables
int longest_name_ = 0; // Contiene la longitud del nombre de fichero mas largo int longest_name_ = 0; // Contiene la longitud del nombre de fichero mas largo
std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros
std::string executable_path_; // Ruta al ejecutable std::string executable_path_; // Ruta al ejecutable
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool checkFile(const std::string &path) const; bool checkFile(const std::string& path) const;
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
std::string getTypeName(AssetType type) const; std::string getTypeName(AssetType type) const;
// Constructor // Constructor
explicit Asset(const std::string &executable_path) explicit Asset(const std::string& executable_path)
: executable_path_(getPath(executable_path)) {} : executable_path_(getPath(executable_path)) {}
// Destructor // Destructor
~Asset() = default; ~Asset() = default;
public: public:
// [SINGLETON] Crearemos el objeto con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &executable_path); static void init(const std::string& executable_path);
// [SINGLETON] Destruiremos el objeto con esta función estática // [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy(); static void destroy();
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Asset *get(); static Asset* get();
// Añade un elemento a la lista // Añade un elemento a la lista
void add(const std::string &file, AssetType type, bool required = true, bool absolute = false); void add(const std::string& file, AssetType type, bool required = true, bool absolute = false);
// Devuelve la ruta completa a un fichero a partir de una cadena // Devuelve la ruta completa a un fichero a partir de una cadena
std::string get(const std::string &text) const; std::string get(const std::string& text) const;
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
bool check() const; bool check() const;
// Devuelve la lista de recursos de un tipo // Devuelve la lista de recursos de un tipo
std::vector<std::string> getListByType(AssetType type) const; std::vector<std::string> getListByType(AssetType type) const;
}; };

View File

@@ -7,15 +7,15 @@
#include <iostream> // Para basic_ostream, operator<<, endl, cout #include <iostream> // Para basic_ostream, operator<<, endl, cout
#include <stdexcept> // Para runtime_error #include <stdexcept> // Para runtime_error
#include "core/resources/asset.hpp" // Para AssetType, Asset #include "core/rendering/screen.hpp" // Para Screen
#include "external/jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_Loa... #include "core/rendering/text.hpp" // Para Text, loadTextFile
#include "game/gameplay/options.hpp" // Para Options, OptionsGame, options #include "core/resources/asset.hpp" // Para AssetType, Asset
#include "game/gameplay/room.hpp" // Para RoomData, loadRoomFile, loadRoomTileFile #include "external/jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_Loa...
#include "core/rendering/screen.hpp" // Para Screen #include "game/gameplay/options.hpp" // Para Options, OptionsGame, options
#include "core/rendering/text.hpp" // Para Text, loadTextFile #include "game/gameplay/room.hpp" // Para RoomData, loadRoomFile, loadRoomTileFile
#include "utils/utils.hpp" // Para getFileName, printWithDots, PaletteColor #include "utils/utils.hpp" // Para getFileName, printWithDots, PaletteColor
struct JA_Music_t; // lines 17-17 struct JA_Music_t; // lines 17-17
struct JA_Sound_t; // lines 18-18 struct JA_Sound_t; // lines 18-18
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Resource* Resource::resource_ = nullptr; Resource* Resource::resource_ = nullptr;
@@ -375,12 +375,12 @@ void Resource::renderProgress() {
constexpr float X_PADDING = 10; constexpr float X_PADDING = 10;
constexpr float Y_PADDING = 10; constexpr float Y_PADDING = 10;
constexpr float BAR_HEIGHT = 10; constexpr float BAR_HEIGHT = 10;
const float bar_position = options.game.height - BAR_HEIGHT - Y_PADDING; const float bar_position = Options::game.height - BAR_HEIGHT - Y_PADDING;
Screen::get()->start(); Screen::get()->start();
Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK)); Screen::get()->clearSurface(static_cast<Uint8>(PaletteColor::BLACK));
auto surface = Screen::get()->getRendererSurface(); auto surface = Screen::get()->getRendererSurface();
const float WIRED_BAR_WIDTH = options.game.width - (X_PADDING * 2); const float WIRED_BAR_WIDTH = Options::game.width - (X_PADDING * 2);
SDL_FRect rect_wired = {X_PADDING, bar_position, WIRED_BAR_WIDTH, X_PADDING}; SDL_FRect rect_wired = {X_PADDING, bar_position, WIRED_BAR_WIDTH, X_PADDING};
surface->drawRectBorder(&rect_wired, static_cast<Uint8>(PaletteColor::WHITE)); surface->drawRectBorder(&rect_wired, static_cast<Uint8>(PaletteColor::WHITE));

View File

@@ -4,12 +4,12 @@
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "game/gameplay/room.hpp" // Para room_t #include "core/rendering/surface.hpp" // Para Surface
#include "core/rendering/surface_animated_sprite.hpp" // Para AnimationsFileBuffer #include "core/rendering/surface_animated_sprite.hpp" // Para AnimationsFileBuffer
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text, TextFile
#include "core/rendering/text.hpp" // Para Text, TextFile #include "game/gameplay/room.hpp" // Para room_t
struct JA_Music_t; // lines 11-11 struct JA_Music_t; // lines 11-11
struct JA_Sound_t; // lines 12-12 struct JA_Sound_t; // lines 12-12
// Estructura para almacenar ficheros de sonido y su nombre // Estructura para almacenar ficheros de sonido y su nombre
struct ResourceSound { struct ResourceSound {

View File

@@ -3,9 +3,9 @@
#include <algorithm> // Para max #include <algorithm> // Para max
#include <memory> // Para __shared_ptr_access, shared_ptr #include <memory> // Para __shared_ptr_access, shared_ptr
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/text.hpp" // Para Text #include "core/rendering/text.hpp" // Para Text
#include "utils/utils.hpp" // Para Color #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para Color
// [SINGLETON] // [SINGLETON]
Debug* Debug::debug_ = nullptr; Debug* Debug::debug_ = nullptr;

View File

@@ -11,15 +11,14 @@
#include <memory> // Para make_unique, unique_ptr #include <memory> // Para make_unique, unique_ptr
#include <string> // Para operator+, allocator, char_traits #include <string> // Para operator+, allocator, char_traits
#include "core/resources/asset.hpp" // Para Asset, AssetType #include "core/input/input.hpp" // Para Input, InputAction
#include "game/gameplay/cheevos.hpp" // Para Cheevos #include "core/rendering/screen.hpp" // Para Screen
#include "core/system/debug.hpp" // Para Debug #include "core/resources/asset.hpp" // Para Asset, AssetType
#include "utils/defines.hpp" // Para WINDOW_CAPTION #include "core/resources/resource.hpp" // Para Resource
#include "external/jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV... #include "core/system/debug.hpp" // Para Debug
#include "core/input/input.hpp" // Para Input, InputAction #include "external/jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
#include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo #include "game/gameplay/cheevos.hpp" // Para Cheevos
#include "core/resources/resource.hpp" // Para Resource #include "game/gameplay/options.hpp" // Para Options, options, OptionsVideo
#include "core/rendering/screen.hpp" // Para Screen
#include "game/scenes/credits.hpp" // Para Credits #include "game/scenes/credits.hpp" // Para Credits
#include "game/scenes/ending.hpp" // Para Ending #include "game/scenes/ending.hpp" // Para Ending
#include "game/scenes/ending2.hpp" // Para Ending2 #include "game/scenes/ending2.hpp" // Para Ending2
@@ -28,7 +27,8 @@
#include "game/scenes/loading_screen.hpp" // Para LoadingScreen #include "game/scenes/loading_screen.hpp" // Para LoadingScreen
#include "game/scenes/logo.hpp" // Para Logo #include "game/scenes/logo.hpp" // Para Logo
#include "game/scenes/title.hpp" // Para Title #include "game/scenes/title.hpp" // Para Title
#include "game/ui/notifier.hpp" // Para Notifier #include "game/ui/notifier.hpp" // Para Notifier
#include "utils/defines.hpp" // Para WINDOW_CAPTION
#ifndef _WIN32 #ifndef _WIN32
#include <pwd.h> #include <pwd.h>
@@ -39,7 +39,7 @@ Director::Director(int argc, const char* argv[]) {
std::cout << "Game start" << std::endl; std::cout << "Game start" << std::endl;
// Crea e inicializa las opciones del programa // Crea e inicializa las opciones del programa
initOptions(); Options::init();
// Comprueba los parametros del programa // Comprueba los parametros del programa
executable_path_ = checkProgramArguments(argc, argv); executable_path_ = checkProgramArguments(argc, argv);
@@ -57,7 +57,7 @@ Director::Director(int argc, const char* argv[]) {
} }
// Carga las opciones desde un fichero // Carga las opciones desde un fichero
loadOptionsFromFile(Asset::get()->get("config.txt")); Options::loadFromFile(Asset::get()->get("config.txt"));
// Inicializa JailAudio // Inicializa JailAudio
initJailAudio(); initJailAudio();
@@ -76,7 +76,7 @@ Director::Director(int argc, const char* argv[]) {
Director::~Director() { Director::~Director() {
// Guarda las opciones a un fichero // Guarda las opciones a un fichero
saveOptionsToFile(Asset::get()->get("config.txt")); Options::saveToFile(Asset::get()->get("config.txt"));
// Destruye los singletones // Destruye los singletones
Cheevos::destroy(); Cheevos::destroy();
@@ -99,15 +99,15 @@ std::string Director::checkProgramArguments(int argc, const char* argv[]) {
std::string argument(argv[i]); std::string argument(argv[i]);
if (argument == "--console") { if (argument == "--console") {
options.console = true; Options::console = true;
} else if (argument == "--infiniteLives") { } else if (argument == "--infiniteLives") {
options.cheats.infinite_lives = Cheat::CheatState::ENABLED; Options::cheats.infinite_lives = Options::Cheat::State::ENABLED;
} else if (argument == "--invincible") { } else if (argument == "--invincible") {
options.cheats.invincible = Cheat::CheatState::ENABLED; Options::cheats.invincible = Options::Cheat::State::ENABLED;
} else if (argument == "--jailEnabled") { } else if (argument == "--jailEnabled") {
options.cheats.jail_is_open = Cheat::CheatState::ENABLED; Options::cheats.jail_is_open = Options::Cheat::State::ENABLED;
} else if (argument == "--altSkin") { } else if (argument == "--altSkin") {
options.cheats.alternate_skin = Cheat::CheatState::ENABLED; Options::cheats.alternate_skin = Options::Cheat::State::ENABLED;
} }
} }
@@ -175,19 +175,19 @@ void Director::initInput() {
Input::get()->discoverGameControllers(); Input::get()->discoverGameControllers();
// Teclado - Movimiento // Teclado - Movimiento
if (options.keys == ControlScheme::CURSOR) { if (Options::keys == Options::ControlScheme::CURSOR) {
Input::get()->bindKey(InputAction::JUMP, SDL_SCANCODE_UP); Input::get()->bindKey(InputAction::JUMP, SDL_SCANCODE_UP);
Input::get()->bindKey(InputAction::LEFT, SDL_SCANCODE_LEFT); Input::get()->bindKey(InputAction::LEFT, SDL_SCANCODE_LEFT);
Input::get()->bindKey(InputAction::RIGHT, SDL_SCANCODE_RIGHT); Input::get()->bindKey(InputAction::RIGHT, SDL_SCANCODE_RIGHT);
Input::get()->bindKey(InputAction::UP, SDL_SCANCODE_UP); Input::get()->bindKey(InputAction::UP, SDL_SCANCODE_UP);
Input::get()->bindKey(InputAction::DOWN, SDL_SCANCODE_DOWN); Input::get()->bindKey(InputAction::DOWN, SDL_SCANCODE_DOWN);
} else if (options.keys == ControlScheme::OPQA) { } else if (Options::keys == Options::ControlScheme::OPQA) {
Input::get()->bindKey(InputAction::JUMP, SDL_SCANCODE_Q); Input::get()->bindKey(InputAction::JUMP, SDL_SCANCODE_Q);
Input::get()->bindKey(InputAction::LEFT, SDL_SCANCODE_O); Input::get()->bindKey(InputAction::LEFT, SDL_SCANCODE_O);
Input::get()->bindKey(InputAction::RIGHT, SDL_SCANCODE_P); Input::get()->bindKey(InputAction::RIGHT, SDL_SCANCODE_P);
Input::get()->bindKey(InputAction::UP, SDL_SCANCODE_Q); Input::get()->bindKey(InputAction::UP, SDL_SCANCODE_Q);
Input::get()->bindKey(InputAction::DOWN, SDL_SCANCODE_A); Input::get()->bindKey(InputAction::DOWN, SDL_SCANCODE_A);
} else if (options.keys == ControlScheme::WASD) { } else if (Options::keys == Options::ControlScheme::WASD) {
Input::get()->bindKey(InputAction::JUMP, SDL_SCANCODE_W); Input::get()->bindKey(InputAction::JUMP, SDL_SCANCODE_W);
Input::get()->bindKey(InputAction::LEFT, SDL_SCANCODE_A); Input::get()->bindKey(InputAction::LEFT, SDL_SCANCODE_A);
Input::get()->bindKey(InputAction::RIGHT, SDL_SCANCODE_D); Input::get()->bindKey(InputAction::RIGHT, SDL_SCANCODE_D);
@@ -241,9 +241,9 @@ void Director::initJailAudio() {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError());
} else { } else {
JA_Init(48000, SDL_AUDIO_S16LE, 2); JA_Init(48000, SDL_AUDIO_S16LE, 2);
if (options.audio.enabled) { if (Options::audio.enabled) {
JA_SetMusicVolume(options.audio.music.volume); JA_SetMusicVolume(Options::audio.music.volume);
JA_SetSoundVolume(options.audio.sound.volume); JA_SetSoundVolume(Options::audio.sound.volume);
} else { } else {
JA_SetMusicVolume(0); JA_SetMusicVolume(0);
JA_SetSoundVolume(0); JA_SetSoundVolume(0);
@@ -542,41 +542,41 @@ void Director::runGame() {
int Director::run() { int Director::run() {
// Bucle principal // Bucle principal
while (options.section.section != Section::QUIT) { while (Options::section.section != Options::Scene::QUIT) {
switch (options.section.section) { switch (Options::section.section) {
case Section::LOGO: case Options::Scene::LOGO:
runLogo(); runLogo();
break; break;
case Section::LOADING_SCREEN: case Options::Scene::LOADING_SCREEN:
runLoadingScreen(); runLoadingScreen();
break; break;
case Section::TITLE: case Options::Scene::TITLE:
runTitle(); runTitle();
break; break;
case Section::CREDITS: case Options::Scene::CREDITS:
runCredits(); runCredits();
break; break;
case Section::DEMO: case Options::Scene::DEMO:
runDemo(); runDemo();
break; break;
case Section::GAME: case Options::Scene::GAME:
runGame(); runGame();
break; break;
case Section::GAME_OVER: case Options::Scene::GAME_OVER:
runGameOver(); runGameOver();
break; break;
case Section::ENDING: case Options::Scene::ENDING:
runEnding(); runEnding();
break; break;
case Section::ENDING2: case Options::Scene::ENDING2:
runEnding2(); runEnding2();
break; break;

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <string> // Para string #include <string> // Para string
@@ -19,7 +19,7 @@ class Director {
// Inicializa jail_audio // Inicializa jail_audio
void initJailAudio(); void initJailAudio();
// Inicializa el objeto Input // Inicializa el objeto Input
void initInput(); void initInput();
// Crea el indice de ficheros // Crea el indice de ficheros

View File

@@ -3,9 +3,9 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <stdlib.h> // Para rand #include <stdlib.h> // Para rand
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "utils/utils.hpp" // Para stringToColor #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para stringToColor
// Constructor // Constructor
Enemy::Enemy(const EnemyData& enemy) Enemy::Enemy(const EnemyData& enemy)

View File

@@ -1,7 +1,7 @@
#include "game/entities/item.hpp" #include "game/entities/item.hpp"
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/resources/resource.hpp" // Para Resource
// Constructor // Constructor
Item::Item(ItemData item) Item::Item(ItemData item)

View File

@@ -9,8 +9,8 @@ class SSprite;
struct ItemData { struct ItemData {
std::string tile_set_file; // Ruta al fichero con los gráficos del item std::string tile_set_file; // Ruta al fichero con los gráficos del item
float x; // Posición del item en pantalla float x; // Posición del item en pantalla
float y; // Posición del item en pantalla float y; // Posición del item en pantalla
int tile; // Número de tile dentro de la textura int tile; // Número de tile dentro de la textura
int counter; // Contador inicial. Es el que lo hace cambiar de color int counter; // Contador inicial. Es el que lo hace cambiar de color
Uint8 color1; // Uno de los dos colores que se utiliza para el item Uint8 color1; // Uno de los dos colores que se utiliza para el item

View File

@@ -4,14 +4,14 @@
#include <algorithm> // Para max, min #include <algorithm> // Para max, min
#include <cmath> // Para ceil, abs #include <cmath> // Para ceil, abs
#include "core/system/debug.hpp" // Para Debug #include "core/input/input.hpp" // Para Input, InputAction
#include "utils/defines.hpp" // Para RoomBorder::BOTTOM, RoomBorder::LEFT, RoomBorder::RIGHT
#include "external/jail_audio.h" // Para JA_PlaySound
#include "core/input/input.hpp" // Para Input, InputAction
#include "game/gameplay/options.hpp" // Para Cheat, Options, options
#include "core/resources/resource.hpp" // Para Resource
#include "game/gameplay/room.hpp" // Para Room, TileType
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "core/resources/resource.hpp" // Para Resource
#include "core/system/debug.hpp" // Para Debug
#include "external/jail_audio.h" // Para JA_PlaySound
#include "game/gameplay/options.hpp" // Para Cheat, Options, options
#include "game/gameplay/room.hpp" // Para Room, TileType
#include "utils/defines.hpp" // Para RoomBorder::BOTTOM, RoomBorder::LEFT, RoomBorder::RIGHT
// Constructor // Constructor
Player::Player(const PlayerData& player) Player::Player(const PlayerData& player)
@@ -218,8 +218,8 @@ void Player::applyGravity() {
// Recalcula la posición del jugador y su animación // Recalcula la posición del jugador y su animación
void Player::move() { void Player::move() {
last_position_ = {x_, y_}; // Guarda la posicion actual antes de modificarla last_position_ = {x_, y_}; // Guarda la posicion actual antes de modificarla
applyGravity(); // Aplica gravedad al jugador applyGravity(); // Aplica gravedad al jugador
checkState(); // Comprueba el estado del jugador checkState(); // Comprueba el estado del jugador
#ifdef DEBUG #ifdef DEBUG
debug_color_ = static_cast<Uint8>(PaletteColor::GREEN); debug_color_ = static_cast<Uint8>(PaletteColor::GREEN);
@@ -549,9 +549,9 @@ bool Player::checkKillingTiles() {
// Establece el color del jugador // Establece el color del jugador
void Player::setColor() { void Player::setColor() {
if (options.cheats.invincible == Cheat::CheatState::ENABLED) { if (Options::cheats.invincible == Options::Cheat::State::ENABLED) {
color_ = static_cast<Uint8>(PaletteColor::CYAN); color_ = static_cast<Uint8>(PaletteColor::CYAN);
} else if (options.cheats.infinite_lives == Cheat::CheatState::ENABLED) { } else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) {
color_ = static_cast<Uint8>(PaletteColor::YELLOW); color_ = static_cast<Uint8>(PaletteColor::YELLOW);
} else { } else {
color_ = static_cast<Uint8>(PaletteColor::WHITE); color_ = static_cast<Uint8>(PaletteColor::WHITE);

View File

@@ -6,11 +6,11 @@
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "utils/defines.hpp" // Para BORDER_TOP, BLOCK
#include "game/gameplay/room.hpp"
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "utils/utils.hpp" // Para Color #include "game/gameplay/room.hpp"
struct JA_Sound_t; // lines 13-13 #include "utils/defines.hpp" // Para BORDER_TOP, BLOCK
#include "utils/utils.hpp" // Para Color
struct JA_Sound_t; // lines 13-13
enum class PlayerState { enum class PlayerState {
STANDING, STANDING,

View File

@@ -6,8 +6,8 @@
#include <fstream> // Para basic_ostream, operator<<, basic_ofstream #include <fstream> // Para basic_ostream, operator<<, basic_ofstream
#include <iostream> // Para cout, cerr #include <iostream> // Para cout, cerr
#include "game/gameplay/options.hpp" // Para Options, options #include "game/gameplay/options.hpp" // Para Options, options
#include "game/ui/notifier.hpp" // Para Notifier #include "game/ui/notifier.hpp" // Para Notifier
// [SINGLETON] // [SINGLETON]
Cheevos* Cheevos::cheevos_ = nullptr; Cheevos* Cheevos::cheevos_ = nullptr;
@@ -102,7 +102,7 @@ void Cheevos::loadFromFile() {
// El fichero no existe // El fichero no existe
if (!file) { if (!file) {
if (options.console) { if (Options::console) {
std::cout << "Warning: Unable to open " << file_ << "! Creating new file..." << std::endl; std::cout << "Warning: Unable to open " << file_ << "! Creating new file..." << std::endl;
} }
@@ -110,7 +110,7 @@ void Cheevos::loadFromFile() {
std::ofstream newFile(file_, std::ios::binary); std::ofstream newFile(file_, std::ios::binary);
if (newFile) { if (newFile) {
if (options.console) { if (Options::console) {
std::cout << "New " << file_ << " created!" << std::endl; std::cout << "New " << file_ << " created!" << std::endl;
} }
@@ -119,14 +119,14 @@ void Cheevos::loadFromFile() {
newFile.write(reinterpret_cast<const char*>(&cheevo.completed), sizeof(bool)); newFile.write(reinterpret_cast<const char*>(&cheevo.completed), sizeof(bool));
} }
} else { } else {
if (options.console) { if (Options::console) {
std::cerr << "Error: Unable to create " << file_ << "!" << std::endl; std::cerr << "Error: Unable to create " << file_ << "!" << std::endl;
} }
} }
} }
// El fichero existe // El fichero existe
else { else {
if (options.console) { if (Options::console) {
std::cout << "Reading " << file_ << std::endl; std::cout << "Reading " << file_ << std::endl;
} }
@@ -150,7 +150,7 @@ void Cheevos::saveToFile() {
// Cierra el fichero // Cierra el fichero
SDL_CloseIO(file); SDL_CloseIO(file);
} else { } else {
if (options.console) { if (Options::console) {
std::cout << "Error: Unable to save file! " << SDL_GetError() << std::endl; std::cout << "Error: Unable to save file! " << SDL_GetError() << std::endl;
} }
} }

View File

@@ -1,83 +1,90 @@
#pragma once #pragma once
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
// Struct para los logros // Struct para los logros
struct Achievement struct Achievement {
{ int id; // Identificador del logro
int id; // Identificador del logro std::string caption; // Texto con el nombre del logro
std::string caption; // Texto con el nombre del logro std::string description; // Texto que describe el logro
std::string description; // Texto que describe el logro int icon; // Indice del icono a utilizar en la notificación
int icon; // Indice del icono a utilizar en la notificación bool completed; // Indica si se ha obtenido el logro
bool completed; // Indica si se ha obtenido el logro bool obtainable; // Indica si se puede obtener el logro
bool obtainable; // Indica si se puede obtener el logro
// Constructor vacío // Constructor vacío
Achievement() : id(0), icon(0), completed(false), obtainable(true) {} Achievement()
: id(0),
icon(0),
completed(false),
obtainable(true) {}
// Constructor parametrizado // Constructor parametrizado
Achievement(int id, const std::string &caption, const std::string &description, int icon, bool completed = false, bool obtainable = true) Achievement(int id, const std::string& caption, const std::string& description, int icon, bool completed = false, bool obtainable = true)
: id(id), caption(caption), description(description), icon(icon), completed(completed), obtainable(obtainable) {} : id(id),
caption(caption),
description(description),
icon(icon),
completed(completed),
obtainable(obtainable) {}
}; };
class Cheevos class Cheevos {
{ private:
private: // [SINGLETON] Objeto privado
// [SINGLETON] Objeto privado static Cheevos* cheevos_;
static Cheevos *cheevos_;
// Variables // Variables
std::vector<Achievement> cheevos_list_; // Listado de logros std::vector<Achievement> cheevos_list_; // Listado de logros
bool enabled_ = true; // Indica si los logros se pueden obtener bool enabled_ = true; // Indica si los logros se pueden obtener
std::string file_; // Fichero donde leer/almacenar el estado de los logros std::string file_; // Fichero donde leer/almacenar el estado de los logros
// Inicializa los logros // Inicializa los logros
void init(); void init();
// Busca un logro por id y devuelve el índice // Busca un logro por id y devuelve el índice
int find(int id); int find(int id);
// Carga el estado de los logros desde un fichero // Carga el estado de los logros desde un fichero
void loadFromFile(); void loadFromFile();
// Guarda el estado de los logros en un fichero // Guarda el estado de los logros en un fichero
void saveToFile(); void saveToFile();
// Constructor // Constructor
explicit Cheevos(const std::string &file); explicit Cheevos(const std::string& file);
// Destructor // Destructor
~Cheevos(); ~Cheevos();
public: public:
// [SINGLETON] Crearemos el objeto con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &file); static void init(const std::string& file);
// [SINGLETON] Destruiremos el objeto con esta función estática // [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy(); static void destroy();
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Cheevos *get(); static Cheevos* get();
// Desbloquea un logro // Desbloquea un logro
void unlock(int id); void unlock(int id);
// Invalida un logro // Invalida un logro
void setUnobtainable(int id); void setUnobtainable(int id);
// Elimina el estado "no obtenible" // Elimina el estado "no obtenible"
void clearUnobtainableState(); void clearUnobtainableState();
// Habilita o deshabilita los logros // Habilita o deshabilita los logros
void enable(bool value) { enabled_ = value; } void enable(bool value) { enabled_ = value; }
// Lista los logros // Lista los logros
const std::vector<Achievement>& list() const { return cheevos_list_; } const std::vector<Achievement>& list() const { return cheevos_list_; }
// Devuelve el número total de logros desbloqueados // Devuelve el número total de logros desbloqueados
int getTotalUnlockedAchievements(); int getTotalUnlockedAchievements();
// Devuelve el número total de logros // Devuelve el número total de logros
int size() { return cheevos_list_.size(); } int size() { return cheevos_list_.size(); }
}; };

View File

@@ -0,0 +1,85 @@
#pragma once
#include <SDL3/SDL.h>
#include "core/rendering/screen.hpp" // Para ScreenFilter
#include "utils/utils.hpp" // Para PaletteColor
// Forward declarations from Options namespace
namespace Options {
enum class Scene;
enum class SceneOptions;
enum class ControlScheme;
enum class NotificationPosition;
} // namespace Options
namespace GameDefaults {
// =============================================================================
// GAME
// =============================================================================
constexpr int GAME_WIDTH = 256; // Ancho de la ventana por defecto
constexpr int GAME_HEIGHT = 192; // Alto de la ventana por defecto
// =============================================================================
// WINDOW
// =============================================================================
constexpr int WINDOW_ZOOM = 2; // Zoom de la ventana por defecto
// =============================================================================
// VIDEO
// =============================================================================
constexpr bool VIDEO_MODE = false; // Modo de pantalla completa por defecto (false = ventana)
constexpr ScreenFilter VIDEO_FILTER = ScreenFilter::NEAREST; // Filtro por defecto
constexpr bool VIDEO_VERTICAL_SYNC = true; // Vsync activado por defecto
constexpr bool VIDEO_SHADERS = false; // Shaders desactivados por defecto
constexpr bool VIDEO_INTEGER_SCALE = true; // Escalado entero activado por defecto
constexpr bool VIDEO_KEEP_ASPECT = true; // Mantener aspecto activado por defecto
constexpr const char* PALETTE_NAME = "zx-spectrum"; // Paleta por defecto
// =============================================================================
// BORDER
// =============================================================================
constexpr bool BORDER_ENABLED = true; // Borde activado por defecto
constexpr int BORDER_WIDTH = 32; // Ancho del borde por defecto
constexpr int BORDER_HEIGHT = 24; // Alto del borde por defecto
// =============================================================================
// AUDIO
// =============================================================================
constexpr int AUDIO_VOLUME = 100; // Volumen por defecto
constexpr bool AUDIO_ENABLED = true; // Audio por defecto
// MUSIC
constexpr int MUSIC_VOLUME = 80; // Volumen por defecto de la musica
constexpr bool MUSIC_ENABLED = true; // Musica habilitada por defecto
// SOUND
constexpr int SOUND_VOLUME = 100; // Volumen por defecto de los efectos de sonido
constexpr bool SOUND_ENABLED = true; // Sonido habilitado por defecto
// =============================================================================
// NOTIFICATIONS
// =============================================================================
constexpr Options::NotificationPosition NOTIFICATION_POSITION = Options::NotificationPosition::UPPER_LEFT; // Posición de las notificaciones por defecto
constexpr bool NOTIFICATION_SOUND = true; // Sonido de las notificaciones por defecto
const Uint8 NOTIFICATION_COLOR = static_cast<Uint8>(PaletteColor::BLUE); // Color de las notificaciones por defecto
// =============================================================================
// SCENE
// =============================================================================
constexpr Options::Scene SCENE = Options::Scene::LOGO; // Sección por defecto
constexpr Options::SceneOptions SUBSECTION = Options::SceneOptions::LOGO_TO_INTRO; // Subsección por defecto
// =============================================================================
// CONTROL
// =============================================================================
constexpr Options::ControlScheme CONTROL_SCHEME = Options::ControlScheme::CURSOR; // Control por defecto
// =============================================================================
// OTHER
// =============================================================================
constexpr bool CONSOLE = false; // Consola desactivada por defecto
constexpr const char* VERSION = "1.10"; // Versión por defecto
} // namespace GameDefaults

View File

@@ -12,32 +12,44 @@
#include <unordered_map> // Para unordered_map, operator==, _Node_const_i... #include <unordered_map> // Para unordered_map, operator==, _Node_const_i...
#include <utility> // Para pair #include <utility> // Para pair
// Variables #include "utils/utils.hpp" // Para stringToBool, boolToString, safeStoi
Options options;
namespace Options {
// --- Variables globales ---
std::string version; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles
bool console; // Indica si ha de mostrar información por la consola de texto
Cheat cheats; // Contiene trucos y ventajas para el juego
Game game; // Opciones de juego
Video video; // Opciones de video
Stats stats; // Datos con las estadisticas de juego
Notification notifications; // Opciones relativas a las notificaciones;
Window window; // Opciones relativas a la ventana
Audio audio; // Opciones relativas al audio
ControlScheme keys; // Teclas usadas para jugar
SceneState section; // Sección actual del programa
bool setOptions(const std::string& var, const std::string& value); bool setOptions(const std::string& var, const std::string& value);
// Crea e inicializa las opciones del programa // Crea e inicializa las opciones del programa
void initOptions() { void init() {
options = Options();
#ifdef DEBUG #ifdef DEBUG
options.section = SectionState(Section::ENDING2, Subsection::LOGO_TO_INTRO); section = SceneState(Scene::ENDING2, SceneOptions::LOGO_TO_INTRO);
options.console = true; console = true;
#else #else
options.section = SectionState(Section::LOGO, Subsection::LOGO_TO_INTRO); section = SceneState(Scene::LOGO, SceneOptions::LOGO_TO_INTRO);
options.console = false; console = false;
#endif #endif
} }
// Carga las opciones desde un fichero // Carga las opciones desde un fichero
bool loadOptionsFromFile(const std::string& file_path) { bool loadFromFile(const std::string& file_path) {
// Indicador de éxito en la carga // Indicador de éxito en la carga
bool success = true; bool success = true;
// Versión actual del fichero // Versión actual del fichero
const std::string configVersion = options.version; const std::string configVersion = version;
options.version = ""; version = "";
// Variables para manejar el fichero // Variables para manejar el fichero
std::ifstream file(file_path); std::ifstream file(file_path);
@@ -45,7 +57,7 @@ bool loadOptionsFromFile(const std::string& file_path) {
// Si el fichero se puede abrir // Si el fichero se puede abrir
if (file.good()) { if (file.good()) {
// Procesa el fichero línea a línea // Procesa el fichero línea a línea
if (options.console) { if (console) {
std::cout << "Reading file config.txt\n"; std::cout << "Reading file config.txt\n";
} }
std::string line; std::string line;
@@ -68,7 +80,7 @@ bool loadOptionsFromFile(const std::string& file_path) {
if (iss >> key >> value) { if (iss >> key >> value) {
if (!setOptions(key, value)) { if (!setOptions(key, value)) {
if (options.console) { if (console) {
std::cout << "Warning: file config.txt\n"; std::cout << "Warning: file config.txt\n";
std::cout << "unknown parameter " << key << std::endl; std::cout << "unknown parameter " << key << std::endl;
} }
@@ -78,21 +90,21 @@ bool loadOptionsFromFile(const std::string& file_path) {
} }
// Cierra el fichero // Cierra el fichero
if (options.console) { if (console) {
std::cout << "Closing file config.txt\n\n"; std::cout << "Closing file config.txt\n\n";
} }
file.close(); file.close();
} else { } else {
// Crea el fichero con los valores por defecto // Crea el fichero con los valores por defecto
saveOptionsToFile(file_path); saveToFile(file_path);
} }
// Si la versión de fichero no coincide, crea un fichero nuevo con los valores por defecto // Si la versión de fichero no coincide, crea un fichero nuevo con los valores por defecto
if (configVersion != options.version) { if (configVersion != version) {
initOptions(); init();
saveOptionsToFile(file_path); saveToFile(file_path);
if (options.console) { if (console) {
std::cout << "Wrong config file: initializing options.\n\n"; std::cout << "Wrong config file: initializing \n\n";
} }
} }
@@ -100,56 +112,56 @@ bool loadOptionsFromFile(const std::string& file_path) {
} }
// Guarda las opciones en un fichero // Guarda las opciones en un fichero
bool saveOptionsToFile(const std::string& file_path) { bool saveToFile(const std::string& file_path) {
// Crea y abre el fichero de texto // Crea y abre el fichero de texto
std::ofstream file(file_path); std::ofstream file(file_path);
bool success = file.is_open(); // Verifica si el archivo se abrió correctamente bool success = file.is_open(); // Verifica si el archivo se abrió correctamente
if (!success) // Si no se pudo abrir el archivo, muestra un mensaje de error y devuelve false if (!success) // Si no se pudo abrir el archivo, muestra un mensaje de error y devuelve false
{ {
if (options.console) { if (console) {
std::cerr << "Error: Unable to open file " << file_path << " for writing." << std::endl; std::cerr << "Error: Unable to open file " << file_path << " for writing." << std::endl;
} }
return false; return false;
} }
if (options.console) { if (console) {
std::cout << file_path << " open for writing" << std::endl; std::cout << file_path << " open for writing" << std::endl;
} }
// Escribe en el fichero // Escribe en el fichero
file << "# Versión de la configuración\n"; file << "# Versión de la configuración\n";
file << "version " << options.version << "\n"; file << "version " << version << "\n";
file << "\n## CONTROL\n"; file << "\n## CONTROL\n";
file << "# Esquema de control: 0 = Cursores, 1 = OPQ, 2 = WAD\n"; file << "# Esquema de control: 0 = Cursores, 1 = OPQ, 2 = WAD\n";
file << "keys " << static_cast<int>(options.keys) << "\n"; file << "keys " << static_cast<int>(keys) << "\n";
file << "\n## WINDOW\n"; file << "\n## WINDOW\n";
file << "# Zoom de la ventana: 1 = Normal, 2 = Doble, 3 = Triple, ...\n"; file << "# Zoom de la ventana: 1 = Normal, 2 = Doble, 3 = Triple, ...\n";
file << "window.zoom " << options.window.zoom << "\n"; file << "window.zoom " << window.zoom << "\n";
file << "\n## VIDEO\n"; file << "\n## VIDEO\n";
file << "# Modo de video: 0 = Ventana, 1 = Pantalla completa, 2 = Pantalla completa (escritorio)\n"; file << "# Modo de video: 0 = Ventana, 1 = Pantalla completa, 2 = Pantalla completa (escritorio)\n";
file << "video.mode " << options.video.fullscreen << "\n\n"; file << "video.mode " << video.fullscreen << "\n\n";
file << "# Filtro de pantalla: 0 = Nearest, 1 = Linear\n"; file << "# Filtro de pantalla: 0 = Nearest, 1 = Linear\n";
file << "video.filter " << static_cast<int>(options.video.filter) << "\n\n"; file << "video.filter " << static_cast<int>(video.filter) << "\n\n";
file << "# Shaders: 1 = Activado, 0 = Desactivado\n"; file << "# Shaders: 1 = Activado, 0 = Desactivado\n";
file << "video.shaders " << boolToString(options.video.shaders) << "\n\n"; file << "video.shaders " << boolToString(video.shaders) << "\n\n";
file << "# Sincronización vertical: 1 = Activado, 0 = Desactivado\n"; file << "# Sincronización vertical: 1 = Activado, 0 = Desactivado\n";
file << "video.vertical_sync " << boolToString(options.video.vertical_sync) << "\n\n"; file << "video.vertical_sync " << boolToString(video.vertical_sync) << "\n\n";
file << "# Escalado entero: 1 = Activado, 0 = Desactivado\n"; file << "# Escalado entero: 1 = Activado, 0 = Desactivado\n";
file << "video.integer_scale " << boolToString(options.video.integer_scale) << "\n\n"; file << "video.integer_scale " << boolToString(video.integer_scale) << "\n\n";
file << "# Mantener aspecto: 1 = Activado, 0 = Desactivado\n"; file << "# Mantener aspecto: 1 = Activado, 0 = Desactivado\n";
file << "video.keep_aspect " << boolToString(options.video.keep_aspect) << "\n\n"; file << "video.keep_aspect " << boolToString(video.keep_aspect) << "\n\n";
file << "# Borde: 1 = Activado, 0 = Desactivado\n"; file << "# Borde: 1 = Activado, 0 = Desactivado\n";
file << "video.border.enabled " << boolToString(options.video.border.enabled) << "\n\n"; file << "video.border.enabled " << boolToString(video.border.enabled) << "\n\n";
file << "# Ancho del borde\n"; file << "# Ancho del borde\n";
file << "video.border.width " << options.video.border.width << "\n\n"; file << "video.border.width " << video.border.width << "\n\n";
file << "# Alto del borde\n"; file << "# Alto del borde\n";
file << "video.border.height " << options.video.border.height << "\n\n"; file << "video.border.height " << video.border.height << "\n\n";
file << "# Paleta\n"; file << "# Paleta\n";
file << "video.palette " << options.video.palette << "\n"; file << "video.palette " << video.palette << "\n";
// Cierra el fichero // Cierra el fichero
file.close(); file.close();
@@ -159,55 +171,55 @@ bool saveOptionsToFile(const std::string& file_path) {
bool setOptions(const std::string& var, const std::string& value) { bool setOptions(const std::string& var, const std::string& value) {
static const std::unordered_map<std::string, std::function<void(const std::string&)>> optionHandlers = { static const std::unordered_map<std::string, std::function<void(const std::string&)>> optionHandlers = {
{"version", [](const std::string& v) { options.version = v; }}, {"version", [](const std::string& v) { version = v; }},
{"keys", [](const std::string& v) { {"keys", [](const std::string& v) {
int val = safeStoi(v, static_cast<int>(DEFAULT_CONTROL_SCHEME)); int val = safeStoi(v, static_cast<int>(GameDefaults::CONTROL_SCHEME));
if (val == static_cast<int>(ControlScheme::CURSOR) || val == static_cast<int>(ControlScheme::OPQA) || val == static_cast<int>(ControlScheme::WASD)) { if (val == static_cast<int>(ControlScheme::CURSOR) || val == static_cast<int>(ControlScheme::OPQA) || val == static_cast<int>(ControlScheme::WASD)) {
options.keys = static_cast<ControlScheme>(val); keys = static_cast<ControlScheme>(val);
} else { } else {
options.keys = DEFAULT_CONTROL_SCHEME; keys = GameDefaults::CONTROL_SCHEME;
} }
}}, }},
{"window.zoom", [](const std::string& v) { {"window.zoom", [](const std::string& v) {
int val = safeStoi(v, DEFAULT_WINDOW_ZOOM); int val = safeStoi(v, GameDefaults::WINDOW_ZOOM);
if (val > 0) { if (val > 0) {
options.window.zoom = val; window.zoom = val;
} else { } else {
options.window.zoom = DEFAULT_WINDOW_ZOOM; window.zoom = GameDefaults::WINDOW_ZOOM;
} }
}}, }},
{"video.mode", [](const std::string& v) { options.video.fullscreen = stringToBool(v); }}, {"video.mode", [](const std::string& v) { video.fullscreen = stringToBool(v); }},
{"video.filter", [](const std::string& v) { {"video.filter", [](const std::string& v) {
int val = safeStoi(v, static_cast<int>(DEFAULT_VIDEO_FILTER)); int val = safeStoi(v, static_cast<int>(GameDefaults::VIDEO_FILTER));
if (val == static_cast<int>(ScreenFilter::NEAREST) || val == static_cast<int>(ScreenFilter::LINEAR)) { if (val == static_cast<int>(ScreenFilter::NEAREST) || val == static_cast<int>(ScreenFilter::LINEAR)) {
options.video.filter = static_cast<ScreenFilter>(val); video.filter = static_cast<ScreenFilter>(val);
} else { } else {
options.video.filter = DEFAULT_VIDEO_FILTER; video.filter = GameDefaults::VIDEO_FILTER;
} }
}}, }},
{"video.shaders", [](const std::string& v) { options.video.shaders = stringToBool(v); }}, {"video.shaders", [](const std::string& v) { video.shaders = stringToBool(v); }},
{"video.vertical_sync", [](const std::string& v) { options.video.vertical_sync = stringToBool(v); }}, {"video.vertical_sync", [](const std::string& v) { video.vertical_sync = stringToBool(v); }},
{"video.integer_scale", [](const std::string& v) { options.video.integer_scale = stringToBool(v); }}, {"video.integer_scale", [](const std::string& v) { video.integer_scale = stringToBool(v); }},
{"video.keep_aspect", [](const std::string& v) { options.video.keep_aspect = stringToBool(v); }}, {"video.keep_aspect", [](const std::string& v) { video.keep_aspect = stringToBool(v); }},
{"video.border.enabled", [](const std::string& v) { options.video.border.enabled = stringToBool(v); }}, {"video.border.enabled", [](const std::string& v) { video.border.enabled = stringToBool(v); }},
{"video.border.width", [](const std::string& v) { {"video.border.width", [](const std::string& v) {
int val = safeStoi(v, DEFAULT_BORDER_WIDTH); int val = safeStoi(v, GameDefaults::BORDER_WIDTH);
if (val > 0) { if (val > 0) {
options.video.border.width = val; video.border.width = val;
} else { } else {
options.video.border.width = DEFAULT_BORDER_WIDTH; video.border.width = GameDefaults::BORDER_WIDTH;
} }
}}, }},
{"video.border.height", [](const std::string& v) { {"video.border.height", [](const std::string& v) {
int val = safeStoi(v, DEFAULT_BORDER_HEIGHT); int val = safeStoi(v, GameDefaults::BORDER_HEIGHT);
if (val > 0) { if (val > 0) {
options.video.border.height = val; video.border.height = val;
} else { } else {
options.video.border.height = DEFAULT_BORDER_HEIGHT; video.border.height = GameDefaults::BORDER_HEIGHT;
} }
}}, }},
{"video.palette", [](const std::string& v) { {"video.palette", [](const std::string& v) {
options.video.palette = v; video.palette = v;
}}}; }}};
auto it = optionHandlers.find(var); auto it = optionHandlers.find(var);
@@ -217,3 +229,4 @@ bool setOptions(const std::string& var, const std::string& value) {
} }
return false; return false;
} }
}

View File

@@ -6,10 +6,22 @@
#include <string> // Para string, basic_string #include <string> // Para string, basic_string
#include "core/rendering/screen.hpp" // Para ScreenFilter #include "core/rendering/screen.hpp" // Para ScreenFilter
#include "utils/utils.hpp" // Para Color, Palette #include "utils/utils.hpp" // Para Color, Palette
// --- Namespace Options: gestión de configuración y opciones del juego ---
namespace Options {
// =============================================================================
// VOLUME HELPERS - Conversión de volumen 0-100 a 0-128
// =============================================================================
namespace VolumeHelpers {
constexpr int convertVolume(int volume_percent) {
return (volume_percent * 128) / 100;
}
} // namespace VolumeHelpers
// Secciones del programa // Secciones del programa
enum class Section { enum class Scene {
LOGO, LOGO,
LOADING_SCREEN, LOADING_SCREEN,
TITLE, TITLE,
@@ -23,7 +35,7 @@ enum class Section {
}; };
// Subsecciones // Subsecciones
enum class Subsection { enum class SceneOptions {
NONE, NONE,
LOGO_TO_INTRO, LOGO_TO_INTRO,
LOGO_TO_TITLE, LOGO_TO_TITLE,
@@ -54,49 +66,27 @@ enum class ControlScheme {
WASD WASD
}; };
// Constantes } // namespace Options
constexpr int DEFAULT_GAME_WIDTH = 256; // Ancho de la ventana por defecto
constexpr int DEFAULT_GAME_HEIGHT = 192; // Alto de la ventana por defecto // Incluir constantes por defecto después de declarar los enums
constexpr int DEFAULT_WINDOW_ZOOM = 2; // Zoom de la ventana por defecto #include "game/gameplay/defaults.hpp"
constexpr bool DEFAULT_VIDEO_MODE = false; // Modo de pantalla completa por defecto
constexpr ScreenFilter DEFAULT_VIDEO_FILTER = ScreenFilter::NEAREST; // Filtro por defecto namespace Options {
constexpr bool DEFAULT_VIDEO_VERTICAL_SYNC = true; // Vsync activado por defecto
constexpr bool DEFAULT_VIDEO_SHADERS = false; // Shaders desactivados por defecto
constexpr bool DEFAULT_VIDEO_INTEGER_SCALE = true; // Escalado entero activado por defecto
constexpr bool DEFAULT_VIDEO_KEEP_ASPECT = true; // Mantener aspecto activado por defecto
constexpr bool DEFAULT_BORDER_ENABLED = true; // Borde activado por defecto
constexpr int DEFAULT_BORDER_WIDTH = 32; // Ancho del borde por defecto
constexpr int DEFAULT_BORDER_HEIGHT = 24; // Alto del borde por defecto
constexpr int DEFAULT_SOUND_VOLUME = 100; // Volumen por defecto de los efectos de sonido
constexpr bool DEFAULT_SOUND_ENABLED = true; // Sonido habilitado por defecto
constexpr int DEFAULT_MUSIC_VOLUME = 80; // Volumen por defecto de la musica
constexpr bool DEFAULT_MUSIC_ENABLED = true; // Musica habilitada por defecto
constexpr int DEFAULT_AUDIO_VOLUME = 100; // Volumen por defecto
constexpr bool DEFAULT_AUDIO_ENABLED = true; // Audio por defecto
constexpr const char* DEFAULT_PALETTE = "zx-spectrum"; // Paleta por defecto
constexpr Section DEFAULT_SECTION = Section::LOGO; // Sección por defecto
constexpr Subsection DEFAULT_SUBSECTION = Subsection::LOGO_TO_INTRO; // Subsección por defecto
constexpr ControlScheme DEFAULT_CONTROL_SCHEME = ControlScheme::CURSOR; // Control por defecto
constexpr NotificationPosition DEFAULT_NOTIFICATION_POSITION = NotificationPosition::UPPER_LEFT; // Posición de las notificaciones por defecto
constexpr bool DEFAULT_NOTIFICATION_SOUND = true; // Sonido de las notificaciones por defecto
const Uint8 DEFAULT_NOTIFICATION_COLOR = static_cast<Uint8>(PaletteColor::BLUE); // Color de las notificaciones por defecto
constexpr bool DEFAULT_CONSOLE = false; // Consola desactivada por defecto
constexpr const char* DEFAULT_VERSION = "1.10"; // Versión por defecto
// Estructura para las opciones de las notificaciones // Estructura para las opciones de las notificaciones
struct OptionsNotification { struct Notification {
NotificationPosition pos; // Ubicación de las notificaciones en pantalla NotificationPosition pos; // Ubicación de las notificaciones en pantalla
bool sound; // Indica si las notificaciones suenan bool sound; // Indica si las notificaciones suenan
Uint8 color; // Color de las notificaciones Uint8 color; // Color de las notificaciones
// Constructor por defecto // Constructor por defecto
OptionsNotification() Notification()
: pos(DEFAULT_NOTIFICATION_POSITION), : pos(GameDefaults::NOTIFICATION_POSITION),
sound(DEFAULT_NOTIFICATION_SOUND), sound(GameDefaults::NOTIFICATION_SOUND),
color(DEFAULT_NOTIFICATION_COLOR) {} color(GameDefaults::NOTIFICATION_COLOR) {}
// Constructor // Constructor
OptionsNotification(NotificationPosition p, bool s, Uint8 c) Notification(NotificationPosition p, bool s, Uint8 c)
: pos(p), : pos(p),
sound(s), sound(s),
color(c) {} color(c) {}
@@ -116,7 +106,6 @@ struct OptionsNotification {
default: default:
return NotificationPosition::UNKNOWN; return NotificationPosition::UNKNOWN;
} }
return NotificationPosition::UNKNOWN;
} }
// Método que devuelve la posición vertical // Método que devuelve la posición vertical
@@ -133,94 +122,95 @@ struct OptionsNotification {
default: default:
return NotificationPosition::UNKNOWN; return NotificationPosition::UNKNOWN;
} }
return NotificationPosition::UNKNOWN;
} }
}; };
// Estructura para saber la seccion y subseccion del programa // Estructura para saber la seccion y subseccion del programa
struct SectionState { struct SceneState {
Section section; Scene section;
Subsection subsection; SceneOptions subsection;
// Constructor por defecto // Constructor por defecto
SectionState() SceneState()
: section(DEFAULT_SECTION), : section(GameDefaults::SCENE),
subsection(DEFAULT_SUBSECTION) {} subsection(GameDefaults::SUBSECTION) {}
// Constructor // Constructor
SectionState(Section s, Subsection ss) SceneState(Scene scene, SceneOptions scene_options)
: section(s), : section(scene),
subsection(ss) {} subsection(scene_options) {}
}; };
// Estructura para albergar trucos // Estructura para albergar trucos
struct Cheat { struct Cheat {
enum class CheatState : bool { enum class State : bool {
DISABLED = false, DISABLED = false,
ENABLED = true ENABLED = true
}; };
CheatState infinite_lives; // Indica si el jugador dispone de vidas infinitas State infinite_lives; // Indica si el jugador dispone de vidas infinitas
CheatState invincible; // Indica si el jugador puede morir State invincible; // Indica si el jugador puede morir
CheatState jail_is_open; // Indica si la Jail está abierta State jail_is_open; // Indica si la Jail está abierta
CheatState alternate_skin; // Indica si se usa una skin diferente para el jugador State alternate_skin; // Indica si se usa una skin diferente para el jugador
// Constructor por defecto // Constructor por defecto
Cheat() Cheat()
: infinite_lives(CheatState::DISABLED), : infinite_lives(State::DISABLED),
invincible(CheatState::DISABLED), invincible(State::DISABLED),
jail_is_open(CheatState::DISABLED), jail_is_open(State::DISABLED),
alternate_skin(CheatState::DISABLED) {} alternate_skin(State::DISABLED) {}
// Constructor // Constructor
Cheat(CheatState il, CheatState i, CheatState je, CheatState as) Cheat(State inf_lives, State is_invincible, State jail_enabled, State alt_skin)
: infinite_lives(il), : infinite_lives(inf_lives),
invincible(i), invincible(is_invincible),
jail_is_open(je), jail_is_open(jail_enabled),
alternate_skin(as) {} alternate_skin(alt_skin) {}
// Método para comprobar si alguno de los tres primeros trucos está activo // Método para comprobar si alguno de los tres primeros trucos está activo
bool enabled() const { bool enabled() const {
return infinite_lives == CheatState::ENABLED || return infinite_lives == State::ENABLED ||
invincible == CheatState::ENABLED || invincible == State::ENABLED ||
jail_is_open == CheatState::ENABLED; jail_is_open == State::ENABLED;
} }
}; };
// Estructura para almacenar estadísticas // Estructura para almacenar estadísticas
struct OptionsStats { struct Stats {
int rooms; // Cantidad de habitaciones visitadas int rooms; // Cantidad de habitaciones visitadas
int items; // Cantidad de items obtenidos int items; // Cantidad de items obtenidos
std::string worst_nightmare; // Habitación con más muertes acumuladas std::string worst_nightmare; // Habitación con más muertes acumuladas
// Constructor por defecto // Constructor por defecto
OptionsStats() Stats()
: rooms(0), : rooms(0),
items(0), items(0),
worst_nightmare("") {} worst_nightmare("") {}
// Constructor // Constructor
OptionsStats(int r, int i, const std::string& wn) Stats(int room_count, int item_count, const std::string& worst_nightmare_room)
: rooms(r), : rooms(room_count),
items(i), items(item_count),
worst_nightmare(wn) {} worst_nightmare(worst_nightmare_room) {}
}; };
// Estructura con opciones de la ventana // Estructura con opciones de la ventana
struct OptionsWindow { struct Window {
std::string caption = "JailDoctor's Dilemma"; // Texto que aparece en la barra de título de la ventana std::string caption; // Texto que aparece en la barra de título de la ventana
int zoom; // Zoom de la ventana int zoom; // Zoom de la ventana
int max_zoom; // Máximo tamaño de zoom para la ventana int max_zoom; // Máximo tamaño de zoom para la ventana
// Constructor por defecto // Constructor por defecto
OptionsWindow() Window()
: zoom(DEFAULT_WINDOW_ZOOM), : caption("JailDoctor's Dilemma"),
max_zoom(DEFAULT_WINDOW_ZOOM) {} zoom(GameDefaults::WINDOW_ZOOM),
max_zoom(GameDefaults::WINDOW_ZOOM) {}
// Constructor // Constructor
OptionsWindow(int z, int mz) Window(int window_zoom, int maximum_zoom)
: zoom(z), : caption("JailDoctor's Dilemma"),
max_zoom(mz) {} zoom(window_zoom),
max_zoom(maximum_zoom) {}
}; };
// Estructura para gestionar el borde de la pantalla // Estructura para gestionar el borde de la pantalla
@@ -231,19 +221,19 @@ struct Border {
// Constructor por defecto // Constructor por defecto
Border() Border()
: enabled(DEFAULT_BORDER_ENABLED), : enabled(GameDefaults::BORDER_ENABLED),
width(DEFAULT_BORDER_WIDTH), width(GameDefaults::BORDER_WIDTH),
height(DEFAULT_BORDER_HEIGHT) {} height(GameDefaults::BORDER_HEIGHT) {}
// Constructor // Constructor
Border(bool e, float w, float h) Border(bool is_enabled, float border_width, float border_height)
: enabled(e), : enabled(is_enabled),
width(w), width(border_width),
height(h) {} height(border_height) {}
}; };
// Estructura para las opciones de video // Estructura para las opciones de video
struct OptionsVideo { struct Video {
bool fullscreen; // Contiene el valor del modo de pantalla completa bool fullscreen; // Contiene el valor del modo de pantalla completa
ScreenFilter filter; // Filtro usado para el escalado de la imagen ScreenFilter filter; // Filtro usado para el escalado de la imagen
bool vertical_sync; // Indica si se quiere usar vsync o no bool vertical_sync; // Indica si se quiere usar vsync o no
@@ -255,170 +245,128 @@ struct OptionsVideo {
std::string info; // Información sobre el modo de vídeo std::string info; // Información sobre el modo de vídeo
// Constructor por defecto // Constructor por defecto
OptionsVideo() Video()
: fullscreen(DEFAULT_VIDEO_MODE), : fullscreen(GameDefaults::VIDEO_MODE),
filter(DEFAULT_VIDEO_FILTER), filter(GameDefaults::VIDEO_FILTER),
vertical_sync(DEFAULT_VIDEO_VERTICAL_SYNC), vertical_sync(GameDefaults::VIDEO_VERTICAL_SYNC),
shaders(DEFAULT_VIDEO_SHADERS), shaders(GameDefaults::VIDEO_SHADERS),
integer_scale(DEFAULT_VIDEO_INTEGER_SCALE), integer_scale(GameDefaults::VIDEO_INTEGER_SCALE),
keep_aspect(DEFAULT_VIDEO_KEEP_ASPECT), keep_aspect(GameDefaults::VIDEO_KEEP_ASPECT),
border(Border()), border(Border()),
palette(DEFAULT_PALETTE) {} palette(GameDefaults::PALETTE_NAME),
info("") {}
// Constructor // Constructor
OptionsVideo(Uint32 m, ScreenFilter f, bool vs, bool s, bool is, bool ka, Border b, const std::string& p) Video(bool is_fullscreen, ScreenFilter screen_filter, bool vsync, bool use_shaders, bool int_scale, bool keep_aspect_ratio, Border video_border, const std::string& palette_name)
: fullscreen(m), : fullscreen(is_fullscreen),
filter(f), filter(screen_filter),
vertical_sync(vs), vertical_sync(vsync),
shaders(s), shaders(use_shaders),
integer_scale(is), integer_scale(int_scale),
keep_aspect(ka), keep_aspect(keep_aspect_ratio),
border(b), border(video_border),
palette(p) {} palette(palette_name),
info("") {}
}; };
// Estructura para las opciones de musica // Estructura para las opciones de musica
struct OptionsMusic { struct Music {
bool enabled; // Indica si la música suena o no bool enabled; // Indica si la música suena o no
int volume; // Volumen al que suena la música (0 a 128 internamente) int volume; // Volumen al que suena la música (0 a 128 internamente)
// Constructor por defecto // Constructor por defecto
OptionsMusic() Music()
: enabled(DEFAULT_MUSIC_ENABLED), : enabled(GameDefaults::MUSIC_ENABLED),
volume(convertVolume(DEFAULT_MUSIC_VOLUME)) {} // Usa el método estático para la conversión volume(VolumeHelpers::convertVolume(GameDefaults::MUSIC_VOLUME)) {}
// Constructor con parámetros // Constructor con parámetros
OptionsMusic(bool e, int v) Music(bool is_enabled, int volume_percent)
: enabled(e), : enabled(is_enabled),
volume(convertVolume(v)) {} // Convierte el volumen usando el método estático volume(VolumeHelpers::convertVolume(volume_percent)) {}
// Método para establecer el volumen // Método para establecer el volumen
void setVolume(int v) { void setVolume(int volume_percent) {
v = std::clamp(v, 0, 100); // Ajusta v al rango [0, 100] volume_percent = std::clamp(volume_percent, 0, 100);
volume = convertVolume(v); // Convierte al rango interno volume = VolumeHelpers::convertVolume(volume_percent);
}
// Método estático para convertir de 0-100 a 0-128
static int convertVolume(int v) {
return (v * 128) / 100;
} }
}; };
// Estructura para las opciones de sonido // Estructura para las opciones de sonido
struct OptionsSound { struct Sound {
bool enabled; // Indica si los sonidos suenan o no bool enabled; // Indica si los sonidos suenan o no
int volume; // Volumen al que suenan los sonidos (0 a 128 internamente) int volume; // Volumen al que suenan los sonidos (0 a 128 internamente)
// Constructor por defecto // Constructor por defecto
OptionsSound() Sound()
: enabled(DEFAULT_SOUND_ENABLED), : enabled(GameDefaults::SOUND_ENABLED),
volume(convertVolume(DEFAULT_SOUND_VOLUME)) {} // Usa el método estático para la conversión volume(VolumeHelpers::convertVolume(GameDefaults::SOUND_VOLUME)) {}
// Constructor con parámetros // Constructor con parámetros
OptionsSound(bool e, int v) Sound(bool is_enabled, int volume_percent)
: enabled(e), : enabled(is_enabled),
volume(convertVolume(v)) {} // También lo integra aquí volume(VolumeHelpers::convertVolume(volume_percent)) {}
// Método para establecer el volumen // Método para establecer el volumen
void setVolume(int v) { void setVolume(int volume_percent) {
v = std::clamp(v, 0, 100); // Ajusta v al rango [0, 100] volume_percent = std::clamp(volume_percent, 0, 100);
volume = convertVolume(v); // Convierte al rango interno volume = VolumeHelpers::convertVolume(volume_percent);
}
// Método estático para convertir de 0-100 a 0-128
static int convertVolume(int v) {
return (v * 128) / 100;
} }
}; };
// Estructura para las opciones de audio // Estructura para las opciones de audio
struct OptionsAudio { struct Audio {
OptionsMusic music; // Opciones para la música Music music; // Opciones para la música
OptionsSound sound; // Opciones para los efectos de sonido Sound sound; // Opciones para los efectos de sonido
bool enabled; // Indica si el audio está activo o no bool enabled; // Indica si el audio está activo o no
int volume; // Volumen al que suenan el audio int volume; // Volumen al que suenan el audio (0-128 internamente)
// Constructor por defecto // Constructor por defecto
OptionsAudio() Audio()
: music(OptionsMusic()), : music(Music()),
sound(OptionsSound()), sound(Sound()),
enabled(DEFAULT_AUDIO_ENABLED), enabled(GameDefaults::AUDIO_ENABLED),
volume(DEFAULT_AUDIO_VOLUME) {} volume(VolumeHelpers::convertVolume(GameDefaults::AUDIO_VOLUME)) {}
// Constructor // Constructor
OptionsAudio(OptionsMusic m, OptionsSound s, bool e, int v) Audio(Music audio_music, Sound audio_sound, bool is_enabled, int volume_percent)
: music(m), : music(audio_music),
sound(s), sound(audio_sound),
enabled(e), enabled(is_enabled),
volume(v) {} volume(VolumeHelpers::convertVolume(volume_percent)) {}
}; };
// Estructura para las opciones de juego // Estructura para las opciones de juego
struct OptionsGame { struct Game {
float width; // Ancho de la resolucion del juego float width; // Ancho de la resolucion del juego
float height; // Alto de la resolucion del juego float height; // Alto de la resolucion del juego
// Constructor por defecto // Constructor por defecto
OptionsGame() Game()
: width(DEFAULT_GAME_WIDTH), : width(GameDefaults::GAME_WIDTH),
height(DEFAULT_GAME_HEIGHT) {} height(GameDefaults::GAME_HEIGHT) {}
// Constructor // Constructor
OptionsGame(float w, float h) Game(float game_width, float game_height)
: width(w), : width(game_width),
height(h) {} height(game_height) {}
}; };
// Estructura con todas las opciones de configuración del programa // --- Variables ---
struct Options { extern std::string version; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles
std::string version; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles extern bool console; // Indica si ha de mostrar información por la consola de texto
bool console; // Indica si ha de mostrar información por la consola de texto extern Cheat cheats; // Contiene trucos y ventajas para el juego
Cheat cheats; // Contiene trucos y ventajas para el juego extern Game game; // Opciones de juego
OptionsGame game; // Opciones de juego extern Video video; // Opciones de video
OptionsVideo video; // Opciones de video extern Stats stats; // Datos con las estadisticas de juego
OptionsStats stats; // Datos con las estadisticas de juego extern Notification notifications; // Opciones relativas a las notificaciones;
OptionsNotification notifications; // Opciones relativas a las notificaciones; extern Window window; // Opciones relativas a la ventana
OptionsWindow window; // Opciones relativas a la ventana extern Audio audio; // Opciones relativas al audio
OptionsAudio audio; // Opciones relativas al audio extern ControlScheme keys; // Teclas usadas para jugar
ControlScheme keys; // Teclas usadas para jugar extern SceneState section; // Sección actual del programa
SectionState section; // Sección actual del programa
// Constructor por defecto // --- Funciones ---
Options() void init(); // Crea e inicializa las opciones del programa
: version(DEFAULT_VERSION), bool loadFromFile(const std::string& file_path); // Carga las opciones desde un fichero
console(DEFAULT_CONSOLE), bool saveToFile(const std::string& file_path); // Guarda las opciones a un fichero
cheats(Cheat()),
game(OptionsGame()),
video(OptionsVideo()),
stats(OptionsStats()),
notifications(OptionsNotification()),
window(OptionsWindow()),
audio(OptionsAudio()),
keys(DEFAULT_CONTROL_SCHEME),
section(SectionState()) {}
// Constructor } // namespace Options
Options(std::string cv, bool c, Cheat ch, OptionsGame g, OptionsVideo v, OptionsStats s, OptionsNotification n, OptionsWindow sw, OptionsAudio a, ControlScheme k, SectionState sec)
: version(cv),
console(c),
cheats(ch),
game(g),
video(v),
stats(s),
notifications(n),
window(sw),
audio(a),
keys(k),
section(sec) {}
};
extern Options options;
// Crea e inicializa las opciones del programa
void initOptions();
// Carga las opciones desde un fichero
bool loadOptionsFromFile(const std::string& file_path);
// Guarda las opciones a un fichero
bool saveOptionsToFile(const std::string& file_path);

View File

@@ -5,17 +5,17 @@
#include <iostream> // Para cout, cerr #include <iostream> // Para cout, cerr
#include <sstream> // Para basic_stringstream #include <sstream> // Para basic_stringstream
#include "core/system/debug.hpp" // Para Debug #include "core/rendering/screen.hpp" // Para Screen
#include "utils/defines.hpp" // Para BLOCK, PLAY_AREA_HEIGHT, PLAY_AREA_WIDTH #include "core/rendering/surface.hpp" // Para Surface
#include "external/jail_audio.h" // Para JA_PlaySound
#include "game/gameplay/item_tracker.hpp" // Para ItemTracker
#include "game/gameplay/options.hpp" // Para Options, OptionsStats, options
#include "core/resources/resource.hpp" // Para Resource
#include "game/gameplay/scoreboard.hpp" // Para ScoreboardData
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical #include "core/system/debug.hpp" // Para Debug
#include "external/jail_audio.h" // Para JA_PlaySound
#include "game/gameplay/item_tracker.hpp" // Para ItemTracker
#include "game/gameplay/options.hpp" // Para Options, OptionsStats, options
#include "game/gameplay/scoreboard.hpp" // Para ScoreboardData
#include "utils/defines.hpp" // Para BLOCK, PLAY_AREA_HEIGHT, PLAY_AREA_WIDTH
#include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical
// Carga las variables y texturas desde un fichero de mapa de tiles // Carga las variables y texturas desde un fichero de mapa de tiles
std::vector<int> loadRoomTileFile(const std::string& file_path, bool verbose) { std::vector<int> loadRoomTileFile(const std::string& file_path, bool verbose) {
@@ -579,7 +579,7 @@ bool Room::itemCollision(SDL_FRect& rect) {
items_.erase(items_.begin() + i); items_.erase(items_.begin() + i);
JA_PlaySound(Resource::get()->getSound("item.wav")); JA_PlaySound(Resource::get()->getSound("item.wav"));
data_->items++; data_->items++;
options.stats.items = data_->items; Options::stats.items = data_->items;
return true; return true;
} }
} }

View File

@@ -6,12 +6,12 @@
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "game/entities/enemy.hpp" // Para EnemyData #include "game/entities/enemy.hpp" // Para EnemyData
#include "game/entities/item.hpp" // Para ItemData #include "game/entities/item.hpp" // Para ItemData
#include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical #include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical
class SSprite; // lines 12-12 class SSprite; // lines 12-12
class Surface; // lines 13-13 class Surface; // lines 13-13
struct ScoreboardData; // lines 15-15 struct ScoreboardData; // lines 15-15
enum class TileType { enum class TileType {
EMPTY, EMPTY,

View File

@@ -1,12 +1,9 @@
#include "game/gameplay/room_tracker.hpp" #include "game/gameplay/room_tracker.hpp"
// Comprueba si la habitación ya ha sido visitada // Comprueba si la habitación ya ha sido visitada
bool RoomTracker::hasBeenVisited(const std::string &name) bool RoomTracker::hasBeenVisited(const std::string& name) {
{ for (const auto& l : list) {
for (const auto &l : list) if (l == name) {
{
if (l == name)
{
return true; return true;
} }
} }
@@ -15,11 +12,9 @@ bool RoomTracker::hasBeenVisited(const std::string &name)
} }
// Añade la habitación a la lista // Añade la habitación a la lista
bool RoomTracker::addRoom(const std::string &name) bool RoomTracker::addRoom(const std::string& name) {
{
// Comprueba si la habitación ya ha sido visitada // Comprueba si la habitación ya ha sido visitada
if (!hasBeenVisited(name)) if (!hasBeenVisited(name)) {
{
// En caso contrario añádela a la lista // En caso contrario añádela a la lista
list.push_back(name); list.push_back(name);
return true; return true;

View File

@@ -1,24 +1,23 @@
#pragma once #pragma once
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
class RoomTracker class RoomTracker {
{ private:
private: // Variables
// Variables std::vector<std::string> list; // Lista con las habitaciones visitadas
std::vector<std::string> list; // Lista con las habitaciones visitadas
// Comprueba si la habitación ya ha sido visitada // Comprueba si la habitación ya ha sido visitada
bool hasBeenVisited(const std::string &name); bool hasBeenVisited(const std::string& name);
public: public:
// Constructor // Constructor
RoomTracker() = default; RoomTracker() = default;
// Destructor // Destructor
~RoomTracker() = default; ~RoomTracker() = default;
// Añade la habitación a la lista // Añade la habitación a la lista
bool addRoom(const std::string &name); bool addRoom(const std::string& name);
}; };

View File

@@ -2,31 +2,31 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include "utils/defines.hpp" // Para BLOCK #include "core/rendering/screen.hpp" // Para Screen
#include "game/gameplay/options.hpp" // Para Options, options, Cheat, OptionsGame #include "core/rendering/surface.hpp" // Para Surface
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text
#include "core/rendering/text.hpp" // Para Text #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para stringToColor #include "game/gameplay/options.hpp" // Para Options, options, Cheat, OptionsGame
#include "utils/defines.hpp" // Para BLOCK
#include "utils/utils.hpp" // Para stringToColor
// Constructor // Constructor
Scoreboard::Scoreboard(std::shared_ptr<ScoreboardData> data) Scoreboard::Scoreboard(std::shared_ptr<ScoreboardData> data)
: item_surface_(Resource::get()->getSurface("items.gif")), : item_surface_(Resource::get()->getSurface("items.gif")),
data_(data), data_(data),
clock_(ClockData()) { clock_(ClockData()) {
const float SURFACE_WIDTH_ = options.game.width; const float SURFACE_WIDTH_ = Options::game.width;
constexpr float SURFACE_HEIGHT_ = 6.0F * BLOCK; constexpr float SURFACE_HEIGHT_ = 6.0F * BLOCK;
// Reserva memoria para los objetos // Reserva memoria para los objetos
auto player_texture = Resource::get()->getSurface(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.gif" : "player.gif"); auto player_texture = Resource::get()->getSurface(Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.gif" : "player.gif");
auto player_animations = Resource::get()->getAnimations(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani"); auto player_animations = Resource::get()->getAnimations(Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.ani" : "player.ani");
player_sprite_ = std::make_shared<SAnimatedSprite>(player_texture, player_animations); player_sprite_ = std::make_shared<SAnimatedSprite>(player_texture, player_animations);
player_sprite_->setCurrentAnimation("walk_menu"); player_sprite_->setCurrentAnimation("walk_menu");
surface_ = std::make_shared<Surface>(SURFACE_WIDTH_, SURFACE_HEIGHT_); surface_ = std::make_shared<Surface>(SURFACE_WIDTH_, SURFACE_HEIGHT_);
surface_dest_ = {0, options.game.height - SURFACE_HEIGHT_, SURFACE_WIDTH_, SURFACE_HEIGHT_}; surface_dest_ = {0, Options::game.height - SURFACE_HEIGHT_, SURFACE_WIDTH_, SURFACE_HEIGHT_};
// Inicializa las variables // Inicializa las variables
counter_ = 0; counter_ = 0;

View File

@@ -1,16 +1,17 @@
#include "game/gameplay/stats.hpp" #include "game/gameplay/stats.hpp"
#include <fstream> // Para basic_ostream, basic_ifstream, basic_istream
#include <sstream> // Para basic_stringstream #include <fstream> // Para basic_ostream, basic_ifstream, basic_istream
#include "game/gameplay/options.hpp" // Para Options, OptionsStats, options #include <sstream> // Para basic_stringstream
#include "game/gameplay/options.hpp" // Para Options, OptionsStats, options
// Constructor // Constructor
Stats::Stats(const std::string &file, const std::string &buffer) Stats::Stats(const std::string& file, const std::string& buffer)
: bufferPath(buffer), : bufferPath(buffer),
filePath(file) {} filePath(file) {}
// Destructor // Destructor
Stats::~Stats() Stats::~Stats() {
{
// Vuelca los datos del buffer en la lista de estadisticas // Vuelca los datos del buffer en la lista de estadisticas
updateListFromBuffer(); updateListFromBuffer();
@@ -38,18 +39,15 @@ void Stats::init()
} }
// Añade una muerte a las estadisticas // Añade una muerte a las estadisticas
void Stats::addDeath(const std::string &name) void Stats::addDeath(const std::string& name) {
{
// Primero busca si ya hay una entrada con ese nombre // Primero busca si ya hay una entrada con ese nombre
const int index = findByName(name, bufferList); const int index = findByName(name, bufferList);
if (index != -1) if (index != -1) {
{
bufferList[index].died++; bufferList[index].died++;
} }
// En caso contrario crea la entrada // En caso contrario crea la entrada
else else {
{
StatsData item; StatsData item;
item.name = name; item.name = name;
item.visited = 0; item.visited = 0;
@@ -59,18 +57,15 @@ void Stats::addDeath(const std::string &name)
} }
// Añade una visita a las estadisticas // Añade una visita a las estadisticas
void Stats::addVisit(const std::string &name) void Stats::addVisit(const std::string& name) {
{
// Primero busca si ya hay una entrada con ese nombre // Primero busca si ya hay una entrada con ese nombre
const int index = findByName(name, bufferList); const int index = findByName(name, bufferList);
if (index != -1) if (index != -1) {
{
bufferList[index].visited++; bufferList[index].visited++;
} }
// En caso contrario crea la entrada // En caso contrario crea la entrada
else else {
{
StatsData item; StatsData item;
item.name = name; item.name = name;
item.visited = 1; item.visited = 1;
@@ -80,14 +75,11 @@ void Stats::addVisit(const std::string &name)
} }
// Busca una entrada en la lista por nombre // Busca una entrada en la lista por nombre
int Stats::findByName(const std::string &name, const std::vector<StatsData> &list) int Stats::findByName(const std::string& name, const std::vector<StatsData>& list) {
{
int i = 0; int i = 0;
for (const auto &l : list) for (const auto& l : list) {
{ if (l.name == name) {
if (l.name == name)
{
return i; return i;
} }
i++; i++;
@@ -97,8 +89,7 @@ int Stats::findByName(const std::string &name, const std::vector<StatsData> &lis
} }
// Carga las estadisticas desde un fichero // Carga las estadisticas desde un fichero
bool Stats::loadFromFile(const std::string &file_path, std::vector<StatsData> &list) bool Stats::loadFromFile(const std::string& file_path, std::vector<StatsData>& list) {
{
list.clear(); list.clear();
// Indicador de éxito en la carga // Indicador de éxito en la carga
@@ -108,15 +99,12 @@ bool Stats::loadFromFile(const std::string &file_path, std::vector<StatsData> &l
std::ifstream file(file_path); std::ifstream file(file_path);
// Si el fichero se puede abrir // Si el fichero se puede abrir
if (file.good()) if (file.good()) {
{
std::string line; std::string line;
// Procesa el fichero linea a linea // Procesa el fichero linea a linea
while (std::getline(file, line)) while (std::getline(file, line)) {
{
// Comprueba que la linea no sea un comentario // Comprueba que la linea no sea un comentario
if (line.substr(0, 1) != "#") if (line.substr(0, 1) != "#") {
{
StatsData stat; StatsData stat;
std::stringstream ss(line); std::stringstream ss(line);
std::string tmp; std::string tmp;
@@ -142,8 +130,7 @@ bool Stats::loadFromFile(const std::string &file_path, std::vector<StatsData> &l
} }
// El fichero no existe // El fichero no existe
else else {
{
// Crea el fichero con los valores por defecto // Crea el fichero con los valores por defecto
saveToFile(file_path, list); saveToFile(file_path, list);
} }
@@ -152,15 +139,13 @@ bool Stats::loadFromFile(const std::string &file_path, std::vector<StatsData> &l
} }
// Guarda las estadisticas en un fichero // Guarda las estadisticas en un fichero
void Stats::saveToFile(const std::string &file_path, const std::vector<StatsData> &list) void Stats::saveToFile(const std::string& file_path, const std::vector<StatsData>& list) {
{
// Crea y abre el fichero de texto // Crea y abre el fichero de texto
std::ofstream file(file_path); std::ofstream file(file_path);
// Escribe en el fichero // Escribe en el fichero
file << "# ROOM NAME;VISITS;DEATHS" << std::endl; file << "# ROOM NAME;VISITS;DEATHS" << std::endl;
for (const auto &item : list) for (const auto& item : list) {
{
file << item.name << ";" << item.visited << ";" << item.died << std::endl; file << item.name << ";" << item.visited << ";" << item.died << std::endl;
} }
@@ -169,40 +154,31 @@ void Stats::saveToFile(const std::string &file_path, const std::vector<StatsData
} }
// Calcula cual es la habitación con más muertes // Calcula cual es la habitación con más muertes
void Stats::checkWorstNightmare() void Stats::checkWorstNightmare() {
{
int deaths = 0; int deaths = 0;
for (const auto &item : list) for (const auto& item : list) {
{ if (item.died > deaths) {
if (item.died > deaths)
{
deaths = item.died; deaths = item.died;
options.stats.worst_nightmare = item.name; Options::stats.worst_nightmare = item.name;
} }
} }
} }
// Añade una entrada al diccionario // Añade una entrada al diccionario
void Stats::addDictionary(const std::string &number, const std::string &name) void Stats::addDictionary(const std::string& number, const std::string& name) {
{
dictionary.push_back({number, name}); dictionary.push_back({number, name});
} }
// Vuelca los datos del buffer en la lista de estadisticas // Vuelca los datos del buffer en la lista de estadisticas
void Stats::updateListFromBuffer() void Stats::updateListFromBuffer() {
{
// Actualiza list desde bufferList // Actualiza list desde bufferList
for (const auto &buffer : bufferList) for (const auto& buffer : bufferList) {
{
int index = findByName(buffer.name, list); int index = findByName(buffer.name, list);
if (index != -1) if (index != -1) { // Encontrado. Aumenta sus estadisticas
{ // Encontrado. Aumenta sus estadisticas
list[index].visited += buffer.visited; list[index].visited += buffer.visited;
list[index].died += buffer.died; list[index].died += buffer.died;
} } else { // En caso contrario crea la entrada
else
{ // En caso contrario crea la entrada
StatsData item; StatsData item;
item.name = buffer.name; item.name = buffer.name;
item.visited = buffer.visited; item.visited = buffer.visited;

View File

@@ -1,63 +1,60 @@
#pragma once #pragma once
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
class Stats class Stats {
{ private:
private: struct StatsData {
struct StatsData std::string name; // Nombre de la habitación
{ int visited; // Cuenta las veces que se ha visitado una habitación
std::string name; // Nombre de la habitación int died; // Cuenta las veces que se ha muerto en una habitación
int visited; // Cuenta las veces que se ha visitado una habitación };
int died; // Cuenta las veces que se ha muerto en una habitación
};
struct StatsDictionary struct StatsDictionary {
{ std::string number; // Numero de la habitación
std::string number; // Numero de la habitación std::string name; // Nombre de la habitación
std::string name; // Nombre de la habitación };
};
// Variables // Variables
std::vector<StatsDictionary> dictionary; // Lista con la equivalencia nombre-numero de habitacion std::vector<StatsDictionary> dictionary; // Lista con la equivalencia nombre-numero de habitacion
std::vector<StatsData> bufferList; // Lista con las estadisticas temporales por habitación std::vector<StatsData> bufferList; // Lista con las estadisticas temporales por habitación
std::vector<StatsData> list; // Lista con las estadisticas completas por habitación std::vector<StatsData> list; // Lista con las estadisticas completas por habitación
std::string bufferPath; // Fichero con las estadísticas temporales std::string bufferPath; // Fichero con las estadísticas temporales
std::string filePath; // Fichero con las estadísticas completas std::string filePath; // Fichero con las estadísticas completas
// Busca una entrada en la lista por nombre // Busca una entrada en la lista por nombre
int findByName(const std::string &name, const std::vector<StatsData> &list); int findByName(const std::string& name, const std::vector<StatsData>& list);
// Carga las estadisticas desde un fichero // Carga las estadisticas desde un fichero
bool loadFromFile(const std::string &filePath, std::vector<StatsData> &list); bool loadFromFile(const std::string& filePath, std::vector<StatsData>& list);
// Guarda las estadisticas en un fichero // Guarda las estadisticas en un fichero
void saveToFile(const std::string &filePath, const std::vector<StatsData> &list); void saveToFile(const std::string& filePath, const std::vector<StatsData>& list);
// Calcula cual es la habitación con más muertes // Calcula cual es la habitación con más muertes
void checkWorstNightmare(); void checkWorstNightmare();
// Vuelca los datos del buffer en la lista de estadisticas // Vuelca los datos del buffer en la lista de estadisticas
void updateListFromBuffer(); void updateListFromBuffer();
public: public:
// Constructor // Constructor
Stats(const std::string &file, const std::string &buffer); Stats(const std::string& file, const std::string& buffer);
// Destructor // Destructor
~Stats(); ~Stats();
// Inicializador // Inicializador
// Se debe llamar a este procedimiento una vez se haya creado el diccionario numero-nombre // Se debe llamar a este procedimiento una vez se haya creado el diccionario numero-nombre
void init(); void init();
// Añade una muerte a las estadisticas // Añade una muerte a las estadisticas
void addDeath(const std::string &name); void addDeath(const std::string& name);
// Añade una visita a las estadisticas // Añade una visita a las estadisticas
void addVisit(const std::string &name); void addVisit(const std::string& name);
// Añade una entrada al diccionario // Añade una entrada al diccionario
void addDictionary(const std::string &number, const std::string &name); void addDictionary(const std::string& number, const std::string& name);
}; };

View File

@@ -4,33 +4,33 @@
#include <algorithm> // Para min #include <algorithm> // Para min
#include "utils/defines.hpp" // Para GAME_SPEED, PLAY_AREA_CENTER_X, PLAY_... #include "core/input/global_inputs.hpp" // Para check
#include "utils/global_events.hpp" // Para check #include "core/rendering/screen.hpp" // Para Screen
#include "core/input/global_inputs.hpp" // Para check #include "core/rendering/surface.hpp" // Para Surface
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, Sectio...
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para PaletteColor #include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, Sectio...
#include "utils/defines.hpp" // Para GAME_SPEED, PLAY_AREA_CENTER_X, PLAY_...
#include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para PaletteColor
// Constructor // Constructor
Credits::Credits() Credits::Credits()
: shining_sprite_(std::make_shared<SAnimatedSprite>(Resource::get()->getSurface("shine.gif"), Resource::get()->getAnimations("shine.ani"))) { : shining_sprite_(std::make_shared<SAnimatedSprite>(Resource::get()->getSurface("shine.gif"), Resource::get()->getAnimations("shine.ani"))) {
// Inicializa variables // Inicializa variables
options.section.section = Section::CREDITS; Options::section.section = Options::Scene::CREDITS;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
shining_sprite_->setPos({194, 174, 8, 8}); shining_sprite_->setPos({194, 174, 8, 8});
// Cambia el color del borde // Cambia el color del borde
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
// Crea la textura para el texto que se escribe en pantalla // Crea la textura para el texto que se escribe en pantalla
text_surface_ = std::make_shared<Surface>(options.game.width, options.game.height); text_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height);
// Crea la textura para cubrir el rexto // Crea la textura para cubrir el rexto
cover_surface_ = std::make_shared<Surface>(options.game.width, options.game.height); cover_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height);
// Escribe el texto en la textura // Escribe el texto en la textura
fillTexture(); fillTexture();
@@ -51,17 +51,16 @@ void Credits::checkInput() {
// Inicializa los textos // Inicializa los textos
void Credits::iniTexts() { void Credits::iniTexts() {
#ifndef GAME_CONSOLE
std::string keys = ""; std::string keys = "";
switch (options.keys) { switch (Options::keys) {
case ControlScheme::CURSOR: case Options::ControlScheme::CURSOR:
keys = "CURSORS"; keys = "CURSORS";
break; break;
case ControlScheme::OPQA: case Options::ControlScheme::OPQA:
keys = "O,P AND Q"; keys = "O,P AND Q";
break; break;
case ControlScheme::WASD: case Options::ControlScheme::WASD:
keys = "A,D AND W"; keys = "A,D AND W";
break; break;
default: default:
@@ -96,36 +95,6 @@ void Credits::iniTexts() {
texts_.push_back({"I LOVE JAILGAMES! ", static_cast<Uint8>(PaletteColor::WHITE)}); texts_.push_back({"I LOVE JAILGAMES! ", static_cast<Uint8>(PaletteColor::WHITE)});
texts_.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)}); texts_.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
#else
texts.clear();
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"INSTRUCTIONS:", static_cast<Uint8>(PaletteColor::YELLOW)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"HELP JAILDOC TO GET BACK ALL", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"HIS PROJECTS AND GO TO THE", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"JAIL TO FINISH THEM", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"KEYS:", static_cast<Uint8>(PaletteColor::YELLOW)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"B TO JUMP", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"R TO SWITCH THE MUSIC", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"L TO SWAP THE COLOR PALETTE", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"START TO PAUSE", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"SELECT TO EXIT", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"A GAME BY JAILDESIGNER", static_cast<Uint8>(PaletteColor::YELLOW)});
texts.push_back({"MADE ON SUMMER/FALL 2022", static_cast<Uint8>(PaletteColor::YELLOW)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"I LOVE JAILGAMES! ", static_cast<Uint8>(PaletteColor::WHITE)});
texts.push_back({"", static_cast<Uint8>(PaletteColor::WHITE)});
#endif
} }
// Escribe el texto en la textura // Escribe el texto en la textura
@@ -196,7 +165,7 @@ void Credits::updateCounter() {
// Comprueba si ha terminado la sección // Comprueba si ha terminado la sección
if (counter_ > 1200) { if (counter_ > 1200) {
options.section.section = Section::DEMO; Options::section.section = Options::Scene::DEMO;
} }
} }
@@ -249,7 +218,7 @@ void Credits::render() {
// Bucle para el logo del juego // Bucle para el logo del juego
void Credits::run() { void Credits::run() {
while (options.section.section == Section::CREDITS) { while (Options::section.section == Options::Scene::CREDITS) {
update(); update();
checkEvents(); checkEvents();
render(); render();

View File

@@ -4,17 +4,17 @@
#include <algorithm> // Para min #include <algorithm> // Para min
#include "utils/defines.hpp" // Para GAME_SPEED #include "core/input/global_inputs.hpp" // Para check
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic #include "core/rendering/screen.hpp" // Para Screen
#include "utils/global_events.hpp" // Para check #include "core/rendering/surface.hpp" // Para Surface
#include "core/input/global_inputs.hpp" // Para check
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, SectionS...
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text, TEXT_STROKE
#include "core/rendering/text.hpp" // Para Text, TEXT_STROKE #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para PaletteColor #include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, SectionS...
#include "utils/defines.hpp" // Para GAME_SPEED
#include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para PaletteColor
// Constructor // Constructor
Ending::Ending() Ending::Ending()
@@ -23,8 +23,8 @@ Ending::Ending()
cover_counter_(0), cover_counter_(0),
ticks_(0), ticks_(0),
current_scene_(0) { current_scene_(0) {
options.section.section = Section::ENDING; Options::section.section = Options::Scene::ENDING;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
// Inicializa los textos // Inicializa los textos
iniTexts(); iniTexts();
@@ -39,7 +39,7 @@ Ending::Ending()
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
// Crea la textura para cubrir el texto // Crea la textura para cubrir el texto
cover_surface_ = std::make_shared<Surface>(options.game.width, options.game.height + 8); cover_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height + 8);
// Rellena la textura para la cortinilla // Rellena la textura para la cortinilla
fillCoverTexture(); fillCoverTexture();
@@ -167,7 +167,7 @@ void Ending::iniTexts() {
// Crea el sprite // Crea el sprite
st.image_sprite = std::make_shared<SSprite>(st.image_surface, 0, 0, st.image_surface->getWidth(), st.image_surface->getHeight()); st.image_sprite = std::make_shared<SSprite>(st.image_surface, 0, 0, st.image_surface->getWidth(), st.image_surface->getHeight());
st.image_sprite->setPosition((options.game.width - st.image_surface->getWidth()) / 2, txt.pos); st.image_sprite->setPosition((Options::game.width - st.image_surface->getWidth()) / 2, txt.pos);
// Crea la cover_surface // Crea la cover_surface
st.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8); st.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8);
@@ -195,7 +195,7 @@ void Ending::iniTexts() {
// Crea el sprite // Crea el sprite
st.cover_sprite = std::make_shared<SSprite>(st.cover_surface, 0, 0, st.cover_surface->getWidth(), st.cover_surface->getHeight() - 8); st.cover_sprite = std::make_shared<SSprite>(st.cover_surface, 0, 0, st.cover_surface->getWidth(), st.cover_surface->getHeight() - 8);
st.cover_sprite->setPosition((options.game.width - st.cover_surface->getWidth()) / 2, txt.pos); st.cover_sprite->setPosition((Options::game.width - st.cover_surface->getWidth()) / 2, txt.pos);
st.cover_sprite->setClip(0, 8, st.cover_surface->getWidth(), st.cover_surface->getHeight()); st.cover_sprite->setClip(0, 8, st.cover_surface->getWidth(), st.cover_surface->getHeight());
// Inicializa variables // Inicializa variables
@@ -232,7 +232,7 @@ void Ending::iniPics() {
// Crea el sprite // Crea el sprite
sp.image_sprite = std::make_shared<SSprite>(sp.image_surface, 0, 0, WIDTH, HEIGHT); sp.image_sprite = std::make_shared<SSprite>(sp.image_surface, 0, 0, WIDTH, HEIGHT);
sp.image_sprite->setPosition((options.game.width - WIDTH) / 2, pic.pos); sp.image_sprite->setPosition((Options::game.width - WIDTH) / 2, pic.pos);
// Crea la cover_surface // Crea la cover_surface
sp.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8); sp.cover_surface = std::make_shared<Surface>(WIDTH, HEIGHT + 8);
@@ -261,7 +261,7 @@ void Ending::iniPics() {
// Crea el sprite // Crea el sprite
sp.cover_sprite = std::make_shared<SSprite>(sp.cover_surface, 0, 0, sp.cover_surface->getWidth(), sp.cover_surface->getHeight() - 8); sp.cover_sprite = std::make_shared<SSprite>(sp.cover_surface, 0, 0, sp.cover_surface->getWidth(), sp.cover_surface->getHeight() - 8);
sp.cover_sprite->setPosition((options.game.width - sp.cover_surface->getWidth()) / 2, pic.pos); sp.cover_sprite->setPosition((Options::game.width - sp.cover_surface->getWidth()) / 2, pic.pos);
sp.cover_sprite->setClip(0, 8, sp.cover_surface->getWidth(), sp.cover_surface->getHeight()); sp.cover_sprite->setClip(0, 8, sp.cover_surface->getWidth(), sp.cover_surface->getHeight());
// Inicializa variables // Inicializa variables
@@ -359,7 +359,7 @@ void Ending::iniScenes() {
void Ending::run() { void Ending::run() {
JA_PlayMusic(Resource::get()->getMusic("ending1.ogg")); JA_PlayMusic(Resource::get()->getMusic("ending1.ogg"));
while (options.section.section == Section::ENDING) { while (Options::section.section == Options::Scene::ENDING) {
update(); update();
checkEvents(); checkEvents();
render(); render();
@@ -423,7 +423,7 @@ void Ending::checkChangeScene() {
cover_counter_ = 0; cover_counter_ = 0;
if (current_scene_ == 5) { if (current_scene_ == 5) {
// Termina el bucle // Termina el bucle
options.section.section = Section::ENDING2; Options::section.section = Options::Scene::ENDING2;
// Mantiene los valores anteriores // Mantiene los valores anteriores
current_scene_ = 4; current_scene_ = 4;
@@ -443,17 +443,17 @@ void Ending::fillCoverTexture() {
const Uint8 color = static_cast<Uint8>(PaletteColor::BLACK); const Uint8 color = static_cast<Uint8>(PaletteColor::BLACK);
auto surface = Screen::get()->getRendererSurface(); auto surface = Screen::get()->getRendererSurface();
for (int i = 0; i < 256; i += 2) { for (int i = 0; i < 256; i += 2) {
surface->putPixel(i + 0, options.game.height + 0, color); surface->putPixel(i + 0, Options::game.height + 0, color);
surface->putPixel(i + 1, options.game.height + 1, color); surface->putPixel(i + 1, Options::game.height + 1, color);
surface->putPixel(i + 0, options.game.height + 2, color); surface->putPixel(i + 0, Options::game.height + 2, color);
surface->putPixel(i + 1, options.game.height + 3, color); surface->putPixel(i + 1, Options::game.height + 3, color);
surface->putPixel(i, options.game.height + 4, color); surface->putPixel(i, Options::game.height + 4, color);
surface->putPixel(i, options.game.height + 6, color); surface->putPixel(i, Options::game.height + 6, color);
} }
// El resto se rellena de color sólido // El resto se rellena de color sólido
SDL_FRect rect = {0, 0, 256, options.game.height}; SDL_FRect rect = {0, 0, 256, Options::game.height};
surface->fillRect(&rect, color); surface->fillRect(&rect, color);
Screen::get()->setRendererSurface(previuos_renderer); Screen::get()->setRendererSurface(previuos_renderer);

View File

@@ -4,24 +4,24 @@
#include <algorithm> // Para max, replace #include <algorithm> // Para max, replace
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAMECANVAS_CENTER_Y #include "core/input/global_inputs.hpp" // Para check
#include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic #include "core/rendering/screen.hpp" // Para Screen
#include "utils/global_events.hpp" // Para check #include "core/rendering/surface.hpp" // Para Surface
#include "core/input/global_inputs.hpp" // Para check
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, Sectio...
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite #include "core/rendering/surface_moving_sprite.hpp" // Para SMovingSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text
#include "core/rendering/text.hpp" // Para Text #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para PaletteColor, stringToColor #include "external/jail_audio.h" // Para JA_SetVolume, JA_PlayMusic, JA_StopMusic
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, Sectio...
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAMECANVAS_CENTER_Y
#include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para PaletteColor, stringToColor
// Constructor // Constructor
Ending2::Ending2() Ending2::Ending2()
: state_(EndingState::PRE_CREDITS, SDL_GetTicks(), STATE_PRE_CREDITS_DURATION_) { : state_(EndingState::PRE_CREDITS, SDL_GetTicks(), STATE_PRE_CREDITS_DURATION_) {
options.section.section = Section::ENDING2; Options::section.section = Options::Scene::ENDING2;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
// Inicializa el vector de colores // Inicializa el vector de colores
const std::vector<std::string> COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"}; const std::vector<std::string> COLORS = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
@@ -146,7 +146,7 @@ void Ending2::checkInput() {
void Ending2::run() { void Ending2::run() {
JA_PlayMusic(Resource::get()->getMusic("ending2.ogg")); JA_PlayMusic(Resource::get()->getMusic("ending2.ogg"));
while (options.section.section == Section::ENDING2) { while (Options::section.section == Options::Scene::ENDING2) {
update(); update();
checkEvents(); checkEvents();
render(); render();
@@ -179,8 +179,8 @@ void Ending2::updateState() {
case EndingState::FADING: case EndingState::FADING:
if (state_.hasEnded(EndingState::FADING)) { if (state_.hasEnded(EndingState::FADING)) {
options.section.section = Section::LOGO; Options::section.section = Options::Scene::LOGO;
options.section.subsection = Subsection::LOGO_TO_INTRO; Options::section.subsection = Options::SceneOptions::LOGO_TO_INTRO;
} }
break; break;
@@ -306,7 +306,7 @@ void Ending2::renderSprites() {
const Uint8 colorA = static_cast<Uint8>(PaletteColor::RED); const Uint8 colorA = static_cast<Uint8>(PaletteColor::RED);
for (auto sprite : sprites_) { for (auto sprite : sprites_) {
const bool A = sprite->getRect().y + sprite->getRect().h > 0; const bool A = sprite->getRect().y + sprite->getRect().h > 0;
const bool B = sprite->getRect().y < options.game.height; const bool B = sprite->getRect().y < Options::game.height;
if (A && B) { if (A && B) {
sprite->render(1, colorA); sprite->render(1, colorA);
} }
@@ -322,7 +322,7 @@ void Ending2::renderSpriteTexts() {
const Uint8 color = static_cast<Uint8>(PaletteColor::WHITE); const Uint8 color = static_cast<Uint8>(PaletteColor::WHITE);
for (auto sprite : sprite_texts_) { for (auto sprite : sprite_texts_) {
const bool A = sprite->getRect().y + sprite->getRect().h > 0; const bool A = sprite->getRect().y + sprite->getRect().h > 0;
const bool B = sprite->getRect().y < options.game.height; const bool B = sprite->getRect().y < Options::game.height;
if (A && B) { if (A && B) {
sprite->render(1, color); sprite->render(1, color);
} }
@@ -333,7 +333,7 @@ void Ending2::renderSpriteTexts() {
void Ending2::renderTexts() { void Ending2::renderTexts() {
for (auto sprite : texts_) { for (auto sprite : texts_) {
const bool A = sprite->getRect().y + sprite->getRect().h > 0; const bool A = sprite->getRect().y + sprite->getRect().h > 0;
const bool B = sprite->getRect().y < options.game.height; const bool B = sprite->getRect().y < Options::game.height;
if (A && B) { if (A && B) {
sprite->render(); sprite->render();
} }
@@ -344,7 +344,7 @@ void Ending2::renderTexts() {
void Ending2::placeSprites() { void Ending2::placeSprites() {
for (int i = 0; i < static_cast<int>(sprites_.size()); ++i) { for (int i = 0; i < static_cast<int>(sprites_.size()); ++i) {
const float X = i % 2 == 0 ? FIRST_COL_ : SECOND_COL_; const float X = i % 2 == 0 ? FIRST_COL_ : SECOND_COL_;
const float Y = (i / 1) * (sprite_max_height_ + DIST_SPRITE_TEXT_ + Resource::get()->getText("smb2")->getCharacterSize() + DIST_SPRITE_SPRITE_) + options.game.height + 40; const float Y = (i / 1) * (sprite_max_height_ + DIST_SPRITE_TEXT_ + Resource::get()->getText("smb2")->getCharacterSize() + DIST_SPRITE_SPRITE_) + Options::game.height + 40;
const float W = sprites_.at(i)->getWidth(); const float W = sprites_.at(i)->getWidth();
const float H = sprites_.at(i)->getHeight(); const float H = sprites_.at(i)->getHeight();
const float DX = -(W / 2); const float DX = -(W / 2);
@@ -355,7 +355,7 @@ void Ending2::placeSprites() {
} }
// Recoloca el sprite del jugador, que es el último de la lista // Recoloca el sprite del jugador, que es el último de la lista
const float X = (options.game.width - sprites_.back()->getWidth()) / 2; const float X = (Options::game.width - sprites_.back()->getWidth()) / 2;
const float Y = sprites_.back()->getPosY() + sprite_max_height_ * 2; const float Y = sprites_.back()->getPosY() + sprite_max_height_ * 2;
sprites_.back()->setPos(X, Y); sprites_.back()->setPos(X, Y);
sprites_.back()->setCurrentAnimation("walk"); sprites_.back()->setCurrentAnimation("walk");
@@ -415,7 +415,7 @@ void Ending2::createTexts() {
const float H = text->getCharacterSize(); const float H = text->getCharacterSize();
const float X = GAMECANVAS_CENTER_X; const float X = GAMECANVAS_CENTER_X;
const float DX = -(W / 2); const float DX = -(W / 2);
const float Y = options.game.height + (text->getCharacterSize() * (i * 2)); const float Y = Options::game.height + (text->getCharacterSize() * (i * 2));
// Crea la surface // Crea la surface
auto surface = std::make_shared<Surface>(W, H); auto surface = std::make_shared<Surface>(W, H);

View File

@@ -6,9 +6,9 @@
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "utils/defines.hpp" // Para GAMECANVAS_WIDTH, GAMECANVAS_FIRST_QUAR... #include "utils/defines.hpp" // Para GAMECANVAS_WIDTH, GAMECANVAS_FIRST_QUAR...
class SAnimatedSprite; // lines 9-9 class SAnimatedSprite; // lines 9-9
class SMovingSprite; // lines 10-10 class SMovingSprite; // lines 10-10
class Ending2 { class Ending2 {
private: private:
@@ -70,8 +70,8 @@ class Ending2 {
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
std::vector<std::string> sprite_list_; // Lista con todos los sprites a dibujar std::vector<std::string> sprite_list_; // Lista con todos los sprites a dibujar
std::vector<Uint8> colors_; // Vector con los colores para el fade std::vector<Uint8> colors_; // Vector con los colores para el fade
float sprite_max_width_ = 0; // El valor de ancho del sprite mas ancho float sprite_max_width_ = 0; // El valor de ancho del sprite mas ancho
float sprite_max_height_ = 0; // El valor de alto del sprite mas alto float sprite_max_height_ = 0; // El valor de alto del sprite mas alto
State state_; // Controla el estado de la clase State state_; // Controla el estado de la clase
// Actualiza el objeto // Actualiza el objeto

View File

@@ -4,30 +4,30 @@
#include <vector> // Para vector #include <vector> // Para vector
#include "core/resources/asset.hpp" // Para Asset #include "core/input/global_inputs.hpp" // Para check
#include "game/gameplay/cheevos.hpp" // Para Cheevos #include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
#include "core/system/debug.hpp" // Para Debug #include "core/rendering/screen.hpp" // Para Screen
#include "utils/defines.hpp" // Para BLOCK, PLAY_AREA_HEIGHT, RoomBorder::BOTTOM #include "core/rendering/surface.hpp" // Para Surface
#include "external/jail_audio.h" // Para JA_PauseMusic, JA_GetMusicState, JA_P... #include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
#include "utils/global_events.hpp" // Para check #include "core/resources/asset.hpp" // Para Asset
#include "core/input/global_inputs.hpp" // Para check #include "core/resources/resource.hpp" // Para ResourceRoom, Resource
#include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT #include "core/system/debug.hpp" // Para Debug
#include "game/gameplay/item_tracker.hpp" // Para ItemTracker #include "external/jail_audio.h" // Para JA_PauseMusic, JA_GetMusicState, JA_P...
#include "game/gameplay/options.hpp" // Para Options, options, Cheat, SectionState #include "game/gameplay/cheevos.hpp" // Para Cheevos
#include "core/resources/resource.hpp" // Para ResourceRoom, Resource #include "game/gameplay/item_tracker.hpp" // Para ItemTracker
#include "game/gameplay/room.hpp" // Para Room, RoomData #include "game/gameplay/options.hpp" // Para Options, options, Cheat, SectionState
#include "game/gameplay/room_tracker.hpp" // Para RoomTracker #include "game/gameplay/room.hpp" // Para Room, RoomData
#include "game/gameplay/scoreboard.hpp" // Para ScoreboardData, Scoreboard #include "game/gameplay/room_tracker.hpp" // Para RoomTracker
#include "core/rendering/screen.hpp" // Para Screen #include "game/gameplay/scoreboard.hpp" // Para ScoreboardData, Scoreboard
#include "game/gameplay/stats.hpp" // Para Stats #include "game/gameplay/stats.hpp" // Para Stats
#include "core/rendering/surface.hpp" // Para Surface #include "game/ui/notifier.hpp" // Para Notifier, NotificationText, CHEEVO_NO...
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR #include "utils/defines.hpp" // Para BLOCK, PLAY_AREA_HEIGHT, RoomBorder::BOTTOM
#include "game/ui/notifier.hpp" // Para Notifier, NotificationText, CHEEVO_NO... #include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para PaletteColor, stringToColor #include "utils/utils.hpp" // Para PaletteColor, stringToColor
// Constructor // Constructor
Game::Game(GameMode mode) Game::Game(GameMode mode)
: board_(std::make_shared<ScoreboardData>(0, 9, 0, true, 0, SDL_GetTicks(), options.cheats.jail_is_open == Cheat::CheatState::ENABLED)), : board_(std::make_shared<ScoreboardData>(0, 9, 0, true, 0, SDL_GetTicks(), Options::cheats.jail_is_open == Options::Cheat::State::ENABLED)),
scoreboard_(std::make_shared<Scoreboard>(board_)), scoreboard_(std::make_shared<Scoreboard>(board_)),
room_tracker_(std::make_shared<RoomTracker>()), room_tracker_(std::make_shared<RoomTracker>()),
stats_(std::make_shared<Stats>(Asset::get()->get("stats.csv"), Asset::get()->get("stats_buffer.csv"))), stats_(std::make_shared<Stats>(Asset::get()->get("stats.csv"), Asset::get()->get("stats_buffer.csv"))),
@@ -55,11 +55,11 @@ Game::Game(GameMode mode)
createRoomNameTexture(); createRoomNameTexture();
changeRoom(current_room_); changeRoom(current_room_);
Cheevos::get()->enable(!options.cheats.enabled()); // Deshabilita los logros si hay trucos activados Cheevos::get()->enable(!Options::cheats.enabled()); // Deshabilita los logros si hay trucos activados
Cheevos::get()->clearUnobtainableState(); Cheevos::get()->clearUnobtainableState();
options.section.section = (mode_ == GameMode::GAME) ? Section::GAME : Section::DEMO; Options::section.section = (mode_ == GameMode::GAME) ? Options::Scene::GAME : Options::Scene::DEMO;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
} }
Game::~Game() { Game::~Game() {
@@ -100,7 +100,7 @@ void Game::run() {
JA_PauseMusic(); JA_PauseMusic();
} }
while (options.section.section == Section::GAME || options.section.section == Section::DEMO) { while (Options::section.section == Options::Scene::GAME || Options::section.section == Options::Scene::DEMO) {
update(); update();
checkEvents(); checkEvents();
render(); render();
@@ -219,7 +219,7 @@ void Game::checkDebugEvents(const SDL_Event& event) {
switch (event.key.key) { switch (event.key.key) {
case SDL_SCANCODE_G: case SDL_SCANCODE_G:
Debug::get()->toggleEnabled(); Debug::get()->toggleEnabled();
options.cheats.invincible = static_cast<Cheat::CheatState>(Debug::get()->getEnabled()); Options::cheats.invincible = static_cast<Options::Cheat::State>(Debug::get()->getEnabled());
board_->music = !Debug::get()->getEnabled(); board_->music = !Debug::get()->getEnabled();
board_->music ? JA_ResumeMusic() : JA_PauseMusic(); board_->music ? JA_ResumeMusic() : JA_PauseMusic();
break; break;
@@ -282,7 +282,7 @@ bool Game::changeRoom(const std::string& room_path) {
if (room_tracker_->addRoom(room_path)) { if (room_tracker_->addRoom(room_path)) {
// Incrementa el contador de habitaciones visitadas // Incrementa el contador de habitaciones visitadas
board_->rooms++; board_->rooms++;
options.stats.rooms = board_->rooms; Options::stats.rooms = board_->rooms;
// Actualiza las estadisticas // Actualiza las estadisticas
stats_->addVisit(room_->getName()); stats_->addVisit(room_->getName());
@@ -335,18 +335,18 @@ void Game::checkIfPlayerIsAlive() {
// Comprueba si ha terminado la partida // Comprueba si ha terminado la partida
void Game::checkGameOver() { void Game::checkGameOver() {
if (board_->lives < 0 && black_screen_counter_ > 17) { if (board_->lives < 0 && black_screen_counter_ > 17) {
options.section.section = Section::GAME_OVER; Options::section.section = Options::Scene::GAME_OVER;
} }
} }
// Mata al jugador // Mata al jugador
void Game::killPlayer() { void Game::killPlayer() {
if (options.cheats.invincible == Cheat::CheatState::ENABLED) { if (Options::cheats.invincible == Options::Cheat::State::ENABLED) {
return; return;
} }
// Resta una vida al jugador // Resta una vida al jugador
if (options.cheats.infinite_lives == Cheat::CheatState::DISABLED) { if (Options::cheats.infinite_lives == Options::Cheat::State::DISABLED) {
--board_->lives; --board_->lives;
} }
@@ -415,9 +415,9 @@ void Game::setScoreBoardColor() {
// Comprueba si ha finalizado el juego // Comprueba si ha finalizado el juego
bool Game::checkEndGame() { bool Game::checkEndGame() {
const bool isOnTheRoom = room_->getName() == "THE JAIL"; // Estar en la habitación que toca const bool isOnTheRoom = room_->getName() == "THE JAIL"; // Estar en la habitación que toca
const bool haveTheItems = board_->items >= int(total_items_ * 0.9f) || options.cheats.jail_is_open == Cheat::CheatState::ENABLED; // Con mas del 90% de los items recogidos const bool haveTheItems = board_->items >= int(total_items_ * 0.9f) || Options::cheats.jail_is_open == Options::Cheat::State::ENABLED; // Con mas del 90% de los items recogidos
const bool isOnTheDoor = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta) const bool isOnTheDoor = player_->getRect().x <= 128; // Y en la ubicación que toca (En la puerta)
if (haveTheItems) { if (haveTheItems) {
board_->jail_is_open = true; board_->jail_is_open = true;
@@ -427,7 +427,7 @@ bool Game::checkEndGame() {
// Comprueba los logros de completar el juego // Comprueba los logros de completar el juego
checkEndGameCheevos(); checkEndGameCheevos();
options.section.section = Section::ENDING; Options::section.section = Options::Scene::ENDING;
return true; return true;
} }
@@ -569,8 +569,8 @@ void Game::checkEndGameCheevos() {
// Inicializa al jugador // Inicializa al jugador
void Game::initPlayer(const PlayerSpawn& spawn_point, std::shared_ptr<Room> room) { void Game::initPlayer(const PlayerSpawn& spawn_point, std::shared_ptr<Room> room) {
std::string player_texture = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.gif" : "player.gif"; std::string player_texture = Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.gif" : "player.gif";
std::string player_animations = options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani"; std::string player_animations = Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.ani" : "player.ani";
const PlayerData player(spawn_point, player_texture, player_animations, room); const PlayerData player(spawn_point, player_texture, player_animations, room);
player_ = std::make_shared<Player>(player); player_ = std::make_shared<Player>(player);
} }
@@ -578,10 +578,10 @@ void Game::initPlayer(const PlayerSpawn& spawn_point, std::shared_ptr<Room> room
// Crea la textura para poner el nombre de la habitación // Crea la textura para poner el nombre de la habitación
void Game::createRoomNameTexture() { void Game::createRoomNameTexture() {
auto text = Resource::get()->getText("smb2"); auto text = Resource::get()->getText("smb2");
room_name_surface_ = std::make_shared<Surface>(options.game.width, text->getCharacterSize() * 2); room_name_surface_ = std::make_shared<Surface>(Options::game.width, text->getCharacterSize() * 2);
// Establece el destino de la textura // Establece el destino de la textura
room_name_rect_ = {0.0F, PLAY_AREA_HEIGHT, options.game.width, text->getCharacterSize() * 2.0F}; room_name_rect_ = {0.0F, PLAY_AREA_HEIGHT, Options::game.width, text->getCharacterSize() * 2.0F};
} }
// Hace sonar la música // Hace sonar la música
@@ -610,8 +610,8 @@ void Game::DEMO_checkRoomChange() {
demo_.counter = 0; demo_.counter = 0;
demo_.room_index++; demo_.room_index++;
if (demo_.room_index == (int)demo_.rooms.size()) { if (demo_.room_index == (int)demo_.rooms.size()) {
options.section.section = Section::LOGO; Options::section.section = Options::Scene::LOGO;
options.section.subsection = Subsection::LOGO_TO_TITLE; Options::section.subsection = Options::SceneOptions::LOGO_TO_TITLE;
} else { } else {
changeRoom(demo_.rooms[demo_.room_index]); changeRoom(demo_.rooms[demo_.room_index]);
} }

View File

@@ -8,10 +8,10 @@
#include <vector> // Para vector #include <vector> // Para vector
#include "game/entities/player.hpp" // Para PlayerSpawn #include "game/entities/player.hpp" // Para PlayerSpawn
class Room; // lines 12-12 class Room; // lines 12-12
class RoomTracker; // lines 13-13 class RoomTracker; // lines 13-13
class Scoreboard; // lines 14-14 class Scoreboard; // lines 14-14
class Stats; // lines 15-15 class Stats; // lines 15-15
class Surface; class Surface;
struct ScoreboardData; // lines 16-16 struct ScoreboardData; // lines 16-16

View File

@@ -5,16 +5,16 @@
#include <algorithm> // Para min, max #include <algorithm> // Para min, max
#include <string> // Para basic_string, operator+, to_string #include <string> // Para basic_string, operator+, to_string
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAME_SPEED #include "core/input/global_inputs.hpp" // Para check
#include "external/jail_audio.h" // Para JA_PlayMusic #include "core/rendering/screen.hpp" // Para Screen
#include "utils/global_events.hpp" // Para check
#include "core/input/global_inputs.hpp" // Para check
#include "game/gameplay/options.hpp" // Para Options, options, OptionsStats, Secti...
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite #include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
#include "core/rendering/text.hpp" // Para TEXT_CENTER, TEXT_COLOR, Text #include "core/rendering/text.hpp" // Para TEXT_CENTER, TEXT_COLOR, Text
#include "utils/utils.hpp" // Para PaletteColor, stringToColor #include "core/resources/resource.hpp" // Para Resource
#include "external/jail_audio.h" // Para JA_PlayMusic
#include "game/gameplay/options.hpp" // Para Options, options, OptionsStats, Secti...
#include "utils/defines.hpp" // Para GAMECANVAS_CENTER_X, GAME_SPEED
#include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para PaletteColor, stringToColor
// Constructor // Constructor
GameOver::GameOver() GameOver::GameOver()
@@ -23,8 +23,8 @@ GameOver::GameOver()
pre_counter_(0), pre_counter_(0),
counter_(0), counter_(0),
ticks_(0) { ticks_(0) {
options.section.section = Section::GAME_OVER; Options::section.section = Options::Scene::GAME_OVER;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
player_sprite_->setPosX(GAMECANVAS_CENTER_X + 10); player_sprite_->setPosX(GAMECANVAS_CENTER_X + 10);
player_sprite_->setPosY(30); player_sprite_->setPosY(30);
@@ -84,14 +84,14 @@ void GameOver::render() {
renderSprites(); renderSprites();
// Escribe el texto con las habitaciones y los items // Escribe el texto con las habitaciones y los items
const std::string ITEMS_TEXT = std::to_string(options.stats.items / 100) + std::to_string((options.stats.items % 100) / 10) + std::to_string(options.stats.items % 10); const std::string ITEMS_TEXT = std::to_string(Options::stats.items / 100) + std::to_string((Options::stats.items % 100) / 10) + std::to_string(Options::stats.items % 10);
const std::string ROOMS_TEXT = std::to_string(options.stats.rooms / 100) + std::to_string((options.stats.rooms % 100) / 10) + std::to_string(options.stats.rooms % 10); const std::string ROOMS_TEXT = std::to_string(Options::stats.rooms / 100) + std::to_string((Options::stats.rooms % 100) / 10) + std::to_string(Options::stats.rooms % 10);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 80, "ITEMS: " + ITEMS_TEXT, 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 80, "ITEMS: " + ITEMS_TEXT, 1, color_);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 90, "ROOMS: " + ROOMS_TEXT, 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 90, "ROOMS: " + ROOMS_TEXT, 1, color_);
// Escribe el texto con "Tu peor pesadilla" // Escribe el texto con "Tu peor pesadilla"
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 110, "YOUR WORST NIGHTMARE IS", 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 110, "YOUR WORST NIGHTMARE IS", 1, color_);
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 120, options.stats.worst_nightmare, 1, color_); text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, Y + 120, Options::stats.worst_nightmare, 1, color_);
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->render(); Screen::get()->render();
@@ -112,7 +112,7 @@ void GameOver::checkInput() {
// Bucle principal // Bucle principal
void GameOver::run() { void GameOver::run() {
while (options.section.section == Section::GAME_OVER) { while (Options::section.section == Options::Scene::GAME_OVER) {
update(); update();
checkEvents(); checkEvents();
render(); render();
@@ -156,7 +156,7 @@ void GameOver::updateCounters() {
// Comprueba si ha terminado la sección // Comprueba si ha terminado la sección
else if (counter_ == COUNTER_SECTION_END_) { else if (counter_ == COUNTER_SECTION_END_) {
options.section.section = Section::LOGO; Options::section.section = Options::Scene::LOGO;
options.section.subsection = Subsection::LOGO_TO_TITLE; Options::section.subsection = Options::SceneOptions::LOGO_TO_TITLE;
} }
} }

View File

@@ -3,16 +3,16 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <stdlib.h> // Para rand #include <stdlib.h> // Para rand
#include "utils/defines.hpp" // Para GAME_SPEED #include "core/input/global_inputs.hpp" // Para check
#include "external/jail_audio.h" // Para JA_PlayMusic, JA_SetVolume, JA_StopMusic #include "core/rendering/screen.hpp" // Para Screen
#include "utils/global_events.hpp" // Para check #include "core/rendering/surface.hpp" // Para Surface
#include "core/input/global_inputs.hpp" // Para check
#include "game/gameplay/options.hpp" // Para Options, options, SectionState, Options...
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para stringToColor, PaletteColor #include "external/jail_audio.h" // Para JA_PlayMusic, JA_SetVolume, JA_StopMusic
#include "game/gameplay/options.hpp" // Para Options, options, SectionState, Options...
#include "utils/defines.hpp" // Para GAME_SPEED
#include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para stringToColor, PaletteColor
// Constructor // Constructor
LoadingScreen::LoadingScreen() LoadingScreen::LoadingScreen()
@@ -20,13 +20,13 @@ LoadingScreen::LoadingScreen()
color_loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")), color_loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")),
mono_loading_screen_sprite_(std::make_shared<SSprite>(mono_loading_screen_surface_, 0, 0, mono_loading_screen_surface_->getWidth(), mono_loading_screen_surface_->getHeight())), mono_loading_screen_sprite_(std::make_shared<SSprite>(mono_loading_screen_surface_, 0, 0, mono_loading_screen_surface_->getWidth(), mono_loading_screen_surface_->getHeight())),
color_loading_screen_sprite_(std::make_shared<SSprite>(color_loading_screen_surface_, 0, 0, color_loading_screen_surface_->getWidth(), color_loading_screen_surface_->getHeight())), color_loading_screen_sprite_(std::make_shared<SSprite>(color_loading_screen_surface_, 0, 0, color_loading_screen_surface_->getWidth(), color_loading_screen_surface_->getHeight())),
screen_surface_(std::make_shared<Surface>(options.game.width, options.game.height)) { screen_surface_(std::make_shared<Surface>(Options::game.width, Options::game.height)) {
// Configura la superficie donde se van a pintar los sprites // Configura la superficie donde se van a pintar los sprites
screen_surface_->clear(static_cast<Uint8>(PaletteColor::WHITE)); screen_surface_->clear(static_cast<Uint8>(PaletteColor::WHITE));
// Inicializa variables // Inicializa variables
options.section.section = Section::LOADING_SCREEN; Options::section.section = Options::Scene::LOADING_SCREEN;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
// Establece el orden de las lineas para imitar el direccionamiento de memoria del spectrum // Establece el orden de las lineas para imitar el direccionamiento de memoria del spectrum
for (int i = 0; i < 192; ++i) { for (int i = 0; i < 192; ++i) {
@@ -96,8 +96,8 @@ void LoadingScreen::updateLoad() {
// Comprueba si ha terminado la intro // Comprueba si ha terminado la intro
if (load_counter_ >= 768) { if (load_counter_ >= 768) {
options.section.section = Section::TITLE; Options::section.section = Options::Scene::TITLE;
options.section.subsection = Subsection::TITLE_WITH_LOADING_SCREEN; Options::section.subsection = Options::SceneOptions::TITLE_WITH_LOADING_SCREEN;
JA_StopMusic(); JA_StopMusic();
} }
} }
@@ -130,8 +130,8 @@ void LoadingScreen::renderBorder() {
// Añade lineas amarillas // Añade lineas amarillas
const Uint8 COLOR = static_cast<Uint8>(PaletteColor::YELLOW); const Uint8 COLOR = static_cast<Uint8>(PaletteColor::YELLOW);
const int WIDTH = options.game.width + (options.video.border.width * 2); const int WIDTH = Options::game.width + (Options::video.border.width * 2);
const int HEIGHT = options.game.height + (options.video.border.height * 2); const int HEIGHT = Options::game.height + (Options::video.border.height * 2);
bool draw_enabled = rand() % 2 == 0 ? true : false; bool draw_enabled = rand() % 2 == 0 ? true : false;
int row = 0; int row = 0;
@@ -162,7 +162,7 @@ void LoadingScreen::update() {
// Dibuja en pantalla // Dibuja en pantalla
void LoadingScreen::render() { void LoadingScreen::render() {
if (options.video.border.enabled) { if (Options::video.border.enabled) {
// Dibuja el efecto de carga en el borde // Dibuja el efecto de carga en el borde
renderBorder(); renderBorder();
} }
@@ -189,7 +189,7 @@ void LoadingScreen::run() {
Screen::get()->clearRenderer(); Screen::get()->clearRenderer();
Screen::get()->render(); Screen::get()->render();
while (options.section.section == Section::LOADING_SCREEN) { while (Options::section.section == Options::Scene::LOADING_SCREEN) {
update(); update();
checkEvents(); checkEvents();
render(); render();

View File

@@ -2,15 +2,15 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include "utils/defines.hpp" // Para GAME_SPEED #include "core/input/global_inputs.hpp" // Para check
#include "utils/global_events.hpp" // Para check #include "core/rendering/screen.hpp" // Para Screen
#include "core/input/global_inputs.hpp" // Para check #include "core/rendering/surface.hpp" // Para Surface
#include "game/gameplay/options.hpp" // Para Options, SectionState, options, Section
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para PaletteColor #include "game/gameplay/options.hpp" // Para Options, SectionState, options, Section
#include "utils/defines.hpp" // Para GAME_SPEED
#include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para PaletteColor
// Constructor // Constructor
Logo::Logo() Logo::Logo()
@@ -30,7 +30,7 @@ Logo::Logo()
} }
// Inicializa variables // Inicializa variables
options.section.section = Section::LOGO; Options::section.section = Options::Scene::LOGO;
// Inicializa el vector de colores // Inicializa el vector de colores
const std::vector<Uint8> COLORS = { const std::vector<Uint8> COLORS = {
@@ -206,7 +206,7 @@ void Logo::render() {
// Bucle para el logo del juego // Bucle para el logo del juego
void Logo::run() { void Logo::run() {
while (options.section.section == Section::LOGO) { while (Options::section.section == Options::Scene::LOGO) {
update(); update();
checkEvents(); checkEvents();
render(); render();
@@ -215,11 +215,11 @@ void Logo::run() {
// Termina la sección // Termina la sección
void Logo::endSection() { void Logo::endSection() {
if (options.section.subsection == Subsection::LOGO_TO_TITLE) { if (Options::section.subsection == Options::SceneOptions::LOGO_TO_TITLE) {
options.section.section = Section::TITLE; Options::section.section = Options::Scene::TITLE;
} }
else if (options.section.subsection == Subsection::LOGO_TO_INTRO) { else if (Options::section.subsection == Options::SceneOptions::LOGO_TO_INTRO) {
options.section.section = Section::LOADING_SCREEN; Options::section.section = Options::Scene::LOADING_SCREEN;
} }
} }

View File

@@ -4,18 +4,18 @@
#include <algorithm> // Para clamp #include <algorithm> // Para clamp
#include "game/gameplay/cheevos.hpp" // Para Cheevos, Achievement #include "core/input/global_inputs.hpp" // Para check
#include "utils/defines.hpp" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH #include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT, REP...
#include "utils/global_events.hpp" // Para check #include "core/rendering/screen.hpp" // Para Screen
#include "core/input/global_inputs.hpp" // Para check #include "core/rendering/surface.hpp" // Para Surface
#include "core/input/input.hpp" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT, REP...
#include "game/gameplay/options.hpp" // Para Options, options, SectionState, Section
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para stringToColor, PaletteColor, playMusic #include "game/gameplay/cheevos.hpp" // Para Cheevos, Achievement
#include "game/gameplay/options.hpp" // Para Options, options, SectionState, Section
#include "utils/defines.hpp" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
#include "utils/global_events.hpp" // Para check
#include "utils/utils.hpp" // Para stringToColor, PaletteColor, playMusic
// Constructor // Constructor
Title::Title() Title::Title()
@@ -23,11 +23,11 @@ Title::Title()
title_logo_sprite_(std::make_shared<SSprite>(title_logo_surface_, 29, 9, title_logo_surface_->getWidth(), title_logo_surface_->getHeight())), title_logo_sprite_(std::make_shared<SSprite>(title_logo_surface_, 29, 9, title_logo_surface_->getWidth(), title_logo_surface_->getHeight())),
loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")), loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")),
loading_screen_sprite_(std::make_shared<SSprite>(loading_screen_surface_, 0, 0, loading_screen_surface_->getWidth(), loading_screen_surface_->getHeight())), loading_screen_sprite_(std::make_shared<SSprite>(loading_screen_surface_, 0, 0, loading_screen_surface_->getWidth(), loading_screen_surface_->getHeight())),
bg_surface_(std::make_shared<Surface>(options.game.width, options.game.height)) { bg_surface_(std::make_shared<Surface>(Options::game.width, Options::game.height)) {
// Inicializa variables // Inicializa variables
state_ = options.section.subsection == Subsection::TITLE_WITH_LOADING_SCREEN ? TitleState::SHOW_LOADING_SCREEN : TitleState::SHOW_MENU; state_ = Options::section.subsection == Options::SceneOptions::TITLE_WITH_LOADING_SCREEN ? TitleState::SHOW_LOADING_SCREEN : TitleState::SHOW_MENU;
options.section.section = Section::TITLE; Options::section.section = Options::Scene::TITLE;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
initMarquee(); initMarquee();
// Crea y rellena la textura para mostrar los logros // Crea y rellena la textura para mostrar los logros
@@ -68,8 +68,8 @@ void Title::checkEvents() {
if (!show_cheevos_) { if (!show_cheevos_) {
switch (event.key.key) { switch (event.key.key) {
case SDLK_1: case SDLK_1:
options.section.section = Section::GAME; Options::section.section = Options::Scene::GAME;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
break; break;
case SDLK_2: case SDLK_2:
@@ -180,8 +180,8 @@ void Title::update() {
// Si el contador alcanza cierto valor, termina la seccion // Si el contador alcanza cierto valor, termina la seccion
if (counter_ == 2200) { if (counter_ == 2200) {
if (!show_cheevos_) { if (!show_cheevos_) {
options.section.section = Section::CREDITS; Options::section.section = Options::Scene::CREDITS;
options.section.subsection = Subsection::NONE; Options::section.subsection = Options::SceneOptions::NONE;
} }
} }
break; break;
@@ -228,7 +228,7 @@ void Title::render() {
// Bucle para el logo del juego // Bucle para el logo del juego
void Title::run() { void Title::run() {
while (options.section.section == Section::TITLE) { while (Options::section.section == Options::Scene::TITLE) {
update(); update();
checkEvents(); checkEvents();
render(); render();

View File

@@ -7,14 +7,14 @@
#include <string> // Para string, basic_string #include <string> // Para string, basic_string
#include <vector> // Para vector #include <vector> // Para vector
#include "external/jail_audio.h" // Para JA_PlaySound #include "core/rendering/screen.hpp" // Para Screen
#include "game/gameplay/options.hpp" // Para Options, options, NotificationPosition #include "core/rendering/surface.hpp" // Para Surface
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_sprite.hpp" // Para SSprite #include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR #include "core/resources/resource.hpp" // Para Resource
#include "utils/utils.hpp" // Para PaletteColor #include "external/jail_audio.h" // Para JA_PlaySound
#include "game/gameplay/options.hpp" // Para Options, options, NotificationPosition
#include "utils/utils.hpp" // Para PaletteColor
// [SINGLETON] // [SINGLETON]
Notifier* Notifier::notifier_ = nullptr; Notifier* Notifier::notifier_ = nullptr;
@@ -38,7 +38,7 @@ Notifier* Notifier::get() {
Notifier::Notifier(const std::string& icon_file, const std::string& text) Notifier::Notifier(const std::string& icon_file, const std::string& text)
: icon_surface_(!icon_file.empty() ? Resource::get()->getSurface(icon_file) : nullptr), : icon_surface_(!icon_file.empty() ? Resource::get()->getSurface(icon_file) : nullptr),
text_(Resource::get()->getText(text)), text_(Resource::get()->getText(text)),
bg_color_(options.notifications.color), bg_color_(Options::notifications.color),
stack_(false), stack_(false),
has_icons_(!icon_file.empty()) {} has_icons_(!icon_file.empty()) {}
@@ -62,7 +62,7 @@ void Notifier::update() {
switch (notification.state) { switch (notification.state) {
case NotificationStatus::RISING: { case NotificationStatus::RISING: {
const int DIRECTION = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? 1 : -1; const int DIRECTION = (Options::notifications.getVerticalPosition() == Options::NotificationPosition::TOP) ? 1 : -1;
notification.rect.y += DIRECTION; notification.rect.y += DIRECTION;
if (notification.rect.y == notification.y) { if (notification.rect.y == notification.y) {
@@ -80,7 +80,7 @@ void Notifier::update() {
} }
case NotificationStatus::VANISHING: { case NotificationStatus::VANISHING: {
const int DIRECTION = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? -1 : 1; const int DIRECTION = (Options::notifications.getVerticalPosition() == Options::NotificationPosition::TOP) ? -1 : 1;
notification.rect.y += DIRECTION; notification.rect.y += DIRECTION;
if (notification.rect.y == notification.y - notification.travel_dist) { if (notification.rect.y == notification.y - notification.travel_dist) {
@@ -140,23 +140,23 @@ void Notifier::show(std::vector<std::string> texts, NotificationText text_is, Ui
const auto PADDING_IN_V = text_size / 2; const auto PADDING_IN_V = text_size / 2;
const int ICON_SPACE = icon >= 0 ? ICON_SIZE_ + PADDING_IN_H : 0; const int ICON_SPACE = icon >= 0 ? ICON_SIZE_ + PADDING_IN_H : 0;
text_is = ICON_SPACE > 0 ? NotificationText::LEFT : text_is; text_is = ICON_SPACE > 0 ? NotificationText::LEFT : text_is;
const float WIDTH = options.game.width - (PADDING_OUT_ * 2); const float WIDTH = Options::game.width - (PADDING_OUT_ * 2);
const float HEIGHT = (text_size * texts.size()) + (PADDING_IN_V * 2); const float HEIGHT = (text_size * texts.size()) + (PADDING_IN_V * 2);
const auto SHAPE = NotificationShape::SQUARED; const auto SHAPE = NotificationShape::SQUARED;
// Posición horizontal // Posición horizontal
float desp_h = 0; float desp_h = 0;
switch (options.notifications.getHorizontalPosition()) { switch (Options::notifications.getHorizontalPosition()) {
case NotificationPosition::LEFT: case Options::NotificationPosition::LEFT:
desp_h = PADDING_OUT_; desp_h = PADDING_OUT_;
break; break;
case NotificationPosition::CENTER: case Options::NotificationPosition::CENTER:
desp_h = ((options.game.width / 2) - (WIDTH / 2)); desp_h = ((Options::game.width / 2) - (WIDTH / 2));
break; break;
case NotificationPosition::RIGHT: case Options::NotificationPosition::RIGHT:
desp_h = options.game.width - WIDTH - PADDING_OUT_; desp_h = Options::game.width - WIDTH - PADDING_OUT_;
break; break;
default: default:
@@ -165,11 +165,11 @@ void Notifier::show(std::vector<std::string> texts, NotificationText text_is, Ui
} }
// Posición vertical // Posición vertical
const int DESP_V = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? PADDING_OUT_ : options.game.height - HEIGHT - PADDING_OUT_; const int DESP_V = (Options::notifications.getVerticalPosition() == Options::NotificationPosition::TOP) ? PADDING_OUT_ : Options::game.height - HEIGHT - PADDING_OUT_;
// Offset // Offset
const auto TRAVEL_DIST = HEIGHT + PADDING_OUT_; const auto TRAVEL_DIST = HEIGHT + PADDING_OUT_;
const int TRAVEL_MOD = (options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? 1 : -1; const int TRAVEL_MOD = (Options::notifications.getVerticalPosition() == Options::NotificationPosition::TOP) ? 1 : -1;
const int OFFSET = !notifications_.empty() ? notifications_.back().y + TRAVEL_MOD * notifications_.back().travel_dist : DESP_V; const int OFFSET = !notifications_.empty() ? notifications_.back().y + TRAVEL_MOD * notifications_.back().travel_dist : DESP_V;
// Crea la notificacion // Crea la notificacion
@@ -183,7 +183,7 @@ void Notifier::show(std::vector<std::string> texts, NotificationText text_is, Ui
n.texts = texts; n.texts = texts;
n.shape = SHAPE; n.shape = SHAPE;
n.display_duration = display_duration; n.display_duration = display_duration;
const float Y_POS = OFFSET + ((options.notifications.getVerticalPosition() == NotificationPosition::TOP) ? -TRAVEL_DIST : TRAVEL_DIST); const float Y_POS = OFFSET + ((Options::notifications.getVerticalPosition() == Options::NotificationPosition::TOP) ? -TRAVEL_DIST : TRAVEL_DIST);
n.rect = {desp_h, Y_POS, WIDTH, HEIGHT}; n.rect = {desp_h, Y_POS, WIDTH, HEIGHT};
// Crea la textura // Crea la textura

View File

@@ -6,13 +6,13 @@ Empezado en Castalla el 01/07/2022.
*/ */
#include <memory> #include <memory>
#include "core/system/director.hpp" #include "core/system/director.hpp"
int main(int argc, char *argv[]) int main(int argc, char* argv[]) {
{ // Crea el objeto Director
// Crea el objeto Director auto director = std::make_unique<Director>(argc, const_cast<const char**>(argv));
auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv));
// Bucle principal // Bucle principal
return director->run(); return director->run();
} }

View File

@@ -1,24 +1,21 @@
#include "utils/global_events.hpp" #include "utils/global_events.hpp"
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, OptionsAudio
#include "core/input/mouse.hpp" #include "core/input/mouse.hpp"
#include "game/gameplay/options.hpp" // Para Options, options, OptionsGame, OptionsAudio
namespace globalEvents namespace globalEvents {
{ // Comprueba los eventos que se pueden producir en cualquier sección del juego
// Comprueba los eventos que se pueden producir en cualquier sección del juego void check(const SDL_Event& event) {
void check(const SDL_Event &event) // Evento de salida de la aplicación
{ if (event.type == SDL_EVENT_QUIT) {
// Evento de salida de la aplicación Options::section.section = Options::Scene::QUIT;
if (event.type == SDL_EVENT_QUIT) return;
{
options.section.section = Section::QUIT;
return;
}
if (event.type == SDL_EVENT_RENDER_DEVICE_RESET || event.type == SDL_EVENT_RENDER_TARGETS_RESET)
{
// reLoadTextures();
}
Mouse::handleEvent(event);
} }
}
if (event.type == SDL_EVENT_RENDER_DEVICE_RESET || event.type == SDL_EVENT_RENDER_TARGETS_RESET) {
// reLoadTextures();
}
Mouse::handleEvent(event);
}
} // namespace globalEvents

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
namespace globalEvents { namespace globalEvents {
// Comprueba los eventos que se pueden producir en cualquier sección del juego // Comprueba los eventos que se pueden producir en cualquier sección del juego

View File

@@ -12,8 +12,8 @@
#include <unordered_map> // Para unordered_map, operator==, _Node_const_iter... #include <unordered_map> // Para unordered_map, operator==, _Node_const_iter...
#include <utility> // Para pair #include <utility> // Para pair
#include "external/jail_audio.h" // Para JA_GetMusicState, JA_Music_state, JA_PlayMusic #include "core/resources/resource.hpp" // Para Resource
#include "core/resources/resource.hpp" // Para Resource #include "external/jail_audio.h" // Para JA_GetMusicState, JA_Music_state, JA_PlayMusic
// Calcula el cuadrado de la distancia entre dos puntos // Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2) { double distanceSquared(int x1, int y1, int x2, int y2) {

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
namespace Version { namespace Version {
constexpr const char* GIT_HASH = "@GIT_HASH@"; constexpr const char* GIT_HASH = "@GIT_HASH@";
constexpr const char* APP_NAME = "Coffee Crisis Arcade Edition"; constexpr const char* APP_NAME = "Coffee Crisis Arcade Edition";
} } // namespace Version