Actualizando las clases comunes a sus ultimas versiones

This commit is contained in:
2022-12-05 09:13:04 +01:00
parent cdb5040b9d
commit 09a205a288
12 changed files with 506 additions and 275 deletions

View File

@@ -1,24 +1,30 @@
#include "notify.h"
#include <string>
#include <stdio.h>
#include <iostream>
// Constructor
Notify::Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile)
Notify::Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile, std::string soundFile, options_t *options)
{
// Inicializa variables
this->renderer = renderer;
bgColor = {64, 64, 64};
this->options = options;
bgColor = options->notifications.color;
waitTime = 300;
// Crea objetos
text = new Text(bitmapFile, textFile, renderer);
texture = new Texture(renderer, bitmapFile);
text = new Text(textFile, texture, renderer);
sound = JA_LoadSound(soundFile.c_str());
}
// Destructor
Notify::~Notify()
{
// Libera la memoria de los objetos
delete texture;
delete text;
JA_DeleteSound(sound);
for (auto notification : notifications)
{
@@ -32,7 +38,7 @@ void Notify::render()
{
for (int i = (int)notifications.size() - 1; i >= 0; --i)
{
notifications.at(i).sprite->render();
notifications[i].sprite->render();
}
}
@@ -41,49 +47,63 @@ void Notify::update()
{
for (int i = 0; i < (int)notifications.size(); ++i)
{
notifications.at(i).counter++;
notifications[i].counter++;
// Comprueba los estados
if (notifications.at(i).state == ns_rising)
if (notifications[i].state == ns_rising)
{
const float step = ((float)notifications.at(i).counter / notifications.at(i).travelDist);
const float step = ((float)notifications[i].counter / notifications[i].travelDist);
const int alpha = 255 * step;
notifications.at(i).rect.y++;
notifications.at(i).texture->setAlpha(alpha);
if (notifications.at(i).rect.y == notifications.at(i).y)
if (options->notifications.posV == pos_top)
{
notifications.at(i).state = ns_stay;
notifications.at(i).texture->setAlpha(255);
notifications.at(i).counter = 0;
notifications[i].rect.y++;
}
else
{
notifications[i].rect.y--;
}
notifications[i].texture->setAlpha(alpha);
if (notifications[i].rect.y == notifications[i].y)
{
notifications[i].state = ns_stay;
notifications[i].texture->setAlpha(255);
notifications[i].counter = 0;
}
}
else if (notifications.at(i).state == ns_stay)
else if (notifications[i].state == ns_stay)
{
if (notifications.at(i).counter == waitTime)
if (notifications[i].counter == waitTime)
{
notifications.at(i).state = ns_vanishing;
notifications.at(i).counter = 0;
notifications[i].state = ns_vanishing;
notifications[i].counter = 0;
}
}
else if (notifications.at(i).state == ns_vanishing)
else if (notifications[i].state == ns_vanishing)
{
const float step = (notifications.at(i).counter / (float)notifications.at(i).travelDist);
const float step = (notifications[i].counter / (float)notifications[i].travelDist);
const int alpha = 255 * (1 - step);
notifications.at(i).rect.y--;
notifications.at(i).texture->setAlpha(alpha);
if (notifications.at(i).rect.y == notifications.at(i).y - notifications.at(i).travelDist)
if (options->notifications.posV == pos_top)
{
notifications.at(i).state = ns_finished;
notifications[i].rect.y--;
}
else
{
notifications[i].rect.y++;
}
notifications[i].texture->setAlpha(alpha);
if (notifications[i].rect.y == notifications[i].y - notifications[i].travelDist)
{
notifications[i].state = ns_finished;
}
}
notifications.at(i).sprite->setRect(notifications.at(i).rect);
notifications[i].sprite->setRect(notifications[i].rect);
}
clearFinishedNotifications();
@@ -94,10 +114,10 @@ void Notify::clearFinishedNotifications()
{
for (int i = (int)notifications.size() - 1; i >= 0; --i)
{
if (notifications.at(i).state == ns_finished)
if (notifications[i].state == ns_finished)
{
delete notifications.at(i).sprite;
delete notifications.at(i).texture;
delete notifications[i].sprite;
delete notifications[i].texture;
notifications.erase(notifications.begin() + i);
}
}
@@ -106,24 +126,67 @@ void Notify::clearFinishedNotifications()
// Muestra una notificación de texto por pantalla;
void Notify::showText(std::string text)
{
// Crea constantes
// Inicializa variables
const int width = this->text->lenght(text) + (this->text->getCharacterSize() * 2);
const int height = this->text->getCharacterSize() * 2;
const int despH = this->text->getCharacterSize() / 2;
const int despV = despH;
const int travelDist = height + despV;
const int offset = (int)notifications.size() > 0 ? notifications.back().y + travelDist : despV;
const int padding = (this->text->getCharacterSize() / 2);
// Posición horizontal
int despH = 0;
if (options->notifications.posH == pos_left)
{
despH = padding;
}
else if (options->notifications.posH == pos_middle)
{
despH = ((options->screen.windowWidth * options->windowSize) / 2 - (width / 2));
}
else
{
despH = (options->screen.windowWidth * options->windowSize) - width - padding;
}
// Posición vertical
int despV = 0;
if (options->notifications.posV == pos_top)
{
despV = padding;
}
else
{
despV = (options->screen.windowHeight * options->windowSize) - height - padding;
}
const int travelDist = height + padding;
// Offset
int offset = 0;
if (options->notifications.posV == pos_top)
{
offset = (int)notifications.size() > 0 ? notifications.back().y + travelDist : despV;
}
else
{
offset = (int)notifications.size() > 0 ? notifications.back().y - travelDist : despV;
}
// Crea la notificacion
notification_t n;
// inicializa variables
// Inicializa variables
n.y = offset;
n.travelDist = travelDist;
n.counter = 0;
n.state = ns_rising;
n.text = text;
n.rect = {despH, offset - travelDist, width, height};
if (options->notifications.posV == pos_top)
{
n.rect = {despH, offset - travelDist, width, height};
}
else
{
n.rect = {despH, offset + travelDist, width, height};
}
// Crea la textura
n.texture = new Texture(renderer);
@@ -132,13 +195,20 @@ void Notify::showText(std::string text)
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(renderer);
n.texture->setBlendMode(SDL_BLENDMODE_BLEND);
this->text->writeDX(TXT_CENTER | TXT_STROKE, width / 2, despV, text, 1, {255, 255, 255}, 1, {0, 0, 0});
this->text->writeDX(TXT_CENTER | TXT_STROKE, width / 2, padding, text, 1, {255, 255, 255}, 1, {0, 0, 0});
SDL_SetRenderTarget(renderer, nullptr);
// Crea el sprite
n.sprite = new Sprite(n.rect, n.texture, renderer);
// Añade la notificación a la lista
notifications.push_back(n);
// Reproduce el sonido de la notificación
if (options->notifications.sound)
{
JA_PlaySound(sound);
}
}
// Indica si hay notificaciones activas
@@ -148,6 +218,6 @@ bool Notify::active()
{
return true;
}
return false;
}

View File

@@ -1,9 +1,10 @@
#pragma once
#include <SDL2/SDL.h>
#include "jail_audio.h"
#include "sprite.h"
#include "text.h"
#include "texture.h"
#include "sprite.h"
#include "utils.h"
#include <vector>
@@ -48,12 +49,15 @@ private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Texture *texture; // Textura para la fuente de las notificaciones
Text *text; // Objeto para dibujar texto
options_t *options; // Variable con todas las opciones del programa
// Variables
color_t bgColor; // Color de fondo de las notificaciones
int waitTime; // Tiempo que se ve la notificación
std::vector<notification_t> notifications; // La lista de notificaciones activas
JA_Sound_t* sound; // Sonido a reproducir cuando suena la notificación
// Elimina las notificaciones finalizadas
void clearFinishedNotifications();
@@ -66,7 +70,7 @@ public:
void update();
// Constructor
Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile);
Notify(SDL_Renderer *renderer, std::string bitmapFile, std::string textFile, std::string soundFile, options_t *options);
// Destructor
~Notify();

View File

@@ -1,9 +1,9 @@
#include "screen.h"
#include <string>
#include <stdio.h>
#include <iostream>
// Constructor
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options, int gameInternalResX, int gameInternalResY)
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options)
{
// Inicializa variables
this->window = window;
@@ -12,10 +12,14 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
this->asset = asset;
// Crea los objetos
notify = new Notify(renderer, asset->get("smb2.png"), asset->get("smb2.txt"));
notify = new Notify(renderer, asset->get("smb2.png"), asset->get("smb2.txt"), asset->get("notify.wav"), options);
gameCanvasWidth = gameInternalResX;
gameCanvasHeight = gameInternalResY;
gameCanvasWidth = options->gameWidth;
gameCanvasHeight = options->gameHeight;
borderWidth = options->borderWidth * 2;
borderHeight = options->borderHeight * 2;
notificationLogicalWidth = gameCanvasWidth;
notificationLogicalHeight = gameCanvasHeight;
iniFade();
iniSpectrumFade();
@@ -27,19 +31,14 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
gameCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, gameCanvasWidth, gameCanvasHeight);
if (gameCanvas == nullptr)
{
printf("TitleSurface could not be created!\nSDL Error: %s\n", SDL_GetError());
if (options->console)
{
std::cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
// Establece el modo de video
setVideoMode(options->fullScreenMode);
// Calcula los anclajes
anchor.left = 0;
anchor.right = gameCanvasWidth;
anchor.center = gameCanvasWidth / 2;
anchor.top = 0;
anchor.bottom = gameCanvasHeight;
anchor.middle = gameCanvasHeight / 2;
setVideoMode(options->videoMode);
// Inicializa variables
notifyActive = false;
@@ -85,96 +84,103 @@ void Screen::blit()
}
// Establece el modo de video
void Screen::setVideoMode(int fullScreenMode)
void Screen::setVideoMode(int videoMode)
{
// Muestra el puntero
SDL_ShowCursor(SDL_ENABLE);
// Aplica el modo de video
SDL_SetWindowFullscreen(window, fullScreenMode);
SDL_SetWindowFullscreen(window, videoMode);
// Si está activo el modo ventana quita el borde
if (fullScreenMode == 0)
if (videoMode == 0)
{
if (options->borderEnabled)
{
const int incWidth = gameCanvasWidth * options->borderSize;
const int incHeight = gameCanvasHeight * options->borderSize;
screenWidth = gameCanvasWidth + incWidth;
screenHeight = gameCanvasHeight + incHeight;
dest = {0 + (incWidth / 2), 0 + (incHeight / 2), gameCanvasWidth, gameCanvasHeight};
windowWidth = gameCanvasWidth + borderWidth;
windowHeight = gameCanvasHeight + borderHeight;
dest = {0 + (borderWidth / 2), 0 + (borderHeight / 2), gameCanvasWidth, gameCanvasHeight};
}
else
{
screenWidth = gameCanvasWidth * options->windowSize;
screenHeight = gameCanvasHeight * options->windowSize;
windowWidth = gameCanvasWidth;
windowHeight = gameCanvasHeight;
dest = {0, 0, gameCanvasWidth, gameCanvasHeight};
}
// Modifica el tamaño del renderizador y de la ventana
// SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight);
// SDL_SetWindowSize(window, screenWidth * options->windowSize, screenHeight * options->windowSize);
SDL_RenderSetLogicalSize(renderer, gameCanvasWidth, gameCanvasHeight);
SDL_SetWindowSize(window, screenWidth, screenHeight);
SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
SDL_SetWindowSize(window, windowWidth * options->windowSize, windowHeight * options->windowSize);
}
// Si está activo el modo de pantalla completa añade el borde
else if (fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
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, &screenWidth, &screenHeight);
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
// Aplica el escalado al rectangulo donde se pinta la textura del juego
if (options->integerScale)
{
// Calcula el tamaño de la escala máxima
int scale = 0;
while (((gameCanvasWidth * (scale + 1)) <= screenWidth) && ((gameCanvasHeight * (scale + 1)) <= screenHeight))
while (((gameCanvasWidth * (scale + 1)) <= windowWidth) && ((gameCanvasHeight * (scale + 1)) <= windowHeight))
{
scale++;
}
dest.w = gameCanvasWidth * scale;
dest.h = gameCanvasHeight * scale;
dest.x = (screenWidth - dest.w) / 2;
dest.y = (screenHeight - dest.h) / 2;
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
else if (options->keepAspect)
{
float ratio = (float)gameCanvasWidth / (float)gameCanvasHeight;
if ((screenWidth - gameCanvasWidth) >= (screenHeight - gameCanvasHeight))
if ((windowWidth - gameCanvasWidth) >= (windowHeight - gameCanvasHeight))
{
dest.h = screenHeight;
dest.w = (int)((screenHeight * ratio) + 0.5f);
dest.x = (screenWidth - dest.w) / 2;
dest.y = (screenHeight - dest.h) / 2;
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 = screenWidth;
dest.h = (int)((screenWidth / ratio) + 0.5f);
dest.x = (screenWidth - dest.w) / 2;
dest.y = (screenHeight - dest.h) / 2;
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 = screenWidth;
dest.h = screenHeight;
dest.w = windowWidth;
dest.h = windowHeight;
dest.x = dest.y = 0;
}
// Modifica el tamaño del renderizador
SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight);
SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
}
// Actualiza el valor de la variable
options->fullScreenMode = fullScreenMode;
// Actualiza las opciones
options->videoMode = videoMode;
options->screen.windowWidth = windowWidth;
options->screen.windowHeight = windowHeight;
// Establece el tamaño de las notificaciones
setNotificationSize();
}
// Camibia entre pantalla completa y ventana
void Screen::switchVideoMode()
{
options->fullScreenMode = (options->fullScreenMode == 0) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
setVideoMode(options->fullScreenMode);
options->videoMode = (options->videoMode == 0) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
setVideoMode(options->videoMode);
}
// Cambia el tamaño de la ventana
@@ -197,9 +203,15 @@ void Screen::setBlendMode(SDL_BlendMode blendMode)
}
// Establece el tamaño del borde
void Screen::setBorderSize(float s)
void Screen::setBorderWidth(int s)
{
options->borderSize = s;
options->borderWidth = s;
}
// Establece el tamaño del borde
void Screen::setBorderHeight(int s)
{
options->borderHeight = s;
}
// Establece si se ha de ver el borde en el modo ventana
@@ -301,7 +313,7 @@ void Screen::iniSpectrumFade()
const std::vector<std::string> vColors = {"black", "blue", "red", "magenta", "green", "cyan", "yellow", "bright_white"};
for (auto v : vColors)
{
spectrumColor.push_back(stringToColor(p_zxspectrum, v));
spectrumColor.push_back(stringToColor(options->palette, v));
}
}
@@ -332,7 +344,7 @@ void Screen::renderSpectrumFade()
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.at(index);
const color_t c = spectrumColor[index];
SDL_SetTextureColorMod(gameCanvas, c.r, c.g, c.b);
}
@@ -358,7 +370,7 @@ void Screen::updateNotifier()
}
// Muestra una notificación de texto por pantalla;
void Screen::showText(std::string text)
void Screen::showNotification(std::string text)
{
notify->showText(text);
}
@@ -371,8 +383,31 @@ void Screen::renderNotifications()
return;
}
//SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight);
SDL_RenderSetLogicalSize(renderer, gameCanvasWidth*2, gameCanvasHeight*2);
//SDL_RenderSetLogicalSize(renderer, notificationLogicalWidth, notificationLogicalHeight);
notify->render();
SDL_RenderSetLogicalSize(renderer, gameCanvasWidth, gameCanvasHeight);
//SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
}
// Establece el tamaño de las notificaciones
void Screen::setNotificationSize()
{
if (options->videoMode == 0)
{
if (options->windowSize == 3)
{
notificationLogicalWidth = (windowWidth * 3) / 2;
notificationLogicalHeight = (windowHeight * 3) / 2;
}
else
{
notificationLogicalWidth = windowWidth * 2;
notificationLogicalHeight = windowHeight * 2;
}
}
if (options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
notificationLogicalWidth = windowWidth / 3;
notificationLogicalHeight = windowHeight / 3;
}
}

