#pragma once #include // for Uint32 #include // for string, basic_string #include "screen.h" // for ScreenFilter #include "utils.h" // for Color, Palette #include // Secciones del programa enum class Section { LOGO, LOADING_SCREEN, TITLE, CREDITS, GAME, DEMO, GAME_OVER, ENDING, ENDING2, QUIT }; // Subsecciones enum class Subsection { NONE, LOGO_TO_INTRO, LOGO_TO_TITLE, TITLE_WITH_LOADING_SCREEN, TITLE_WITHOUT_LOADING_SCREEN }; // Posiciones de las notificaciones enum class NotificationPosition { UPPER_LEFT, UPPER_CENTER, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT, TOP, BOTTOM, LEFT, RIGHT, CENTER, UNKNOWN, }; // Tipos de control de teclado enum class ControlScheme { CURSOR, OPQA, WASD }; // Constantes constexpr int DEFAULT_GAME_WIDTH = 256; // Ancho de la ventana por defecto constexpr int DEFAULT_GAME_HEIGHT = 192; // Alto de la ventana por defecto constexpr int DEFAULT_WINDOW_ZOOM = 2; // Zoom de la ventana por defecto constexpr int DEFAULT_VIDEO_MODE = 0; // Modo de pantalla completa por defecto constexpr ScreenFilter DEFAULT_VIDEO_FILTER = ScreenFilter::NEAREST; // Filtro por defecto 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 Palette DEFAULT_PALETTE = Palette::ZXSPECTRUM; // 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 Color DEFAULT_NOTIFICATION_COLOR = Color(48, 48, 48); // Color de las notificaciones por defecto constexpr bool DEFAULT_CONSOLE = false; // Consola desactivada por defecto constexpr const char *DEFAULT_VERSION = "1.09"; // Versión por defecto // Estructura para las opciones de las notificaciones struct OptionsNotification { NotificationPosition pos; // Ubicación de las notificaciones en pantalla bool sound; // Indica si las notificaciones suenan Color color; // Color de las notificaciones // Constructor por defecto OptionsNotification() : pos(DEFAULT_NOTIFICATION_POSITION), sound(DEFAULT_NOTIFICATION_SOUND), color(DEFAULT_NOTIFICATION_COLOR) {} // Constructor OptionsNotification(NotificationPosition p, bool s, Color c) : pos(p), sound(s), color(c) {} // Método que devuelve la posición horizontal NotificationPosition getHorizontalPosition() const { switch (pos) { case NotificationPosition::UPPER_LEFT: case NotificationPosition::BOTTOM_LEFT: return NotificationPosition::LEFT; case NotificationPosition::UPPER_CENTER: case NotificationPosition::BOTTOM_CENTER: return NotificationPosition::CENTER; case NotificationPosition::UPPER_RIGHT: case NotificationPosition::BOTTOM_RIGHT: return NotificationPosition::RIGHT; default: return NotificationPosition::UNKNOWN; } return NotificationPosition::UNKNOWN; } // Método que devuelve la posición vertical NotificationPosition getVerticalPosition() const { switch (pos) { case NotificationPosition::UPPER_LEFT: case NotificationPosition::UPPER_CENTER: case NotificationPosition::UPPER_RIGHT: return NotificationPosition::TOP; case NotificationPosition::BOTTOM_LEFT: case NotificationPosition::BOTTOM_CENTER: case NotificationPosition::BOTTOM_RIGHT: return NotificationPosition::BOTTOM; default: return NotificationPosition::UNKNOWN; } return NotificationPosition::UNKNOWN; } }; // Estructura para saber la seccion y subseccion del programa struct SectionState { Section section; Subsection subsection; // Constructor por defecto SectionState() : section(DEFAULT_SECTION), subsection(DEFAULT_SUBSECTION) {} // Constructor SectionState(Section s, Subsection ss) : section(s), subsection(ss) {} }; // Estructura para albergar trucos struct Cheat { enum class CheatState : bool { DISABLED = false, ENABLED = true }; CheatState infinite_lives; // Indica si el jugador dispone de vidas infinitas CheatState invincible; // Indica si el jugador puede morir CheatState jail_is_open; // Indica si la Jail está abierta CheatState alternate_skin; // Indica si se usa una skin diferente para el jugador // Constructor por defecto Cheat() : infinite_lives(CheatState::DISABLED), invincible(CheatState::DISABLED), jail_is_open(CheatState::DISABLED), alternate_skin(CheatState::DISABLED) {} // Constructor Cheat(CheatState il, CheatState i, CheatState je, CheatState as) : infinite_lives(il), invincible(i), jail_is_open(je), alternate_skin(as) {} // Método para comprobar si alguno de los tres primeros trucos está activo bool enabled() const { return infinite_lives == CheatState::ENABLED || invincible == CheatState::ENABLED || jail_is_open == CheatState::ENABLED; } }; // Estructura para almacenar estadísticas struct OptionsStats { int rooms; // Cantidad de habitaciones visitadas int items; // Cantidad de items obtenidos std::string worst_nightmare; // Habitación con más muertes acumuladas // Constructor por defecto OptionsStats() : rooms(0), items(0), worst_nightmare("") {} // Constructor OptionsStats(int r, int i, std::string wn) : rooms(r), items(i), worst_nightmare(wn) {} }; // Estructura con opciones de la ventana struct OptionsWindow { int zoom; // Zoom de la ventana int max_zoom; // Máximo tamaño de zoom para la ventana // Constructor por defecto OptionsWindow() : zoom(DEFAULT_WINDOW_ZOOM), max_zoom(DEFAULT_WINDOW_ZOOM) {} // Constructor OptionsWindow(int z, int mz) : zoom(z), max_zoom(mz) {} }; // Estructura para gestionar el borde de la pantalla struct Border { bool enabled; // Indica si se ha de mostrar el borde int width; // Ancho del borde int height; // Alto del borde // Constructor por defecto Border() : enabled(DEFAULT_BORDER_ENABLED), width(DEFAULT_BORDER_WIDTH), height(DEFAULT_BORDER_HEIGHT) {} // Constructor Border(bool e, int w, int h) : enabled(e), width(w), height(h) {} }; // Estructura para las opciones de video struct OptionsVideo { Uint32 mode; // Contiene el valor del modo de pantalla completa ScreenFilter filter; // Filtro usado para el escalado de la imagen bool vertical_sync; // Indica si se quiere usar vsync o no bool shaders; // Indica si se van a usar shaders o no bool integer_scale; // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa bool keep_aspect; // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa Border border; // Borde de la pantalla Palette palette; // Paleta de colores a usar en el juego // Constructor por defecto OptionsVideo() : mode(DEFAULT_VIDEO_MODE), filter(DEFAULT_VIDEO_FILTER), vertical_sync(DEFAULT_VIDEO_VERTICAL_SYNC), shaders(DEFAULT_VIDEO_SHADERS), integer_scale(DEFAULT_VIDEO_INTEGER_SCALE), keep_aspect(DEFAULT_VIDEO_KEEP_ASPECT), border(Border()), palette(DEFAULT_PALETTE) {} // Constructor OptionsVideo(Uint32 m, ScreenFilter f, bool vs, bool s, bool is, bool ka, Border b, Palette p) : mode(m), filter(f), vertical_sync(vs), shaders(s), integer_scale(is), keep_aspect(ka), border(b), palette(p) {} }; // Estructura para las opciones de musica struct OptionsMusic { bool enabled; // Indica si la música suena o no int volume; // Volumen al que suena la música (0 a 128 internamente) // Constructor por defecto OptionsMusic() : enabled(DEFAULT_MUSIC_ENABLED), volume(convertVolume(DEFAULT_MUSIC_VOLUME)) {} // Usa el método estático para la conversión // Constructor con parámetros OptionsMusic(bool e, int v) : enabled(e), volume(convertVolume(v)) {} // Convierte el volumen usando el método estático // Método para establecer el volumen void setVolume(int v) { v = std::clamp(v, 0, 100); // Ajusta v al rango [0, 100] volume = convertVolume(v); // Convierte al rango interno } // 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 struct OptionsSound { bool enabled; // Indica si los sonidos suenan o no int volume; // Volumen al que suenan los sonidos (0 a 128 internamente) // Constructor por defecto OptionsSound() : enabled(DEFAULT_SOUND_ENABLED), volume(convertVolume(DEFAULT_SOUND_VOLUME)) {} // Usa el método estático para la conversión // Constructor con parámetros OptionsSound(bool e, int v) : enabled(e), volume(convertVolume(v)) {} // También lo integra aquí // Método para establecer el volumen void setVolume(int v) { v = std::clamp(v, 0, 100); // Ajusta v al rango [0, 100] volume = convertVolume(v); // Convierte al rango interno } // 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 struct OptionsAudio { OptionsMusic music; // Opciones para la música OptionsSound sound; // Opciones para los efectos de sonido bool enabled; // Indica si el audio está activo o no int volume; // Volumen al que suenan el audio // Constructor por defecto OptionsAudio() : music(OptionsMusic()), sound(OptionsSound()), enabled(DEFAULT_AUDIO_ENABLED), volume(DEFAULT_AUDIO_VOLUME) {} // Constructor OptionsAudio(OptionsMusic m, OptionsSound s, bool e, int v) : music(m), sound(s), enabled(e), volume(v) {} }; // Estructura para las opciones de juego struct OptionsGame { int width; // Ancho de la resolucion del juego int height; // Alto de la resolucion del juego // Constructor por defecto OptionsGame() : width(DEFAULT_GAME_WIDTH), height(DEFAULT_GAME_HEIGHT) {} // Constructor OptionsGame(int w, int h) : width(w), height(h) {} }; // Estructura con todas las opciones de configuración del programa struct Options { 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 OptionsGame game; // Opciones de juego OptionsVideo video; // Opciones de video OptionsStats stats; // Datos con las estadisticas de juego OptionsNotification notifications; // Opciones relativas a las notificaciones; OptionsWindow window; // Opciones relativas a la ventana OptionsAudio audio; // Opciones relativas al audio ControlScheme keys; // Teclas usadas para jugar SectionState section; // Sección actual del programa // Constructor por defecto Options() : version(DEFAULT_VERSION), console(DEFAULT_CONSOLE), cheats(Cheat()), game(OptionsGame()), video(OptionsVideo()), stats(OptionsStats()), notifications(OptionsNotification()), window(OptionsWindow()), audio(OptionsAudio()), keys(DEFAULT_CONTROL_SCHEME), section(SectionState()) {} // Constructor 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);