From c6288918b243fcc6100fcd972299c97ba2196a30 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Thu, 27 Mar 2025 18:34:04 +0100 Subject: [PATCH] ja funciona el audio --- source/director.cpp | 111 +++---------------------- source/director.h | 6 +- source/global_inputs.cpp | 4 +- source/input.cpp | 25 ++++-- source/input.h | 2 + source/jail_audio.cpp | 27 ++++-- source/options.cpp | 26 +++--- source/options.h | 19 +++-- source/screen.cpp | 174 +++++++++++++++++++++++++++++++-------- source/screen.h | 11 ++- 10 files changed, 221 insertions(+), 184 deletions(-) diff --git a/source/director.cpp b/source/director.cpp index c4d6135..70d77a6 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -98,11 +98,9 @@ void Director::init() loadScoreFile(); // Carga el fichero de puntuaciones // Inicializa y crea el resto de objetos - initSDL(); - SDL_HideCursor(); - initJailAudio(); lang::loadFromFile(getLangFile(static_cast(options.game.language))); - Screen::init(window_, renderer_); + Screen::init(); + initJailAudio(); Resource::init(); Input::init(Asset::get()->get("gamecontrollerdb.txt")); bindInputs(); @@ -124,9 +122,6 @@ void Director::close() JA_Quit(); - SDL_DestroyRenderer(renderer_); - SDL_DestroyWindow(window_); - SDL_Quit(); #ifdef ARCADE @@ -267,109 +262,27 @@ void Director::bindInputs() // Inicializa JailAudio void Director::initJailAudio() { - JA_Init(48000, SDL_AUDIO_S16LE, 2); - if (options.audio.enabled) - { - JA_SetMusicVolume(to_JA_volume(options.audio.music.volume)); - JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume)); - } - else - { - JA_SetMusicVolume(0); - JA_SetSoundVolume(0); - } -} - -// Arranca SDL y crea la ventana -bool Director::initSDL() -{ - // Indicador de éxito - auto success = true; - // Inicializa SDL - if (!SDL_Init(SDL_INIT_VIDEO || SDL_INIT_AUDIO || SDL_INIT_GAMEPAD)) + if (!SDL_Init(SDL_INIT_AUDIO)) { - std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl; - success = false; + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError()); } else { - // Obtiene información sobre la pantalla - int i, num_displays = 0; - SDL_DisplayID *displays = SDL_GetDisplays(&num_displays); - if (displays) + JA_Init(48000, SDL_AUDIO_S16LE, 2); + if (options.audio.enabled) { - for (i = 0; i < num_displays; ++i) - { - SDL_DisplayID instance_id = displays[i]; - const char *name = SDL_GetDisplayName(instance_id); - - SDL_Log("Display %" SDL_PRIu32 ": %s", instance_id, name ? name : "Unknown"); - } - - auto DM = SDL_GetCurrentDisplayMode(displays[0]); - - // Calcula el máximo factor de zoom que se puede aplicar a la pantalla - options.video.window.max_zoom = std::min(DM->w / param.game.width, DM->h / param.game.height); - options.video.window.zoom = std::min(options.video.window.zoom, options.video.window.max_zoom); - - // Muestra información sobre el tamaño de la pantalla y de la ventana de juego - std::cout << "\nCurrent display mode: " << DM->w << "x" << DM->h << " @ " << DM->refresh_rate << "Hz" << std::endl; - std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.zoom << std::endl; - options.video.info = std::to_string(DM->w) + " X " + std::to_string(DM->h) + " AT " + std::to_string(DM->refresh_rate) + " HZ"; - - SDL_free(displays); - } - - // Establece el filtro de la textura - /*if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast(options.video.filter)).c_str())) - { - std::cout << "Warning: texture filtering not enabled!\n"; - }*/ - - if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) - { - std::cout << "Warning: opengl not enabled!\n"; - } - - // Crea la ventana - window_ = SDL_CreateWindow(WINDOW_CAPTION, param.game.width * options.video.window.zoom, param.game.height * options.video.window.zoom, SDL_WINDOW_OPENGL); - if (!window_) - { - std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl; - success = false; + JA_SetMusicVolume(to_JA_volume(options.audio.music.volume)); + JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume)); } else { - // Crea un renderizador para la ventana. El vsync se activa en funcion de las opciones - // Uint32 flags = 0; - if (options.video.v_sync) - { - // flags = SDL_RENDERER_PRESENTVSYNC; - } - - // La aceleración se activa según el define - // flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE; - - renderer_ = SDL_CreateRenderer(window_, nullptr); - - if (!renderer_) - { - std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl; - success = false; - } - else - { - SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF); - SDL_SetRenderLogicalPresentation(renderer_, param.game.width, param.game.height, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); - SDL_SetWindowFullscreen(window_, static_cast(options.video.fullscreen)); - SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); - } + JA_SetMusicVolume(0); + JA_SetSoundVolume(0); } - } - std::cout << std::endl; - return success; + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO: Initialization complete."); + } } // Crea el indice de ficheros diff --git a/source/director.h b/source/director.h index 57e5cda..d4f39ab 100644 --- a/source/director.h +++ b/source/director.h @@ -15,8 +15,7 @@ class Director { private: // Objetos y punteros - SDL_Window *window_; // La ventana donde dibujamos - SDL_Renderer *renderer_; // El renderizador de la ventana + #ifndef VERBOSE std::streambuf *orig_buf; // Puntero al buffer de flujo original para restaurar std::cout #endif @@ -28,9 +27,6 @@ private: // Inicializa jail_audio void initJailAudio(); - // Arranca SDL y crea la ventana - bool initSDL(); - // Asigna los botones y teclas al objeto Input void bindInputs(); diff --git a/source/global_inputs.cpp b/source/global_inputs.cpp index 2279085..c611677 100644 --- a/source/global_inputs.cpp +++ b/source/global_inputs.cpp @@ -191,7 +191,7 @@ namespace globalInputs { if (Screen::get()->decWindowZoom()) { - Notifier::get()->show({lang::getText(131) + " x" + std::to_string(options.video.window.zoom)}); + Notifier::get()->show({lang::getText(131) + " x" + std::to_string(options.window.zoom)}); } return; } @@ -201,7 +201,7 @@ namespace globalInputs { if (Screen::get()->incWindowZoom()) { - Notifier::get()->show({lang::getText(131) + " x" + std::to_string(options.video.window.zoom)}); + Notifier::get()->show({lang::getText(131) + " x" + std::to_string(options.window.zoom)}); } return; } diff --git a/source/input.cpp b/source/input.cpp index fae043a..337f75f 100644 --- a/source/input.cpp +++ b/source/input.cpp @@ -1,5 +1,5 @@ #include "input.h" -#include // Para SDL_GetError +#include // Para SDL_GetError #include // Para SDL_INIT_GAMEPAD, SDL_InitSubSystem #include // Para SDL_GetKeyboardState #include // Para find @@ -33,6 +33,9 @@ Input *Input::get() Input::Input(const std::string &game_controller_db_path) : game_controller_db_path_(game_controller_db_path) { + // Inicializa el subsistema SDL_INIT_GAMEPAD + initSDL(); + // Busca si hay mandos conectados discoverGameControllers(); @@ -221,11 +224,6 @@ bool Input::discoverGameControllers() { bool found = false; - if (SDL_WasInit(SDL_INIT_GAMEPAD) != 1) - { - SDL_InitSubSystem(SDL_INIT_GAMEPAD); - } - if (SDL_AddGamepadMappingsFromFile(game_controller_db_path_.c_str()) < 0) { std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl; @@ -430,4 +428,19 @@ bool Input::checkAxisInput(InputAction input, int controller_index, bool repeat) // Mantener el estado actual return false; } +} + +void Input::initSDL() +{ + if (SDL_WasInit(SDL_INIT_GAMEPAD) != 1) + { + if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD)) + { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GAMEPAD could not initialize! SDL Error: %s", SDL_GetError()); + } + else + { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_GAMEPAD: Initialization complete."); + } + } } \ No newline at end of file diff --git a/source/input.h b/source/input.h index 69771eb..62fb091 100644 --- a/source/input.h +++ b/source/input.h @@ -100,6 +100,8 @@ private: int num_gamepads_ = 0; // Número de mandos conectados std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt + void initSDL(); + // Comprueba el eje del mando bool checkAxisInput(InputAction input, int controller_index, bool repeat); diff --git a/source/jail_audio.cpp b/source/jail_audio.cpp index c621419..23c3ffe 100644 --- a/source/jail_audio.cpp +++ b/source/jail_audio.cpp @@ -97,6 +97,7 @@ Uint32 JA_UpdateCallback(void *userdata, SDL_TimerID timerID, Uint32 interval) if (time > (fade_start_time+fade_duration)) { fading = false; JA_StopMusic(); + return 30; } else { const int time_passed = time - fade_start_time; const float percent = (float)time_passed / (float)fade_duration; @@ -150,7 +151,7 @@ void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice); sdlAudioDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &JA_audioSpec); SDL_Log( (sdlAudioDevice==0) ? "Failed to initialize SDL audio!\n" : "OK!\n"); - SDL_PauseAudioDevice(sdlAudioDevice); + //SDL_PauseAudioDevice(sdlAudioDevice); JA_timerID = SDL_AddTimer(30, JA_UpdateCallback, nullptr); } @@ -215,7 +216,7 @@ void JA_PlayMusic(JA_Music_t *music, const int loop) if (!SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length)) printf("[ERROR] SDL_PutAudioStreamData failed!\n"); SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume); if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n"); - SDL_ResumeAudioStreamDevice(current_music->stream); + //SDL_ResumeAudioStreamDevice(current_music->stream); } void JA_PauseMusic() @@ -224,7 +225,8 @@ void JA_PauseMusic() if (!current_music || current_music->state == JA_MUSIC_INVALID) return; current_music->state = JA_MUSIC_PAUSED; - SDL_PauseAudioStreamDevice(current_music->stream); + //SDL_PauseAudioStreamDevice(current_music->stream); + SDL_UnbindAudioStream(current_music->stream); } void JA_ResumeMusic() @@ -233,7 +235,8 @@ void JA_ResumeMusic() if (!current_music || current_music->state == JA_MUSIC_INVALID) return; current_music->state = JA_MUSIC_PLAYING; - SDL_ResumeAudioStreamDevice(current_music->stream); + //SDL_ResumeAudioStreamDevice(current_music->stream); + SDL_BindAudioStream(sdlAudioDevice, current_music->stream); } void JA_StopMusic() @@ -243,7 +246,7 @@ void JA_StopMusic() current_music->pos = 0; current_music->state = JA_MUSIC_STOPPED; - SDL_PauseAudioStreamDevice(current_music->stream); + //SDL_PauseAudioStreamDevice(current_music->stream); SDL_DestroyAudioStream(current_music->stream); current_music->stream = nullptr; } @@ -388,7 +391,8 @@ void JA_PauseChannel(const int channel) if (channels[i].state == JA_CHANNEL_PLAYING) { channels[i].state = JA_CHANNEL_PAUSED; - SDL_PauseAudioStreamDevice(channels[i].stream); + //SDL_PauseAudioStreamDevice(channels[i].stream); + SDL_UnbindAudioStream(channels[i].stream); } } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) @@ -396,7 +400,8 @@ void JA_PauseChannel(const int channel) if (channels[channel].state == JA_CHANNEL_PLAYING) { channels[channel].state = JA_CHANNEL_PAUSED; - SDL_PauseAudioStreamDevice(channels[channel].stream); + //SDL_PauseAudioStreamDevice(channels[channel].stream); + SDL_UnbindAudioStream(channels[channel].stream); } } } @@ -411,7 +416,8 @@ void JA_ResumeChannel(const int channel) if (channels[i].state == JA_CHANNEL_PAUSED) { channels[i].state = JA_CHANNEL_PLAYING; - SDL_ResumeAudioStreamDevice(channels[i].stream); + //SDL_ResumeAudioStreamDevice(channels[i].stream); + SDL_BindAudioStream(sdlAudioDevice, channels[i].stream); } } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) @@ -419,7 +425,8 @@ void JA_ResumeChannel(const int channel) if (channels[channel].state == JA_CHANNEL_PAUSED) { channels[channel].state = JA_CHANNEL_PLAYING; - SDL_ResumeAudioStreamDevice(channels[channel].stream); + //SDL_ResumeAudioStreamDevice(channels[channel].stream); + SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream); } } } @@ -432,6 +439,7 @@ void JA_StopChannel(const int channel) { for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { if (channels[i].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[i].stream); + channels[channel].stream = nullptr; channels[i].state = JA_CHANNEL_FREE; channels[i].pos = 0; channels[i].sound = NULL; @@ -440,6 +448,7 @@ void JA_StopChannel(const int channel) else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { if (channels[channel].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[channel].stream); + channels[channel].stream = nullptr; channels[channel].state = JA_CHANNEL_FREE; channels[channel].pos = 0; channels[channel].sound = NULL; diff --git a/source/options.cpp b/source/options.cpp index 4fa4880..a993304 100644 --- a/source/options.cpp +++ b/source/options.cpp @@ -18,18 +18,15 @@ bool setOptions(const std::string &var, const std::string &value); // Inicializa las opciones del programa void initOptions() { + options.window.caption = "Coffee Crisis Arcade Edition"; + options.window.zoom = 2; + // Opciones de video -#ifdef ANBERNIC - options.video.mode = false; - options.video.window.size = 3; -#else options.video.fullscreen = false; - options.video.window.zoom = 2; -#endif options.video.filter = ScreenFilter::NEAREST; options.video.v_sync = true; options.video.integer_scale = true; - options.video.shaders = true; + options.video.shaders = false; // Opciones de audio options.audio.enabled = true; @@ -92,13 +89,12 @@ bool loadOptionsFile(std::string file_path) // El fichero no existe else - { // Crea el fichero con los valores por defecto + { + // Crea el fichero con los valores por defecto saveOptionsFile(file_path); } // Normaliza los valores - options.video.window.zoom = std::clamp(options.video.window.zoom, 1, 4); - if (options.game.language != lang::Code::en_UK && options.game.language != lang::Code::ba_BA && options.game.language != lang::Code::es_ES) @@ -127,8 +123,8 @@ bool saveOptionsFile(std::string file_path) file << "## video.filter [" << static_cast(ScreenFilter::NEAREST) << ": nearest, " << static_cast(ScreenFilter::LINEAL) << ": lineal]\n"; file << "\n"; + file << "window.zoom=" << options.window.zoom << "\n"; file << "video.fullscreen=" << boolToString(options.video.fullscreen) << "\n"; - file << "video.window.size=" << options.video.window.zoom << "\n"; file << "video.filter=" << static_cast(options.video.filter) << "\n"; file << "video.v_sync=" << boolToString(options.video.v_sync) << "\n"; file << "video.integer_scale=" << boolToString(options.video.integer_scale) << "\n"; @@ -193,12 +189,12 @@ bool setOptions(const std::string &var, const std::string &value) { options.video.fullscreen = stringToBool(value); } - else if (var == "video.window.size") + else if (var == "window.zoom") { - options.video.window.zoom = std::stoi(value); - if ((options.video.window.zoom < 1) || (options.video.window.zoom > 4)) + options.window.zoom = std::stoi(value); + if ((options.window.zoom < 1) || (options.window.zoom > 4)) { - options.video.window.zoom = 3; + options.window.zoom = 3; } } else if (var == "video.filter") diff --git a/source/options.h b/source/options.h index 4a0a5cf..c059aeb 100644 --- a/source/options.h +++ b/source/options.h @@ -22,20 +22,20 @@ enum class GameDifficulty // Estructura para las opciones de la ventana struct WindowOptions { - int zoom = 1; // Contiene el valor por el que se multiplica el tamaño de la ventana - int max_zoom = 1; // Tamaño máximo para que el tamaño de la ventana no sea mayor que el tamaño de la pantalla + std::string caption; // Texto que aparece en la barra de titulo de la ventana + int zoom = 1; // Contiene el valor por el que se multiplica el tamaño de la ventana + int max_zoom = 1; // Tamaño máximo para que el tamaño de la ventana no sea mayor que el tamaño de la pantalla }; // Estructura con opciones para el video struct VideoOptions { - WindowOptions window; // Opciones para la ventana del programa - ScreenFilter filter; // Filtro usado para el escalado de la imagen - bool fullscreen; // Contiene el valor del modo de pantalla completa - bool v_sync; // Indica si se quiere usar vsync o no - bool integer_scale; // Indica si se va a usar el escalado entero - bool shaders; // Indica si se van a usar shaders para los filtros de video - std::string info; // Información sobre el modo de video + ScreenFilter filter; // Filtro usado para el escalado de la imagen + bool fullscreen; // Contiene el valor del modo de pantalla completa + bool v_sync; // Indica si se quiere usar vsync o no + bool integer_scale; // Indica si se va a usar el escalado entero + bool shaders; // Indica si se van a usar shaders para los filtros de video + std::string info; // Información sobre el modo de video }; // Estructura para las opciones de musica @@ -99,6 +99,7 @@ struct GamepadOptions // Estructura con todas las opciones de configuración del programa struct Options { + WindowOptions window; // Opciones para la ventana del programa GameOptions game; // Opciones para el propio juego VideoOptions video; // Opciones relativas a la clase screen AudioOptions audio; // Opciones para el audio diff --git a/source/screen.cpp b/source/screen.cpp index 9f9db45..6364b64 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -1,6 +1,8 @@ #include "screen.h" +#include // Para SDL_PixelFormat #include // Para SDL_PixelFormat #include // Para SDL_GetTicks +#include // Para SDL_Init, SDL_INIT_VIDEO #include // Para max, min #include // Para basic_ifstream, ifstream #include // Para istreambuf_iterator, operator== @@ -19,7 +21,7 @@ Screen *Screen::screen_ = nullptr; // [SINGLETON] Crearemos el objeto con esta función estática -void Screen::init(SDL_Window *window, SDL_Renderer *renderer) { Screen::screen_ = new Screen(window, renderer); } +void Screen::init() { Screen::screen_ = new Screen(); } // [SINGLETON] Destruiremos el objeto con esta función estática void Screen::destroy() { delete Screen::screen_; } @@ -28,13 +30,17 @@ void Screen::destroy() { delete Screen::screen_; } Screen *Screen::get() { return Screen::screen_; } // Constructor -Screen::Screen(SDL_Window *window, SDL_Renderer *renderer) - : window_(window), - renderer_(renderer), - game_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), - src_rect_(SDL_FRect{0, 0, static_cast(param.game.width), static_cast(param.game.height)}), +Screen::Screen() + : src_rect_(SDL_FRect{0, 0, static_cast(param.game.width), static_cast(param.game.height)}), dst_rect_(SDL_FRect{0, 0, static_cast(param.game.width), static_cast(param.game.height)}) { + // Arranca SDL VIDEO, crea la ventana y el renderizador + initSDL(); + + // Crea la textura de destino + game_canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); + SDL_SetTextureScaleMode(game_canvas_, SDL_SCALEMODE_NEAREST); + // Inicializa variables adjustRenderLogicalSize(); @@ -46,7 +52,13 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer) } // Destructor -Screen::~Screen() { SDL_DestroyTexture(game_canvas_); } +Screen::~Screen() +{ + SDL_DestroyTexture(game_canvas_); + + SDL_DestroyRenderer(renderer_); + SDL_DestroyWindow(window_); +} // Limpia la pantalla void Screen::clean(Color color) @@ -109,7 +121,7 @@ void Screen::toggleFullscreen() // Cambia el tamaño de la ventana void Screen::setWindowZoom(int zoom) { - options.video.window.zoom = zoom; + options.window.zoom = zoom; adjustWindowSize(); } @@ -118,11 +130,11 @@ bool Screen::decWindowZoom() { if (!options.video.fullscreen) { - const int PREVIOUS_ZOOM = options.video.window.zoom; - --options.video.window.zoom; - options.video.window.zoom = std::max(options.video.window.zoom, 1); + const int PREVIOUS_ZOOM = options.window.zoom; + --options.window.zoom; + options.window.zoom = std::max(options.window.zoom, 1); - if (options.video.window.zoom != PREVIOUS_ZOOM) + if (options.window.zoom != PREVIOUS_ZOOM) { adjustWindowSize(); return true; @@ -137,11 +149,11 @@ bool Screen::incWindowZoom() { if (!options.video.fullscreen) { - const int PREVIOUS_ZOOM = options.video.window.zoom; - ++options.video.window.zoom; - options.video.window.zoom = std::min(options.video.window.zoom, options.video.window.max_zoom); + const int PREVIOUS_ZOOM = options.window.zoom; + ++options.window.zoom; + options.window.zoom = std::min(options.window.zoom, options.window.max_zoom); - if (options.video.window.zoom != PREVIOUS_ZOOM) + if (options.window.zoom != PREVIOUS_ZOOM) { adjustWindowSize(); return true; @@ -236,13 +248,11 @@ void Screen::initShaders() // Calcula el tamaño de la ventana void Screen::adjustWindowSize() { - options.video.window.max_zoom = getMaxZoom(); - // Establece el nuevo tamaño if (!options.video.fullscreen) { - const int WIDTH = param.game.width * options.video.window.zoom; - const int HEIGHT = param.game.height * options.video.window.zoom; + const int WIDTH = param.game.width * options.window.zoom; + const int HEIGHT = param.game.height * options.window.zoom; int old_width, old_height; SDL_GetWindowSize(window_, &old_width, &old_height); @@ -263,21 +273,6 @@ void Screen::adjustWindowSize() } } -// Obtiene el tamaño máximo de zoom posible para la ventana -int Screen::getMaxZoom() -{ - // Obtiene información sobre la pantalla - auto DM = SDL_GetCurrentDisplayMode(0); - - // Calcula el máximo factor de zoom que se puede aplicar a la pantalla - const int MAX_ZOOM = std::min(DM->w / param.game.width, (DM->h - WINDOWS_DECORATIONS_) / param.game.height); - - // Normaliza los valores de zoom - options.video.window.zoom = std::min(options.video.window.zoom, MAX_ZOOM); - - return MAX_ZOOM; -} - // Renderiza todos los overlays y efectos void Screen::renderOverlays() { @@ -298,4 +293,113 @@ void Screen::renderAttenuate() SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64); SDL_RenderFillRect(renderer_, nullptr); } +} + +// Arranca SDL VIDEO y crea la ventana +bool Screen::initSDL() +{ + // Indicador de éxito + auto success = true; + + // Inicializa SDL + if (!SDL_Init(SDL_INIT_VIDEO)) + { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_VIDEO could not initialize! SDL Error: %s", SDL_GetError()); + success = false; + } + else + { + getDisplayInfo(); + + // Establece el filtro de la textura + /*if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast(options.video.filter)).c_str())) + { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: texture filtering not enabled!"); + }*/ + + if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) + { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: opengl not enabled!"); + } + + // Crea la ventana + window_ = SDL_CreateWindow(options.window.caption.c_str(), param.game.width * options.window.zoom, param.game.height * options.window.zoom, SDL_WINDOW_OPENGL); + if (!window_) + { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window could not be created! SDL Error: %s", SDL_GetError()); + success = false; + } + else + { + // Crea un renderizador para la ventana. El vsync se activa en función de las opciones + // Uint32 flags = 0; + if (options.video.v_sync) + { + // flags = SDL_RENDERER_PRESENTVSYNC; + } + + // La aceleración se activa según el define + // flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE; + + renderer_ = SDL_CreateRenderer(window_, nullptr); + + if (!renderer_) + { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Renderer could not be created! SDL Error: %s", SDL_GetError()); + success = false; + } + else + { + SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF); + SDL_SetRenderLogicalPresentation(renderer_, param.game.width, param.game.height, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); + SDL_SetWindowFullscreen(window_, static_cast(options.video.fullscreen)); + SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); + } + } + } + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_VIDEO: Initialization complete."); + return success; +} + +// Obtiene información sobre la pantalla +void Screen::getDisplayInfo() +{ + int i, num_displays = 0; + SDL_DisplayID *displays = SDL_GetDisplays(&num_displays); + if (displays) + { + for (i = 0; i < num_displays; ++i) + { + SDL_DisplayID instance_id = displays[i]; + const char *name = SDL_GetDisplayName(instance_id); + + SDL_Log("Display %" SDL_PRIu32 ": %s", instance_id, name ? name : "Unknown"); + } + + auto DM = SDL_GetCurrentDisplayMode(displays[0]); + + // Calcula el máximo factor de zoom que se puede aplicar a la pantalla + options.window.max_zoom = std::min(DM->w / param.game.width, DM->h / param.game.height); + 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 + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Current display mode: %dx%d @ %dHz", + static_cast(DM->w), static_cast(DM->h), static_cast(DM->refresh_rate)); + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Window resolution: %dx%d x%d", + static_cast(param.game.width), static_cast(param.game.height), options.window.zoom); + + options.video.info = std::to_string(static_cast(DM->w)) + " X " + + std::to_string(static_cast(DM->h)) + " AT " + + std::to_string(static_cast(DM->refresh_rate)) + " HZ"; + + // Calcula el máximo factor de zoom que se puede aplicar a la pantalla + const int MAX_ZOOM = std::min(DM->w / param.game.width, (DM->h - WINDOWS_DECORATIONS_) / param.game.height); + + // Normaliza los valores de zoom + options.window.zoom = std::min(options.window.zoom, MAX_ZOOM); + + SDL_free(displays); + } } \ No newline at end of file diff --git a/source/screen.h b/source/screen.h index ee71bba..8709955 100644 --- a/source/screen.h +++ b/source/screen.h @@ -169,6 +169,9 @@ private: bool show_debug_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla #endif + // Arranca SDL VIDEO y crea la ventana + bool initSDL(); + // Dibuja el efecto de flash en la pantalla void renderFlash(); @@ -193,8 +196,8 @@ private: // Ajusta el tamaño lógico del renderizador void adjustRenderLogicalSize() { SDL_SetRenderLogicalPresentation(renderer_, param.game.width, param.game.height, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); } - // Obtiene el tamaño máximo de zoom posible para la ventana - int getMaxZoom(); + // Obtiene información sobre la pantalla + void getDisplayInfo(); // Renderiza todos los overlays y efectos void renderOverlays(); @@ -203,14 +206,14 @@ private: void renderAttenuate(); // Constructor - Screen(SDL_Window *window, SDL_Renderer *renderer); + Screen(); // Destructor ~Screen(); public: // [SINGLETON] Crearemos el objeto con esta función estática - static void init(SDL_Window *window, SDL_Renderer *renderer); + static void init(); // [SINGLETON] Destruiremos el objeto con esta función estática static void destroy();