#include "screen.h" #include #include // Constructor Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options) { // Inicializa variables this->window = window; this->renderer = renderer; this->options = options; borderWidth = options->screen.borderWidth * 2; borderHeight = options->screen.borderHeight * 2; iniFade(); iniSpectrumFade(); // Define el color del borde para el modo de pantalla completa borderColor = {0x00, 0x00, 0x00}; // Crea la textura donde se dibujan los graficos del juego gameCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, options->screen.nativeWidth, options->screen.nativeHeight); if (gameCanvas == nullptr) { if (options->console) { cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << endl; } } SDL_SetTextureBlendMode(gameCanvas, SDL_BLENDMODE_BLEND); // Establece el modo de video setVideoMode(options->screen.mode); } // Destructor Screen::~Screen() { if (notify != nullptr) { delete notify; } SDL_DestroyTexture(gameCanvas); } // Limpia la pantalla void Screen::clean(color_t color) { SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0xFF); SDL_RenderClear(renderer); } // Prepara para empezar a dibujar en la textura de juego void Screen::start() { SDL_SetRenderTarget(renderer, gameCanvas); SDL_RenderSetLogicalSize(renderer, options->screen.nativeWidth, options->screen.nativeHeight); } // Vuelca el contenido del renderizador en pantalla void Screen::blit() { // Vuelve a dejar el renderizador en modo normal SDL_SetRenderTarget(renderer, nullptr); // Borra el contenido previo SDL_SetRenderDrawColor(renderer, borderColor.r, borderColor.g, borderColor.b, 0xFF); SDL_RenderClear(renderer); SDL_RenderSetLogicalSize(renderer, gameWidth, gameHeight); // Copia la textura de juego en el renderizador en la posición adecuada SDL_RenderCopy(renderer, gameCanvas, nullptr, &dest); // Dibuja las notificaciones renderNotifications(); // Muestra por pantalla el renderizador SDL_RenderPresent(renderer); } // Establece el modo de video void Screen::setVideoMode(int videoMode) { // Aplica el modo de video SDL_SetWindowFullscreen(window, videoMode); // Si está activo el modo ventana quita el borde if (videoMode == 0) { // Muestra el puntero SDL_ShowCursor(SDL_ENABLE); if (options->screen.borderEnabled) { windowWidth = options->screen.nativeWidth + borderWidth; windowHeight = options->screen.nativeHeight + borderHeight; dest = {0 + (borderWidth / 2), 0 + (borderHeight / 2), options->screen.nativeWidth, options->screen.nativeHeight}; } else { // windowWidth = options->screen.nativeWidth; windowWidth = options->screen.nativeWidth * options->screen.nativeZoom * options->screen.windowZoom; // windowHeight = options->screen.nativeHeight; windowHeight = options->screen.nativeHeight * options->screen.nativeZoom * options->screen.windowZoom; // dest = {0, 0, options->screen.nativeWidth, options->screen.nativeHeight}; gameWidth = options->screen.nativeWidth * options->screen.nativeZoom; gameHeight = options->screen.nativeHeight * options->screen.nativeZoom; dest = {0, 0, gameWidth, gameHeight}; } // Modifica el tamaño de la ventana // SDL_SetWindowSize(window, windowWidth * options->screen.windowZoom, windowHeight * options->screen.windowZoom); SDL_SetWindowSize(window, windowWidth, windowHeight); SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); } // Si está activo el modo de pantalla completa añade el borde else if (videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP) { // Oculta el puntero SDL_ShowCursor(SDL_DISABLE); // Obten el alto y el ancho de la ventana SDL_GetWindowSize(window, &windowWidth, &windowHeight); // Aplica el escalado al rectangulo donde se pinta la textura del juego if (options->screen.integerScale) { // Calcula el tamaño de la escala máxima int scale = 0; while (((options->screen.nativeWidth * (scale + 1)) <= windowWidth) && ((options->screen.nativeHeight * (scale + 1)) <= windowHeight)) { scale++; } dest.w = options->screen.nativeWidth * scale; dest.h = options->screen.nativeHeight * scale; dest.x = (windowWidth - dest.w) / 2; dest.y = (windowHeight - dest.h) / 2; } else if (options->screen.keepAspect) { float ratio = (float)options->screen.nativeWidth / (float)options->screen.nativeHeight; if ((windowWidth - options->screen.nativeWidth) >= (windowHeight - options->screen.nativeHeight)) { dest.h = windowHeight; dest.w = (int)((windowHeight * ratio) + 0.5f); dest.x = (windowWidth - dest.w) / 2; dest.y = (windowHeight - dest.h) / 2; } else { dest.w = windowWidth; dest.h = (int)((windowWidth / ratio) + 0.5f); dest.x = (windowWidth - dest.w) / 2; dest.y = (windowHeight - dest.h) / 2; } } else { dest.w = windowWidth; dest.h = windowHeight; dest.x = dest.y = 0; } } // Modifica el tamaño del renderizador // SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight); //SDL_RenderSetLogicalSize(renderer, gameWidth, gameHeight); // Actualiza las opciones options->screen.mode = videoMode; } // Camibia entre pantalla completa y ventana void Screen::switchVideoMode() { options->screen.mode = (options->screen.mode == 0) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0; setVideoMode(options->screen.mode); } // Cambia el tamaño de la ventana void Screen::setWindowSize(int size) { options->screen.windowZoom = size; setVideoMode(0); } // Reduce el tamaño de la ventana void Screen::decWindowSize() { --options->screen.windowZoom; options->screen.windowZoom = max(options->screen.windowZoom, 1); setVideoMode(0); } // Aumenta el tamaño de la ventana void Screen::incWindowSize() { ++options->screen.windowZoom; options->screen.windowZoom = min(options->screen.windowZoom, 4); setVideoMode(0); } // Cambia el color del borde void Screen::setBorderColor(color_t color) { borderColor = color; } // Cambia el tipo de mezcla void Screen::setBlendMode(SDL_BlendMode blendMode) { SDL_SetRenderDrawBlendMode(renderer, blendMode); } // Establece el tamaño del borde void Screen::setBorderWidth(int s) { options->screen.borderWidth = s; } // Establece el tamaño del borde void Screen::setBorderHeight(int s) { options->screen.borderHeight = s; } // Establece si se ha de ver el borde en el modo ventana void Screen::setBorderEnabled(bool value) { options->screen.borderEnabled = value; } // Cambia entre borde visible y no visible void Screen::switchBorder() { options->screen.borderEnabled = !options->screen.borderEnabled; setVideoMode(0); } // Activa el fade void Screen::setFade() { fade = true; } // Comprueba si ha terminado el fade bool Screen::fadeEnded() { if (fade || fadeCounter > 0) { return false; } return true; } // Activa el spectrum fade void Screen::setspectrumFade() { spectrumFade = true; } // Comprueba si ha terminado el spectrum fade bool Screen::spectrumFadeEnded() { if (spectrumFade || spectrumFadeCounter > 0) { return false; } return true; } // Inicializa las variables para el fade void Screen::iniFade() { fade = false; fadeCounter = 0; fadeLenght = 200; } // Actualiza el fade void Screen::updateFade() { if (!fade) { return; } fadeCounter++; if (fadeCounter > fadeLenght) { iniFade(); } } // Dibuja el fade void Screen::renderFade() { if (!fade) { return; } const SDL_Rect rect = {0, 0, options->screen.nativeWidth, options->screen.nativeHeight}; color_t color = {0, 0, 0}; const float step = (float)fadeCounter / (float)fadeLenght; const int alpha = 0 + (255 - 0) * step; SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, alpha); SDL_RenderFillRect(renderer, &rect); } // Inicializa las variables para el fade spectrum void Screen::iniSpectrumFade() { spectrumFade = false; spectrumFadeCounter = 0; spectrumFadeLenght = 50; spectrumColor.clear(); // Inicializa el vector de colores const vector vColors = {"black", "blue", "red", "magenta", "green", "cyan", "yellow", "bright_white"}; for (auto v : vColors) { spectrumColor.push_back(stringToColor(options->palette, v)); } } // Actualiza el spectrum fade void Screen::updateSpectrumFade() { if (!spectrumFade) { return; } spectrumFadeCounter++; if (spectrumFadeCounter > spectrumFadeLenght) { iniSpectrumFade(); SDL_SetTextureColorMod(gameCanvas, 255, 255, 255); } } // Dibuja el spectrum fade void Screen::renderSpectrumFade() { if (!spectrumFade) { return; } const float step = (float)spectrumFadeCounter / (float)spectrumFadeLenght; const int max = spectrumColor.size() - 1; const int index = max + (0 - max) * step; const color_t c = spectrumColor[index]; SDL_SetTextureColorMod(gameCanvas, c.r, c.g, c.b); } // Actualiza los efectos void Screen::updateFX() { updateFade(); updateSpectrumFade(); } // Dibuja los efectos void Screen::renderFX() { renderFade(); renderSpectrumFade(); } // Añade un notificador a la pantalla void Screen::addNotifier(string iconsFile, string bitmapFontFile, string offsetFontFile, string soundFile) { notify = new Notify(renderer, iconsFile, bitmapFontFile, offsetFontFile, soundFile, options); } // Actualiza el notificador void Screen::updateNotifier() { notify->update(); } // Muestra una notificación de texto por pantalla; void Screen::showNotification(string text1, string text2, int icon) { notify->showText(text1, text2, icon); } // Dibuja las notificaciones void Screen::renderNotifications() { if (!notify->active()) { return; } notify->render(); } // Actualiza la lógica del objeto void Screen::update() { updateNotifier(); updateFX(); }