View File

@@ -12,21 +12,10 @@
#define FILTER_NEAREST 0
#define FILTER_LINEAL 1
struct anchor_t
{
int left; // Parte izquierda de la pantalla de juego
int right; // Parte drecha de la pantalla de juego
int center; // Parte central horizontal de la pantalla de juego
int top; // Parte superior de la pantalla de juego
int bottom; // Parte infoerior de la pantalla de juego
int middle; // Parte central vertical de la pantalla de juego
};
// Clase Screen
class Screen
{
private:
// Objetos y variables
// Objetos y punteros
SDL_Window *window; // Ventana de la aplicación
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con el listado de recursos
@@ -34,16 +23,20 @@ private:
options_t *options; // Variable con todas las opciones del programa
Notify *notify; // Dibuja notificaciones por pantalla
int screenWidth; // Ancho de la pantalla o ventana
int screenHeight; // Alto de la pantalla o ventana
int gameCanvasWidth; // Resolución interna del juego. Es el ancho de la textura donde se dibuja el juego
int gameCanvasHeight; // Resolución interna del juego. Es el alto de la textura donde se dibuja el juego
anchor_t anchor; // Variable con los anclajes de la pantalla
SDL_Rect dest; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla
bool notifyActive; // Indica si hay notificaciones activas
// Variables
int windowWidth; // Ancho de la pantalla o ventana
int windowHeight; // Alto de la pantalla o ventana
int gameCanvasWidth; // Resolución interna del juego. Es el ancho de la textura donde se dibuja el juego
int gameCanvasHeight; // Resolución interna del juego. Es el alto de la textura donde se dibuja el juego
int borderWidth; // Anchura del borde
int borderHeight; // Anltura del borde
SDL_Rect dest; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla
bool notifyActive; // Indica si hay notificaciones activas
int notificationLogicalWidth; // Ancho lógico de las notificaciones en relación al tamaño de pantalla
int notificationLogicalHeight; // Alto lógico de las notificaciones en relación al tamaño de pantalla
// EFECTOS
// Variables - Efectos
bool fade; // Indica si esta activo el efecto de fade
int fadeCounter; // Temporizador para el efecto de fade
int fadeLenght; // Duración del fade
@@ -73,9 +66,12 @@ private:
// Dibuja las notificaciones
void renderNotifications();
// Establece el tamaño de las notificaciones
void setNotificationSize();
public:
// Constructor
Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options, int gameInternalResX, int gameInternalResY);
Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options);
// Destructor
~Screen();
@@ -90,7 +86,7 @@ public:
void blit();
// Establece el modo de video
void setVideoMode(int fullScreenMode);
void setVideoMode(int videoMode);
// Camibia entre pantalla completa y ventana
void switchVideoMode();
@@ -105,7 +101,8 @@ public:
void setBlendMode(SDL_BlendMode blendMode);
// Establece el tamaño del borde
void setBorderSize(float s);
void setBorderWidth(int s);
void setBorderHeight(int s);
// Establece si se ha de ver el borde en el modo ventana
void setBorderEnabled(bool value);
@@ -135,7 +132,7 @@ public:
void updateNotifier();
// Muestra una notificación de texto por pantalla;
void showText(std::string text);
void showNotification(std::string text);
};
#endif

