Reballats tots els .h i .cpp en la mateixa carpeta
This commit is contained in:
515
source/screen.cpp
Normal file
515
source/screen.cpp
Normal file
@@ -0,0 +1,515 @@
|
||||
#include "screen.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#ifndef NO_SHADERS
|
||||
#include "jshader.h"
|
||||
#endif
|
||||
#include "dbgtxt.h"
|
||||
|
||||
// Constructor
|
||||
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, Input *input, options_t *options)
|
||||
{
|
||||
// Copia punteros
|
||||
this->window = window;
|
||||
this->renderer = renderer;
|
||||
this->asset = asset;
|
||||
this->input = input;
|
||||
this->options = options;
|
||||
|
||||
// Inicializa variables
|
||||
SDL_GetRendererOutputSize(renderer, &windowWidth, &windowHeight);
|
||||
gameCanvasWidth = options->video.gameWidth;
|
||||
gameCanvasHeight = options->video.gameHeight;
|
||||
dest = {0, 0, 0, 0};
|
||||
borderColor = {0, 0, 0};
|
||||
flashEffect.enabled = false;
|
||||
flashEffect.counter = 0;
|
||||
flashEffect.lenght = 0;
|
||||
flashEffect.color = {0xFF, 0xFF, 0xFF};
|
||||
shakeEffect.desp = 1;
|
||||
shakeEffect.delay = 3;
|
||||
shakeEffect.counter = 0;
|
||||
shakeEffect.lenght = 8;
|
||||
shakeEffect.remaining = 0;
|
||||
shakeEffect.origin = 0;
|
||||
attenuateEffect = false;
|
||||
fpsTicks = 0;
|
||||
fpsCounter = 0;
|
||||
fps = 0;
|
||||
#ifdef DEBUG
|
||||
showInfo = false;
|
||||
#else
|
||||
showInfo = false;
|
||||
#endif
|
||||
SDL_DisplayMode DM;
|
||||
SDL_GetCurrentDisplayMode(0, &DM);
|
||||
infoResolution = std::to_string(DM.w) + " X " + std::to_string(DM.h) + " AT " + std::to_string(DM.refresh_rate) + " HZ";
|
||||
|
||||
// Crea los objetos
|
||||
notify = new Notify(renderer, asset->get("notify.png"), asset->get("8bithud.png"), asset->get("8bithud.txt"), asset->get("notify.wav"), options);
|
||||
|
||||
// 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, gameCanvasWidth, gameCanvasHeight);
|
||||
|
||||
// Establece el modo de video
|
||||
setVideoMode(options->video.mode);
|
||||
|
||||
// Muestra la ventana
|
||||
SDL_ShowWindow(window);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Screen::~Screen()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
void Screen::blit()
|
||||
{
|
||||
// Actualiza y dibuja el efecto de flash en la pantalla
|
||||
doFlash();
|
||||
|
||||
// Atenua la pantalla
|
||||
doAttenuate();
|
||||
|
||||
// Actualiza el contador de FPS
|
||||
fpsCounter++;
|
||||
|
||||
// Muestra información por pantalla
|
||||
displayInfo();
|
||||
|
||||
// Muestra las notificaciones
|
||||
notify->render();
|
||||
|
||||
#ifdef NO_SHADERS
|
||||
// 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);
|
||||
|
||||
// Copia la textura de juego en el renderizador en la posición adecuada
|
||||
SDL_RenderCopy(renderer, gameCanvas, nullptr, &dest);
|
||||
|
||||
// Muestra por pantalla el renderizador
|
||||
SDL_RenderPresent(renderer);
|
||||
#else
|
||||
if (options->video.shaders)
|
||||
{
|
||||
shader::render();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
|
||||
// Copia la textura de juego en el renderizador en la posición adecuada
|
||||
SDL_RenderCopy(renderer, gameCanvas, nullptr, &dest);
|
||||
|
||||
// Muestra por pantalla el renderizador
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Establece el modo de video
|
||||
void Screen::setVideoMode(int videoMode)
|
||||
{
|
||||
#ifdef ARCADE
|
||||
videoMode = SCREEN_VIDEO_MODE_WINDOW;
|
||||
// videoMode = SCREEN_VIDEO_MODE_FULLSCREEN;
|
||||
#endif
|
||||
|
||||
// Si está activo el modo ventana quita el borde
|
||||
if (videoMode == SCREEN_VIDEO_MODE_WINDOW)
|
||||
{
|
||||
// Aplica el modo de video
|
||||
SDL_SetWindowFullscreen(window, 0);
|
||||
|
||||
#ifdef ARCADE
|
||||
// Oculta el puntero
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
#else
|
||||
// Muestra el puntero
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
#endif
|
||||
|
||||
windowWidth = gameCanvasWidth;
|
||||
windowHeight = gameCanvasHeight;
|
||||
dest = {0, 0, windowWidth, windowHeight};
|
||||
|
||||
// Modifica el tamaño de la ventana
|
||||
SDL_SetWindowSize(window, windowWidth * options->video.window.size, windowHeight * options->video.window.size);
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
|
||||
// Si está activo el modo de pantalla completa añade el borde
|
||||
else if (videoMode == SCREEN_VIDEO_MODE_FULLSCREEN)
|
||||
{
|
||||
// Aplica el modo de video
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
#ifdef ARCADE
|
||||
/*SDL_DisplayMode DM;
|
||||
DM.w = 1024;
|
||||
DM.h = 600;
|
||||
DM.refresh_rate = 60;
|
||||
if (!SDL_SetWindowDisplayMode(window, &DM))
|
||||
{
|
||||
std::cout << SDL_GetError() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Changed windows display mode" << std::endl;
|
||||
}*/
|
||||
#endif
|
||||
|
||||
// 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->video.integerScale)
|
||||
{
|
||||
// Calcula el tamaño de la escala máxima
|
||||
int scale = 0;
|
||||
while (((gameCanvasWidth * (scale + 1)) <= windowWidth) && ((gameCanvasHeight * (scale + 1)) <= windowHeight))
|
||||
{
|
||||
scale++;
|
||||
}
|
||||
|
||||
dest.w = gameCanvasWidth * scale;
|
||||
dest.h = gameCanvasHeight * scale;
|
||||
dest.x = (windowWidth - dest.w) / 2;
|
||||
dest.y = (windowHeight - dest.h) / 2;
|
||||
}
|
||||
else if (options->video.keepAspect)
|
||||
{
|
||||
float ratio = (float)gameCanvasWidth / (float)gameCanvasHeight;
|
||||
if ((windowWidth - gameCanvasWidth) >= (windowHeight - gameCanvasHeight))
|
||||
{
|
||||
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 = {0, 0, windowWidth, windowHeight};
|
||||
dest = {0, 0, gameCanvasWidth, gameCanvasHeight};
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NO_SHADERS
|
||||
// El renderizador pasa a tener el tamaño de la pantalla en fullscreen o del juego en modo ventana
|
||||
SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
|
||||
#else
|
||||
// Reinicia los shaders
|
||||
if (options->video.shaders)
|
||||
{
|
||||
std::ifstream f(asset->get("crtpi.glsl").c_str());
|
||||
std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
||||
|
||||
shader::init(window, gameCanvas, source.c_str());
|
||||
}
|
||||
|
||||
// Modifica el tamaño del renderizador
|
||||
else
|
||||
{
|
||||
// El renderizador pasa a tener el tamaño de la pantalla en fullscreen o del juego en modo ventana
|
||||
// SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
|
||||
SDL_RenderSetLogicalSize(renderer, gameCanvasWidth, gameCanvasHeight);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Actualiza las opciones
|
||||
options->video.mode = videoMode;
|
||||
options->video.window.width = windowWidth;
|
||||
options->video.window.height = windowHeight;
|
||||
|
||||
// Actualiza variables
|
||||
shakeEffect.origin = dest.x;
|
||||
}
|
||||
|
||||
// Camibia entre pantalla completa y ventana
|
||||
void Screen::switchVideoMode()
|
||||
{
|
||||
options->video.mode = options->video.mode == SCREEN_VIDEO_MODE_WINDOW ? SCREEN_VIDEO_MODE_FULLSCREEN : SCREEN_VIDEO_MODE_WINDOW;
|
||||
setVideoMode(options->video.mode);
|
||||
}
|
||||
|
||||
// Cambia el tamaño de la ventana
|
||||
void Screen::setWindowSize(int size)
|
||||
{
|
||||
options->video.window.size = size;
|
||||
setVideoMode(SCREEN_VIDEO_MODE_WINDOW);
|
||||
}
|
||||
|
||||
// Reduce el tamaño de la ventana
|
||||
void Screen::decWindowSize()
|
||||
{
|
||||
--options->video.window.size;
|
||||
options->video.window.size = std::max(options->video.window.size, 1);
|
||||
setVideoMode(SCREEN_VIDEO_MODE_WINDOW);
|
||||
}
|
||||
|
||||
// Aumenta el tamaño de la ventana
|
||||
void Screen::incWindowSize()
|
||||
{
|
||||
++options->video.window.size;
|
||||
options->video.window.size = std::min(options->video.window.size, 4);
|
||||
setVideoMode(SCREEN_VIDEO_MODE_WINDOW);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Actualiza la lógica de la clase
|
||||
void Screen::update()
|
||||
{
|
||||
updateShake();
|
||||
notify->update();
|
||||
updateFPS();
|
||||
}
|
||||
|
||||
// Comprueba las entradas
|
||||
void Screen::checkInput()
|
||||
{
|
||||
#ifndef ARCADE
|
||||
// Comprueba el teclado para cambiar entre pantalla completa y ventana
|
||||
if (input->checkInput(input_window_fullscreen, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
|
||||
{
|
||||
switchVideoMode();
|
||||
const std::string mode = options->video.mode == SCREEN_VIDEO_MODE_WINDOW ? "Window" : "Fullscreen";
|
||||
showNotification(mode + " mode");
|
||||
return;
|
||||
}
|
||||
|
||||
// Comprueba el teclado para decrementar el tamaño de la ventana
|
||||
if (input->checkInput(input_window_dec_size, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
|
||||
{
|
||||
decWindowSize();
|
||||
const std::string size = std::to_string(options->video.window.size);
|
||||
showNotification("Window size x" + size);
|
||||
return;
|
||||
}
|
||||
|
||||
// Comprueba el teclado para incrementar el tamaño de la ventana
|
||||
if (input->checkInput(input_window_inc_size, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
|
||||
{
|
||||
incWindowSize();
|
||||
const std::string size = std::to_string(options->video.window.size);
|
||||
showNotification("Window size x" + size);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Comprueba el teclado para activar o desactivar los shaders
|
||||
if (input->checkInput(input_video_shaders, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
|
||||
{
|
||||
switchShaders();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Comprueba el teclado para mostrar la información de debug
|
||||
if (input->checkInput(input_showinfo, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
|
||||
{
|
||||
showInfo = !showInfo;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < input->getNumControllers(); ++i)
|
||||
{
|
||||
// Comprueba los mandos para activar o desactivar los shaders
|
||||
if (input->checkModInput(input_service, input_video_shaders, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
|
||||
{
|
||||
switchShaders();
|
||||
return;
|
||||
}
|
||||
|
||||
// Comprueba los mandos para mostrar la información de debug
|
||||
if (input->checkModInput(input_service, input_showinfo, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
|
||||
{
|
||||
showInfo = !showInfo;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Agita la pantalla
|
||||
void Screen::shake()
|
||||
{
|
||||
// Si ya hay un shake effect en marcha no se pilla el origen, solo se renuevan los contadores
|
||||
if (shakeEffect.remaining == 0)
|
||||
{
|
||||
shakeEffect.origin = dest.x;
|
||||
}
|
||||
|
||||
shakeEffect.remaining = shakeEffect.lenght;
|
||||
shakeEffect.counter = shakeEffect.delay;
|
||||
}
|
||||
|
||||
// Actualiza la logica para agitar la pantalla
|
||||
void Screen::updateShake()
|
||||
{
|
||||
if (shakeEffect.remaining > 0)
|
||||
{
|
||||
if (shakeEffect.counter > 0)
|
||||
{
|
||||
shakeEffect.counter--;
|
||||
}
|
||||
else
|
||||
{
|
||||
shakeEffect.counter = shakeEffect.delay;
|
||||
const int desp = shakeEffect.remaining % 2 == 0 ? shakeEffect.desp * (-1) : shakeEffect.desp;
|
||||
dest.x = shakeEffect.origin + desp;
|
||||
shakeEffect.remaining--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dest.x = shakeEffect.origin;
|
||||
}
|
||||
}
|
||||
|
||||
// Pone la pantalla de color
|
||||
void Screen::flash(color_t color, int lenght)
|
||||
{
|
||||
flashEffect.enabled = true;
|
||||
flashEffect.counter = 0;
|
||||
flashEffect.lenght = lenght;
|
||||
flashEffect.color = color;
|
||||
}
|
||||
|
||||
// Actualiza y dibuja el efecto de flash en la pantalla
|
||||
void Screen::doFlash()
|
||||
{
|
||||
if (flashEffect.enabled)
|
||||
{
|
||||
// Dibuja el color del flash en la textura
|
||||
SDL_Texture *temp = SDL_GetRenderTarget(renderer);
|
||||
SDL_SetRenderTarget(renderer, gameCanvas);
|
||||
SDL_SetRenderDrawColor(renderer, flashEffect.color.r, flashEffect.color.g, flashEffect.color.b, 0xFF);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_SetRenderTarget(renderer, temp);
|
||||
|
||||
// Actualiza la lógica del efecto
|
||||
flashEffect.counter < flashEffect.lenght ? flashEffect.counter++ : flashEffect.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Atenua la pantalla
|
||||
void Screen::doAttenuate()
|
||||
{
|
||||
if (attenuateEffect)
|
||||
{
|
||||
SDL_Texture *temp = SDL_GetRenderTarget(renderer);
|
||||
SDL_SetRenderTarget(renderer, gameCanvas);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 64);
|
||||
SDL_RenderFillRect(renderer, nullptr);
|
||||
SDL_SetRenderTarget(renderer, temp);
|
||||
}
|
||||
}
|
||||
|
||||
// Activa/desactiva los shaders
|
||||
void Screen::switchShaders()
|
||||
{
|
||||
options->video.shaders = !options->video.shaders;
|
||||
setVideoMode(options->video.mode);
|
||||
const std::string value = options->video.shaders ? "on" : "off";
|
||||
showNotification("Shaders " + value);
|
||||
}
|
||||
|
||||
// Atenua la pantalla
|
||||
void Screen::attenuate(bool value)
|
||||
{
|
||||
attenuateEffect = value;
|
||||
}
|
||||
|
||||
// Muestra una notificación de texto por pantalla;
|
||||
void Screen::showNotification(std::string text1, std::string text2, int icon)
|
||||
{
|
||||
notify->showText(text1, text2, icon);
|
||||
}
|
||||
|
||||
// Obtiene el puntero al renderizador
|
||||
SDL_Renderer *Screen::getRenderer()
|
||||
{
|
||||
return renderer;
|
||||
}
|
||||
|
||||
// Calcula los frames por segundo
|
||||
void Screen::updateFPS()
|
||||
{
|
||||
if (SDL_GetTicks() - fpsTicks > 1000)
|
||||
{
|
||||
fpsTicks = SDL_GetTicks();
|
||||
fps = fpsCounter;
|
||||
fpsCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Muestra información por pantalla
|
||||
void Screen::displayInfo()
|
||||
{
|
||||
if (showInfo)
|
||||
{
|
||||
// FPS
|
||||
const std::string fpstext = std::to_string(fps) + " FPS";
|
||||
dbg_print(gameCanvasWidth - fpstext.length() * 8, 0, fpstext.c_str(), 255, 255, 0);
|
||||
|
||||
// Resolution
|
||||
dbg_print(0, 0, infoResolution.c_str(), 255, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Indica si hay alguna notificación activa en pantalla
|
||||
bool Screen::notificationsAreActive()
|
||||
{
|
||||
return notify->active();
|
||||
}
|
||||
Reference in New Issue
Block a user