View File

@@ -3,22 +3,151 @@
#include <iostream>
#include <fstream>
// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(std::string file, bool verbose)
{
textFile_t tf;
// Inicializa a cero el vector con las coordenadas
for (int i = 0; i < 128; ++i)
{
tf.offset[i].x = 0;
tf.offset[i].y = 0;
tf.offset[i].w = 0;
}
// Abre el fichero para leer los valores
const std::string filename = file.substr(file.find_last_of("\\/") + 1).c_str();
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good())
{
std::string buffer;
// Lee los dos primeros valores del fichero
std::getline(rfile, buffer);
std::getline(rfile, buffer);
tf.boxWidth = std::stoi(buffer);
std::getline(rfile, buffer);
std::getline(rfile, buffer);
tf.boxHeight = std::stoi(buffer);
// lee el resto de datos del fichero
int index = 32;
int line_read = 0;
while (std::getline(rfile, buffer))
{
// Almacena solo las lineas impares
if (line_read % 2 == 1)
{
tf.offset[index++].w = std::stoi(buffer);
}
// Limpia el buffer
buffer.clear();
line_read++;
};
// Cierra el fichero
if (verbose)
{
std::cout << "Text loaded: " << filename.c_str() << std::endl;
}
rfile.close();
}
// El fichero no se puede abrir
else
{
if (verbose)
{
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; ++i)
{
tf.offset[i].x = ((i - 32) % 15) * tf.boxWidth;
tf.offset[i].y = ((i - 32) / 15) * tf.boxHeight;
}
return tf;
}
// Constructor
Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer)
{
// Carga los offsets desde el fichero
initOffsetFromFile(textFile);
textFile_t tf = LoadTextFile(textFile);
// Inicializa variables desde la estructura
boxHeight = tf.boxHeight;
boxWidth = tf.boxWidth;
for (int i = 0; i < 128; ++i)
{
offset[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w;
}
// Crea los objetos
texture = new Texture(renderer, bitmapFile);
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer);
}
// Constructor
Text::Text(std::string textFile, Texture *texture, SDL_Renderer *renderer)
{
// Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile);
// Inicializa variables desde la estructura
boxHeight = tf.boxHeight;
boxWidth = tf.boxWidth;
for (int i = 0; i < 128; ++i)
{
offset[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w;
}
// Crea los objetos
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer);
// Inicializa variables
fixedWidth = false;
}
// Constructor
Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer)
{
// Inicializa variables desde la estructura
boxHeight = textFile->boxHeight;
boxWidth = textFile->boxWidth;
for (int i = 0; i < 128; ++i)
{
offset[i].x = textFile->offset[i].x;
offset[i].y = textFile->offset[i].y;
offset[i].w = textFile->offset[i].w;
}
// Crea los objetos
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer);
// Inicializa variables
fixedWidth = false;
}
// Destructor
Text::~Text()
{
delete texture;
delete sprite;
if (texture)
{
delete texture;
}
}
// Escribe texto en pantalla
@@ -35,7 +164,8 @@ void Text::write(int x, int y, std::string text, int kerning, int lenght)
sprite->setPosX(x + shift);
sprite->setPosY(y);
sprite->render();
shift += (offset[int(text[i])].w + kerning);
// shift += (offset[int(text[i])].w + kerning);
shift += fixedWidth ? boxWidth : (offset[int(text[i])].w + kerning);
}
}
@@ -72,28 +202,37 @@ void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, col
const bool stroked = ((flags & TXT_STROKE) == TXT_STROKE);
if (centered)
{
x -= (Text::lenght(text, kerning) / 2);
}
if (shadowed)
{
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
}
if (stroked)
{
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x + shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x + shadowDistance, y, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y, text, shadowColor, kerning, lenght);
for (int dist = 1; dist <= shadowDistance; ++dist)
{
for (int dy = -dist; dy <= dist; ++dy)
{
for (int dx = -dist; dx <= dist; ++dx)
{
writeColored(x + dx, y + dy, text, shadowColor, kerning, lenght);
}
}
}
}
if (colored)
{
writeColored(x, y, text, textColor, kerning, lenght);
}
else
{
write(x, y, text, kerning, lenght);
}
}
// Obtiene la longitud en pixels de una cadena
@@ -108,69 +247,6 @@ int Text::lenght(std::string text, int kerning)
return shift - kerning;
}
// Inicializa el vector de offsets desde un fichero
void Text::initOffsetFromFile(std::string file)
{
// Inicializa a cero el vector con las coordenadas
for (int i = 0; i < 128; ++i)
{
offset[i].x = 0;
offset[i].y = 0;
offset[i].w = 0;
}
// Abre el fichero para leer los valores
const std::string filename = file.substr(file.find_last_of("\\/") + 1).c_str();
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good())
{
std::string buffer;
// Lee los dos primeros valores del fichero
std::getline(rfile, buffer);
std::getline(rfile, buffer);
boxWidth = std::stoi(buffer);
std::getline(rfile, buffer);
std::getline(rfile, buffer);
boxHeight = std::stoi(buffer);
// lee el resto de datos del fichero
int index = 32;
int line_read = 0;
while (std::getline(rfile, buffer))
{
// Almacena solo las lineas impares
if (line_read % 2 == 1)
{
offset[index++].w = std::stoi(buffer);
}
// Limpia el buffer
buffer.clear();
line_read++;
};
// Cierra el fichero
printf("Text loaded: %s\n", filename.c_str());
rfile.close();
}
// El fichero no se puede abrir
else
{
printf("Warning: Unable to open %s file\n", filename.c_str());
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; ++i)
{
offset[i].x = ((i - 32) % 15) * boxWidth;
offset[i].y = ((i - 32) / 15) * boxHeight;
}
}
// Devuelve el valor de la variable
int Text::getCharacterSize()
{
@@ -180,5 +256,11 @@ int Text::getCharacterSize()
// Recarga la textura
void Text::reLoadTexture()
{
texture->reLoad();
sprite->getTexture()->reLoad();
}
// Establece si se usa un tamaño fijo de letra
void Text::setFixedWidth(bool value)
{
fixedWidth = value;
}

View File

@@ -11,32 +11,42 @@
#define TXT_CENTER 4
#define TXT_STROKE 8
struct offset_t
{
int x;
int y;
int w;
};
struct textFile_t
{
int boxWidth; // Anchura de la caja de cada caracter en el png
int boxHeight; // Altura de la caja de cada caracter en el png
offset_t offset[128]; // Vector con las posiciones y ancho de cada letra
};
// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(std::string file, bool verbose = false);
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text
{
private:
struct offset_t
{
int x;
int y;
int w;
};
// Objetos y punteros
Sprite *sprite; // Objeto con los graficos para el texto
Sprite *sprite; // Objeto con los graficos para el texto
Texture *texture; // Textura con los bitmaps del texto
// Variables
int boxWidth; // Anchura de la caja de cada caracter en el png
int boxHeight; // Altura de la caja de cada caracter en el png
int boxWidth; // Anchura de la caja de cada caracter en el png
int boxHeight; // Altura de la caja de cada caracter en el png
bool fixedWidth; // Indica si el texto se ha de escribir con longitud fija en todas las letras
offset_t offset[128]; // Vector con las posiciones y ancho de cada letra
// Inicializa el vector de offsets desde un fichero
void initOffsetFromFile(std::string file);
public:
// Constructor
Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer);
Text(std::string textFile, Texture *texture, SDL_Renderer *renderer);
Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer);
// Destructor
~Text();
@@ -64,6 +74,9 @@ public:
// Recarga la textura
void reLoadTexture();
// Establece si se usa un tamaño fijo de letra
void setFixedWidth(bool value);
};
#endif

View File

@@ -64,6 +64,16 @@ enum palette_e
p_zxarne
};
// Posiciones de las notificaciones
enum not_pos_e
{
pos_top,
pos_bottom,
pos_left,
pos_middle,
pos_right
};
// Estructura para saber la seccion y subseccion del programa
struct section_t
{
@@ -94,6 +104,7 @@ struct input_t
struct online_t
{
bool enabled; // Indica si se quiere usar el modo online o no
bool sessionEnabled; // Indica ya se ha hecho login
std::string server; // Servidor para los servicios online
int port; // Puerto del servidor
std::string gameID; // Identificador del juego para los servicios online
@@ -101,6 +112,22 @@ struct online_t
int score; // Puntuación almacenada online
};
// Estructura con opciones de la pantalla
struct op_screen_t
{
int windowWidth; // Ancho de la ventana
int windowHeight; // Alto de la ventana
};
// Estructura para las opciones de las notificaciones
struct op_notification_t
{
not_pos_e posH; // Ubicación de las notificaciones en pantalla
not_pos_e posV; // Ubicación de las notificaciones en pantalla
bool sound; // Indica si las notificaciones suenan
color_t color; // Color de las notificaciones
};
// Estructura con todas las opciones de configuración del programa
struct options_t
{
@@ -108,17 +135,24 @@ struct options_t
Uint8 playerSelected; // Jugador seleccionado para el modo 1P
std::vector<input_t> input; // Modo de control (teclado o mando)
Uint8 language; // Idioma usado en el juego
Uint32 fullScreenMode; // Contiene el valor del modo de pantalla completa
Uint8 windowSize; // Contiene el valor por el que se multiplica el tamaño de la ventana
Uint32 filter; // Filtro usado para el escalado de la imagen
bool vSync; // Indica si se quiere usar vsync o no
int screenWidth; // Ancho de la pantalla/ventana
int screenHeight; // Alto de la pantalla/ventana
bool integerScale; // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa
bool keepAspect; // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa
bool borderEnabled; // Indica si ha de mostrar el borde en el modo de ventana
float borderSize; // Porcentaje de borde que se añade a lo ventana
online_t online; // Datos del servicio online
Uint32 videoMode; // Contiene el valor del modo de pantalla completa
int windowSize; // Contiene el valor por el que se multiplica el tamaño de la ventana
Uint32 filter; // Filtro usado para el escalado de la imagen
bool vSync; // Indica si se quiere usar vsync o no
int gameWidth; // Ancho de la resolucion nativa del juego
int gameHeight; // Alto de la resolucion nativa del juego
bool integerScale; // Indica si el escalado de la imagen ha de ser entero en el modo a pantalla completa
bool keepAspect; // Indica si se ha de mantener la relación de aspecto al poner el modo a pantalla completa
bool borderEnabled; // Indica si ha de mostrar el borde en el modo de ventana
int borderWidth; // Cantidad de pixels que se añade en el borde de la ventana
int borderHeight; // Cantidad de pixels que se añade en el borde de la ventana
palette_e palette; // Paleta de colores a usar en el juego
bool console; // Indica si ha de mostrar información por la consola de texto
online_t online; // Datos del servicio online
op_screen_t screen; // Opciones relativas a la clase screen
op_notification_t notifications; // Opciones relativas a las notificaciones;
};
// Calcula el cuadrado de la distancia entre dos puntos

View File

@@ -40,7 +40,7 @@ Director::Director(std::string path)
input = new Input(asset->get("controllerdb.txt"));
initInput();
screen = new Screen(window, renderer, asset, options, GAME_WIDTH, GAME_HEIGHT);
screen = new Screen(window, renderer, asset, options);
// Inicializa los servicios online
initOnline();
@@ -123,7 +123,14 @@ bool Director::initSDL()
}
// Crea la ventana
window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, options->screenWidth * options->windowSize, options->screenHeight * options->windowSize, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
int incW = 0;
int incH = 0;
if (options->borderEnabled)
{
incW = options->borderWidth * 2;
incH = options->borderHeight * 2;
}
window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (options->gameWidth + incW) * options->windowSize, (options->gameHeight + incH) * options->windowSize, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
if (window == nullptr)
{
printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError());
@@ -152,7 +159,7 @@ bool Director::initSDL()
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(renderer, options->screenWidth, options->screenHeight);
SDL_RenderSetLogicalSize(renderer, options->gameWidth, options->gameHeight);
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
@@ -314,18 +321,17 @@ void Director::initOptions()
inp.deviceType = INPUT_USE_GAMECONTROLLER;
options->input.push_back(inp);
options->fullScreenMode = 0;
options->videoMode = 0;
options->windowSize = 3;
options->language = ba_BA;
options->difficulty = DIFFICULTY_NORMAL;
options->playerSelected = 0;
options->filter = FILTER_NEAREST;
options->vSync = true;
options->screenWidth = GAME_WIDTH;
options->screenHeight = GAME_HEIGHT;
options->integerScale = true;
options->keepAspect = true;
options->borderSize = 0.0f;
options->borderWidth = 0;
options->borderHeight = 0;
options->borderEnabled = false;
// Online
@@ -381,12 +387,12 @@ bool Director::loadConfigFile()
}
// Normaliza los valores
const bool a = options->fullScreenMode == 0;
const bool b = options->fullScreenMode == SDL_WINDOW_FULLSCREEN;
const bool c = options->fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP;
const bool a = options->videoMode == 0;
const bool b = options->videoMode == SDL_WINDOW_FULLSCREEN;
const bool c = options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP;
if (!(a || b || c))
{
options->fullScreenMode = 0;
options->videoMode = 0;
}
if (options->windowSize < 1 || options->windowSize > 4)
@@ -412,17 +418,17 @@ bool Director::saveConfigFile()
// Escribe en el fichero
file << "## VISUAL OPTIONS\n";
if (options->fullScreenMode == 0)
if (options->videoMode == 0)
{
file << "fullScreenMode=0\n";
}
else if (options->fullScreenMode == SDL_WINDOW_FULLSCREEN)
else if (options->videoMode == SDL_WINDOW_FULLSCREEN)
{
file << "fullScreenMode=SDL_WINDOW_FULLSCREEN\n";
}
else if (options->fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
else if (options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
file << "fullScreenMode=SDL_WINDOW_FULLSCREEN_DESKTOP\n";
}
@@ -442,9 +448,8 @@ bool Director::saveConfigFile()
file << "integerScale=" + boolToString(options->integerScale) + "\n";
file << "keepAspect=" + boolToString(options->keepAspect) + "\n";
file << "borderEnabled=" + boolToString(options->borderEnabled) + "\n";
file << "borderSize=" + std::to_string(options->borderSize) + "\n";
file << "screenWidth=" + std::to_string(options->screenWidth) + "\n";
file << "screenHeight=" + std::to_string(options->screenHeight) + "\n";
file << "borderWidth=" + std::to_string(options->borderWidth) + "\n";
file << "borderHeight=" + std::to_string(options->borderHeight) + "\n";
file << "\n## OTHER OPTIONS\n";
file << "language=" + std::to_string(options->language) + "\n";
@@ -536,7 +541,7 @@ void Director::initOnline()
// Obten el Jailer ID
if (options->online.jailerID == "")
{ // Jailer ID no definido
screen->showText("No ha especificado ningun Jailer ID");
screen->showNotification("No ha especificado ningun Jailer ID");
std::cout << "No ha especificado ningun Jailer ID" << std::endl;
}
else
@@ -548,16 +553,16 @@ void Director::initOnline()
// Obtiene la información online
if (jscore::initOnlineScore(options->online.gameID))
{
screen->showText(options->online.jailerID + " ha iniciado sesion");
screen->showNotification(options->online.jailerID + " ha iniciado sesion");
std::cout << options->online.jailerID << " ha iniciado sesion" << std::endl;
}
else
{
screen->showText("Fallo al conectar a " + options->online.server);
screen->showNotification("Fallo al conectar a " + options->online.server);
std::cout << "Fallo al conectar a " << options->online.server << std::endl;
options->online.enabled = false;
options->online.enabled = false;
return;
}
@@ -565,7 +570,7 @@ void Director::initOnline()
const int points = jscore::getUserPoints(options->online.gameID, options->online.jailerID);
if (points == 0)
{ // Fallo de conexión o no hay registros
screen->showText("No se ha podido obtener la puntuacion online");
screen->showNotification("No se ha podido obtener la puntuacion online");
std::cout << "No se ha podido obtener la puntuacion online" << std::endl;
}
else
@@ -581,19 +586,19 @@ bool Director::setOptions(options_t *options, std::string var, std::string value
// Indicador de éxito en la asignación
bool success = true;
if (var == "fullScreenMode")
if (var == "videoMode")
{
if (value == "SDL_WINDOW_FULLSCREEN_DESKTOP")
{
options->fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
options->videoMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
}
else if (value == "SDL_WINDOW_FULLSCREEN")
{
options->fullScreenMode = SDL_WINDOW_FULLSCREEN;
options->videoMode = SDL_WINDOW_FULLSCREEN;
}
else
{
options->fullScreenMode = 0;
options->videoMode = 0;
}
}
@@ -638,23 +643,14 @@ bool Director::setOptions(options_t *options, std::string var, std::string value
options->borderEnabled = stringToBool(value);
}
else if (var == "borderSize")
else if (var == "borderWidth")
{
options->borderSize = std::stof(value);
if (options->borderSize < 0.0f || options->borderSize > 0.5f)
{
options->borderSize = 0.1f;
}
options->borderWidth = std::stoi(value);
}
else if (var == "screenWidth")
else if (var == "borderHeight")
{
options->screenWidth = std::stoi(value);
}
else if (var == "screenHeight")
{
options->screenHeight = std::stoi(value);
options->borderHeight = std::stoi(value);
}
else if (var == "language")

View File

@@ -744,12 +744,12 @@ bool Game::sendOnlineScore()
if (jscore::updateUserPoints("coffee_crisis", options->online.jailerID, score))
{
options->online.score = score;
screen->showText("PUNTUACION ENVIADA: " + std::to_string(score) + " PUNTOS");
screen->showNotification("PUNTUACION ENVIADA: " + std::to_string(score) + " PUNTOS");
return true;
}
else
{
screen->showText("NO SE HA PODIDO ENVIAR LA PUNTUACION");
screen->showNotification("NO SE HA PODIDO ENVIAR LA PUNTUACION");
return false;
}
}

View File

@@ -215,7 +215,7 @@ void Intro::checkEventHandler()
break;
case SDL_SCANCODE_F5:
screen->showText("HOLA MAMA!");
screen->showNotification("HOLA MAMA!");
break;
default:

View File

@@ -88,7 +88,7 @@ void Logo::checkEventHandler()
break;
case SDL_SCANCODE_F5:
screen->showText("Conectado a Jailers.net");
screen->showNotification("Conectado a Jailers.net");
break;
default:

View File

@@ -426,7 +426,7 @@ void Title::update()
case 6: // Display mode
switchFullScreenModeVar();
if (options->fullScreenMode != 0)
if (options->videoMode != 0)
{
menu.options->setSelectable(8, false);
menu.options->setGreyed(8, true);
@@ -742,20 +742,20 @@ void Title::updateBG()
// Cambia el valor de la variable de modo de pantalla completa
void Title::switchFullScreenModeVar()
{
switch (options->fullScreenMode)
switch (options->videoMode)
{
case 0:
options->fullScreenMode = SDL_WINDOW_FULLSCREEN;
options->videoMode = SDL_WINDOW_FULLSCREEN;
break;
case SDL_WINDOW_FULLSCREEN:
options->fullScreenMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
options->videoMode = SDL_WINDOW_FULLSCREEN_DESKTOP;
break;
case SDL_WINDOW_FULLSCREEN_DESKTOP:
options->fullScreenMode = 0;
options->videoMode = 0;
break;
default:
options->fullScreenMode = 0;
options->videoMode = 0;
break;
}
}
@@ -869,7 +869,7 @@ void Title::updateMenuLabels()
i++;
// DISPLAY MODE - OPTIONS
switch (options->fullScreenMode)
switch (options->videoMode)
{
case 0:
menu.options->setItemCaption(i, lang->getText(4)); // WINDOW
@@ -945,7 +945,7 @@ void Title::updateMenuLabels()
// Aplica las opciones de menu seleccionadas
void Title::applyOptions()
{
screen->setVideoMode(options->fullScreenMode);
screen->setVideoMode(options->videoMode);
lang->setLang(options->language);