Compare commits

...

47 Commits

Author SHA1 Message Date
08031810c9 Añadidas las unidades para trabajar con paletas 2024-02-05 16:43:30 +01:00
16baf48d8c Añadidos ficheros .gif 2024-02-05 16:33:53 +01:00
07caf71ce3 demo: El teclado se crea y se destruye según se use o no 2023-09-16 12:50:51 +02:00
c656d48b72 demo: El teclado se crea y se destruye según se use o no 2023-09-13 18:30:12 +02:00
2d03333463 on_screen_keyboard: arreglado bug al reducir el numero de columna o fila 2023-08-18 08:04:13 +02:00
477fc35e29 on_screen_keyboard: Añadidos bordes 2023-05-28 19:45:32 +02:00
d2e94ce74b on_screen_keyboard: Mejorada la calidad del cursor
on_screen_keyboard: Compatibilidad con fuentes de texto de tamaño variable
2023-05-28 19:35:49 +02:00
120c3791cf on_screen_keyboard: Ya se pueden añadir y quitar caracteres al texto de salida 2023-05-28 18:33:52 +02:00
921f9d2606 Input: Modificado el input por defecto para la acción de cancelar con teclado 2023-05-28 18:26:33 +02:00
c51eb06a61 on_screen_keyboard: Ya se dibuja el cursor 2023-05-28 17:44:59 +02:00
cc421e56ea on_screen_keyboard: Ya se dibuja el teclado en la pantalla 2023-05-28 12:58:02 +02:00
ad9a3fb594 utils: Añadida la función randColor 2023-05-28 11:58:34 +02:00
5d58d24cb9 on_screen_keyboard: Se empiezan a dibujar algunas teclas en pantalla 2023-05-28 10:38:04 +02:00
2b5a2cb588 utils: Añadidas las funciones darkenColor y lightenColor 2023-05-28 09:17:30 +02:00
73849a2fef on_screen_keyboard: Ya dibuja el objeto básico en pantalla 2023-05-28 09:09:26 +02:00
54947dce2d OnScreenKeyboard: Creado el esqueleto base 2023-05-26 11:00:51 +02:00
40701d9029 input: Retocados los mensajes de información 2023-05-26 08:43:20 +02:00
1746e38a56 demo: Pequeños retoques en el efecto de fuego 2023-05-26 08:39:43 +02:00
c12e8841b4 demo: Optimizado el calculo del efecto de fuego 2023-05-25 22:16:59 +02:00
ab90709963 demo: El efecto de fuego se ha optimizado pintando los pixels en una textura 2023-05-25 20:42:15 +02:00
6012b6ac5f demo: Se puede cambiar el efecto de fondo desde el teclado 2023-05-25 17:13:44 +02:00
c8960704c1 demo: El efecto de fuego ocupa toda la pantalla 2023-05-25 12:51:15 +02:00
f2ea6dbdb9 demo: Posibilidad de modificar el efecto de fuego con el teclado 2023-05-25 12:13:57 +02:00
f13947e73c demo: fire effect arreglado bug en la creación de la primera linea del efecto 2023-05-25 07:22:14 +02:00
5fa0c40102 demo: Añadido efecto de fuego en el fondo 2023-05-24 21:21:39 +02:00
bb6894e297 demo: Preparado todo para empezar a trabajar en el efecto de fuego 2023-05-24 18:37:46 +02:00
83d230846e demo: convertido todo el codigo que estava a lo bruto en el main a funciones y procedimientos 2023-05-24 17:43:38 +02:00
51c0a97a8a (cambio de ordenador) 2023-05-24 10:13:51 +02:00
1a40212b7a demo: Modificado el titulo de la ventana 2023-05-23 22:56:30 +02:00
0674e44b52 demo: Modificado el texto en pantalla 2023-05-23 22:55:56 +02:00
4424f2c2d3 input: Mejorado el texto informativo al inicializar el objeto 2023-05-23 20:59:54 +02:00
cb8d8e19e1 input fix: clearBindings no borraba completamente el vector de asignaciones 2023-05-23 20:12:07 +02:00
aca80e43a5 input: Añadido clearBindings() 2023-05-23 20:09:31 +02:00
71a81755d0 input: Añadidos más inputs por defecto 2023-05-23 20:07:29 +02:00
92aae07fd1 input: optimizado el constructor 2023-05-23 18:30:30 +02:00
bc017c1d55 demo: optimizada la inicialización de input 2023-05-23 18:27:27 +02:00
51518f3bd8 input: añadidas asignaciones por defecto para teclado y mando 2023-05-23 18:24:17 +02:00
82b2b8bf57 input: el nombre de los mandos ya no se redimensiona ni se añade el índice 2023-05-23 18:10:22 +02:00
5581034487 Demo: añadido control con mando 2023-05-23 17:46:37 +02:00
ae6477c2ea Eliminados los comentarios de creación y destrucción de objetos 2023-05-23 17:41:35 +02:00
c31bfc6cae using namespace std en todos los ficheros 2023-05-23 17:40:12 +02:00
5a5bbf7f73 Actualizado Makefile con windows_debug 2023-05-23 17:28:40 +02:00
f11469d06b fix: menu.h usaba variables antiguas de input 2023-05-23 17:16:36 +02:00
a61dda4875 Input unit: Generalizados los tipos de input. Ya no son específicos de cada juego 2023-05-23 17:11:21 +02:00
14f970011e Demo: añadida la clase input 2023-05-07 19:51:00 +02:00
1923347da9 Añadidos colores al fondo 2023-05-07 19:00:44 +02:00
5363433871 Screen: resolucion del juego y del overlay independientes 2023-05-07 18:33:03 +02:00
37 changed files with 4264 additions and 405 deletions

View File

@@ -6,6 +6,10 @@ windows:
g++ $(source) -std=c++11 -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o "$(executable).exe" g++ $(source) -std=c++11 -Wall -Os -lmingw32 -lws2_32 -lSDL2main -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows -o "$(executable).exe"
strip -s -R .comment -R .gnu.version "$(executable).exe" --strip-unneeded strip -s -R .comment -R .gnu.version "$(executable).exe" --strip-unneeded
windows_debug:
@echo off
g++ $(source) -D DEBUG -std=c++11 -Wall -lmingw32 -lws2_32 -lSDL2main -lSDL2 -static-libstdc++ -o "$(executable)_debug.exe"
macos: macos:
clang++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -o "$(executable)" clang++ $(source) -std=c++11 -Wall -Os -lSDL2 -ffunction-sections -fdata-sections -o "$(executable)"

BIN
data/debug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

194
data/debug.txt Normal file
View File

@@ -0,0 +1,194 @@
# box width
5
# box height
5
# 32 espacio ( )
3
# 33 !
1
# 34 "
3
# 35 #
3
# 36 $
3
# 37 %
3
# 38 &
3
# 39 '
1
# 40 (
2
# 41 )
2
# 42 *
3
# 43 +
3
# 44 ,
1
# 45 -
3
# 46 .
1
# 47 /
3
# 48 0
3
# 49 1
3
# 50 2
3
# 51 3
3
# 52 4
3
# 53 5
3
# 54 6
3
# 55 7
3
# 56 8
3
# 57 9
3
# 58 :
1
# 59 ;
1
# 60 <
3
# 61 =
3
# 62 >
3
# 63 ?
3
# 64 @
3
# 65 A
3
# 66 B
3
# 67 C
3
# 68 D
3
# 69 E
3
# 70 F
3
# 71 G
3
# 72 H
3
# 73 I
3
# 74 J
3
# 75 K
3
# 76 L
3
# 77 M
3
# 78 N
3
# 79 O
3
# 80 P
3
# 81 Q
3
# 82 R
3
# 83 S
3
# 84 T
3
# 85 U
3
# 86 V
3
# 87 W
3
# 88 X
3
# 89 Y
3
# 90 Z
3
# 91 [
2
# 92 \
3
# 93 ]
2
# 94 ^
3
# 95 _
3
# 96 `
2
# 97 a
3
# 98 b
3
# 99 c
3
# 100 d
3
# 101 e
3
# 102 f
3
# 103 g
3
# 104 h
3
# 105 i
3
# 106 j
3
# 107 k
3
# 108 l
3
# 109 m
3
# 110 n
3
# 111 o
3
# 112 p
3
# 113 q
3
# 114 r
3
# 115 s
3
# 116 t
3
# 117 u
3
# 118 v
3
# 119 w
3
# 120 x
3
# 121 y
3
# 122 z
3
# 123 {
3
# 124 |
3
# 125 }
3
# 126 ~
5

1144
data/gamecontrollerdb.txt Normal file

File diff suppressed because it is too large Load Diff

BIN
data/nokia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

194
data/nokia.txt Normal file
View File

@@ -0,0 +1,194 @@
# box width
8
# box height
8
# 32 espacio ( )
4
# 33 !
2
# 34 "
3
# 35 #
5
# 36 $
5
# 37 %
6
# 38 &
6
# 39 '
1
# 40 (
3
# 41 )
3
# 42 *
5
# 43 +
5
# 44 ,
2
# 45 -
4
# 46 .
2
# 47 /
3
# 48 0
5
# 49 1
3
# 50 2
5
# 51 3
5
# 52 4
5
# 53 5
5
# 54 6
5
# 55 7
5
# 56 8
5
# 57 9
5
# 58 :
2
# 59 ;
2
# 60 <
4
# 61 =
4
# 62 >
4
# 63 ?
5
# 64 @
6
# 65 A
5
# 66 B
5
# 67 C
5
# 68 D
5
# 69 E
5
# 70 F
5
# 71 G
5
# 72 H
5
# 73 I
2
# 74 J
4
# 75 K
6
# 76 L
4
# 77 M
7
# 78 N
6
# 79 O
6
# 80 P
5
# 81 Q
6
# 82 R
5
# 83 S
4
# 84 T
6
# 85 U
5
# 86 V
6
# 87 W
7
# 88 X
6
# 89 Y
6
# 90 Z
5
# 91 [
2
# 92 \
3
# 93 ]
2
# 94 ^
3
# 95 _
6
# 96 `
2
# 97 a
5
# 98 b
5
# 99 c
4
# 100 d
5
# 101 e
5
# 102 f
3
# 103 g
5
# 104 h
5
# 105 i
2
# 106 j
3
# 107 k
5
# 108 l
2
# 109 m
8
# 110 n
5
# 111 o
5
# 112 p
5
# 113 q
5
# 114 r
4
# 115 s
4
# 116 t
3
# 117 u
5
# 118 v
5
# 119 w
7
# 120 x
5
# 121 y
5
# 122 z
5
# 123 { -> ñ
5
# 124 | -> ç
5
# 125 }
0
# 126 ~
0

BIN
data/pal01.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

BIN
data/pal02.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

BIN
data/williams.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

794
main.cpp
View File

@@ -14,52 +14,190 @@ Código fuente creado por JailDesigner
#include "units/movingsprite.h" #include "units/movingsprite.h"
#include "units/texture.h" #include "units/texture.h"
#include "units/screen.h" #include "units/screen.h"
#include "units/input.h"
#include "units/on_screen_keyboard.h"
#include "quickcg.h"
using namespace QuickCG;
using namespace std;
// Punteros
SDL_Event *event; SDL_Event *event;
SDL_Window *window; SDL_Window *window;
SDL_Renderer *renderer; SDL_Renderer *renderer;
Uint32 ticks = 0; Asset *asset;
Uint32 ticksSpeed = 15; JA_Music_t *music;
int counter = 0; JA_Sound_t *sound;
Input *input;
struct options_t *options;
Screen *screen;
Text *text;
Text *debugText;
Texture *texture;
MovingSprite *sprite;
OnScreenKeyboard *osk = nullptr;
// Variables de uso general
Uint32 ticks = 0; // Variable para la frecuencia de actualización de la lógica del programa
const Uint32 ticksSpeed = 15; // Variable para la frecuencia de actualización de la lógica del programa
bool should_exit = false; // Variable para saber si ha terminado el progra,a
int counter = 0; // Contador para lo que se necesite
string controllerName; // Nombre del primer mando detectado
string inputPressed; // Texto con el último input que se ha pulsado
int fx = 0; // Efecto seleccionado para el fondo
// 0 - Degradado
// 1 - Fuego
int fxTotal = 2; // Cantidad total de efectos disponibles para el fondo
// Variables para el efecto del degradado
int gradColorMin = 64; // Minimo color más alto del degradado int gradColorMin = 64; // Minimo color más alto del degradado
int gradColorMax = 192; // Minimo color más alto del degradado int gradColorMax = 192; // Minimo color más alto del degradado
int gradCurrentColor = 192; // Color actual más alto del degradado int gradCurrentColor = 192; // Color actual más alto del degradado
int gradBreathDirection = 0; // Indica si gradCurrentColor crece o decrece int gradBreathDirection = 0; // Indica si gradCurrentColor crece o decrece
int main(int argc, char *argv[]) // Variables para el efecto de fuego
const int fireDesp = 3; // Desplazamiento inferior del efecto de fuego para eliminar las primeras filas
const int fireWidth = 320; // Ancho del efecto de fuego
const int fireHeight = 240 + fireDesp; // Alto del efecto de fuego
Uint8 fire[fireHeight][fireWidth]; // Buffer con el fuego
Uint32 palette[256]; // Paleta de color para el fuego
int fireModifier = 28; // Valor para modificar el efecto de fuego (0-30)
SDL_Texture *fireTexture; // Textura donde pintar los pixels del fuego
Uint32 *fireBuffer; // Ubiación donde se guardan los pixeles del fuego
int pitch; // No se utiliza pero se necesita para dibujar los pixeles en la textura
SDL_Rect fireSource = {0, 0, fireWidth, fireHeight - fireDesp}; // Parte de la textura donde está el efecto de fuego que se copiará a la pantalla
// Inicializa las opciones
void initOptions();
// Inicializa la lista de recursos
void initAsset(char *argv[]);
// Inicializa SDL
void initSDL();
// Inicializa la ventana
void initWindow();
// Inicializa el gestor de eventos
void initEvent();
// Inicializa jail_audio
void initJailAudio();
// Inicializa el objeto screen
void initScreen();
// Inicializa el objeto input
void initInput();
// Inicializa el texto
void initText();
// Inicializa el teclado en pantalla
void initOnScreenKeyboard();
// Inicializa el sprite
void initSprite();
// Inicializa el efecto de fuego
void initFire();
// Inicializa todo
void initAll(char *argv[]);
// Comprueba el teclado y los eventos
void checkEvents();
// Comprueba el objeto input
void checkInput();
// Actualiza el sprite
void updateSprite();
// Actualiza el efecto de degradado
void updateGradient();
// Actualiza el efecto de fuego
void updateFire();
// Actualiza el efecto de fondo
void updateFX();
// Actualiza la lógica del programa
void update();
// Dibuja un degradado de fondo
void renderGradient();
// Dibuja el efecto de fuego
void renderFire();
// Dibuja el efecto de fondo
void renderFX();
// Dibuja el texto
void renderText();
// Dibuja los elementos del programa en pantalla
void render();
// Libera la memoria reservada
void freeAll();
// Inicializa las opciones
void initOptions()
{ {
// Inicializa las opciones options = new options_t;
struct options_t *options = new options_t;
initOptions(options); initOptions(options);
options->screen.nativeWidth = 320; options->screen.nativeWidth = 320;
options->screen.nativeHeight = 240; options->screen.nativeHeight = 240;
options->screen.nativeZoom = 1; options->screen.nativeZoom = 2;
options->screen.windowZoom = 2; options->screen.windowZoom = 1;
options->console = false; options->console = true;
}
// Inicializa la lista de recursos // Inicializa la lista de recursos
Asset *asset = new Asset(argv[0]); void initAsset(char *argv[])
{
asset = new Asset(argv[0]);
asset->add("/data/music.ogg", t_music); asset->add("/data/music.ogg", t_music);
asset->add("/data/sound.wav", t_sound); asset->add("/data/sound.wav", t_sound);
asset->add("/data/smb2.txt", t_font); asset->add("/data/smb2.txt", t_font);
asset->add("/data/smb2.png", t_bitmap); asset->add("/data/smb2.png", t_bitmap);
asset->add("/data/debug.txt", t_font);
asset->add("/data/debug.png", t_bitmap);
asset->add("/data/nokia.txt", t_font);
asset->add("/data/nokia.png", t_bitmap);
asset->add("/data/z80.png", t_bitmap); asset->add("/data/z80.png", t_bitmap);
asset->add("/data/notify.png", t_bitmap); asset->add("/data/notify.png", t_bitmap);
asset->add("/data/notify.wav", t_sound); asset->add("/data/notify.wav", t_sound);
asset->add("/data/gamecontrollerdb.txt", t_data);
asset->setVerbose(options->console); asset->setVerbose(options->console);
if (!asset->check()) if (!asset->check())
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
}
// Inicializa SDL y la ventana // Inicializa SDL
void initSDL()
{
SDL_Init(SDL_INIT_EVERYTHING); SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("jail_engine_demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, options->screen.nativeWidth * options->screen.nativeZoom * options->screen.windowZoom, options->screen.nativeHeight * options->screen.nativeZoom * options->screen.windowZoom, SDL_WINDOW_SHOWN); }
// window = SDL_CreateWindow("jail_engine_demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 240, SDL_WINDOW_SHOWN);
// Inicializa la ventana
void initWindow()
{
window = SDL_CreateWindow("Jail Engine DEMO", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, options->screen.nativeWidth * options->screen.nativeZoom * options->screen.windowZoom, options->screen.nativeHeight * options->screen.nativeZoom * options->screen.windowZoom, SDL_WINDOW_SHOWN);
if (window != nullptr) if (window != nullptr)
{ {
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == nullptr) if (renderer != nullptr)
{
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
}
else
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -68,25 +206,82 @@ int main(int argc, char *argv[])
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
event = new SDL_Event(); }
// Inicializa jail_audio // Inicializa el gestor de eventos
void initEvent()
{
event = new SDL_Event();
}
// Inicializa jail_audio
void initJailAudio()
{
JA_Init(48000, AUDIO_S16, 2); JA_Init(48000, AUDIO_S16, 2);
JA_Music_t *music;
JA_Sound_t *sound;
music = JA_LoadMusic(asset->get("music.ogg").c_str()); music = JA_LoadMusic(asset->get("music.ogg").c_str());
sound = JA_LoadSound(asset->get("sound.wav").c_str()); sound = JA_LoadSound(asset->get("sound.wav").c_str());
// JA_PlayMusic(music, true);
}
// Inicializa el objeto screen // Inicializa el objeto screen
Screen *screen = new Screen(window, renderer, options); void initScreen()
{
screen = new Screen(window, renderer, options);
screen->addNotifier(asset->get("notify.png"), asset->get("smb2.png"), asset->get("smb2.txt"), asset->get("notify.wav")); screen->addNotifier(asset->get("notify.png"), asset->get("smb2.png"), asset->get("smb2.txt"), asset->get("notify.wav"));
}
// Inicializa el texto // Inicializa el objeto input
Text *text = new Text(asset->get("smb2.txt"), asset->get("smb2.png"), renderer); void initInput()
{
input = new Input(asset->get("gamecontrollerdb.txt"), options->console);
controllerName = input->getNumControllers() > 0 ? input->getControllerName(0) : "No se ha encontrado ningun mando";
}
// Inicializa el sprite // Inicializa el texto
Texture *texture = new Texture(renderer, asset->get("z80.png")); void initText()
MovingSprite *sprite = new MovingSprite(); {
text = new Text(asset->get("smb2.txt"), asset->get("smb2.png"), renderer);
debugText = new Text(asset->get("debug.txt"), asset->get("debug.png"), renderer);
}
// Inicializa el teclado en pantalla
void initOnScreenKeyboard()
{
osk = new OnScreenKeyboard(renderer, input, asset->get("nokia.png"), asset->get("nokia.txt"), options, options->screen.nativeWidth - 30, options->screen.nativeHeight - 80, "JailDesigner");
osk->setBgColor({123, 99, 63});
osk->setCaption("JAILER_ID");
osk->setChars(USE_UPPER | USE_LOWER | USE_NUMBER);
}
// Elimina el teclado en pantalla
void deleteOnScreenKeyboard()
{
if (osk != nullptr)
{
delete osk;
osk = nullptr;
}
}
// Dibuja el teclado en pantalla
void renderOnScreenKeyboard()
{
if (osk != nullptr)
osk->render();
}
// Actualiza el teclado en pantalla
void updateOnScreenKeyboard()
{
if (osk != nullptr)
osk->update();
}
// Inicializa el sprite
void initSprite()
{
texture = new Texture(renderer, asset->get("z80.png"));
sprite = new MovingSprite();
sprite->setRenderer(renderer); sprite->setRenderer(renderer);
sprite->setTexture(texture); sprite->setTexture(texture);
sprite->setPosX(140); sprite->setPosX(140);
@@ -96,166 +291,436 @@ int main(int argc, char *argv[])
sprite->setSpriteClip({0, 0, 16, 32}); sprite->setSpriteClip({0, 0, 16, 32});
sprite->setVelX(1); sprite->setVelX(1);
sprite->setVelY(2); sprite->setVelY(2);
}
// Bucle principal // Inicializa el efecto de fuego
JA_PlayMusic(music, true); void initFire()
bool should_exit = false; {
while (!should_exit) // Inicializa el generador de numeros aleatorios
srand((unsigned)SDL_GetTicks());
// Inicializa el buffer de fuego
for (int y = 0; y < fireHeight; ++y)
for (int x = 0; x < fireWidth; ++x)
fire[y][x] = 0;
fireTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, fireWidth, fireHeight);
// Inicializa la paleta
for (int x = 0; x < 256; ++x)
{ {
// HSLtoRGB is used to generate colors:
// Hue goes from 0 to 85: red to yellow
// Saturation is always the maximum: 255
// Lightness is 0..255 for x=0..128, and 255 for x=128..255
ColorRGB color = HSLtoRGB(ColorHSL(x / 3, 255, min(255, x * 2)));
// Comprueba el teclado y los eventos // Pon en la paleta el color calculado
while (SDL_PollEvent(event)) palette[x] = (Uint32)16777216 * 255 + 65536 * color.r + 256 * color.g + color.b;
}
// Coloca algo de fuego en la textura
for (int x = 0; x < 100; ++x)
updateFire();
}
// Inicializa todo
void initAll(char *argv[])
{
// Inicializa las opciones
initOptions();
// Inicializa la lista de recursos
initAsset(argv);
// Inicializa SDL
initSDL();
// Inicializa la ventana
initWindow();
// Inicializa el gestor de eventos
initEvent();
// Inicializa jail_audio
initJailAudio();
// Inicializa el objeto screen
initScreen();
// Inicializa el objeto input
initInput();
// Inicializa el texto
initText();
// Inicializa el teclado en pantalla
// initOnScreenKeyboard();
// Inicializa el sprite
initSprite();
// Inicializa el efecto de fuego
initFire();
}
// Comprueba el teclado y los eventos
void checkEvents()
{
while (SDL_PollEvent(event))
{
if (event->type == SDL_QUIT)
{ {
if (event->type == SDL_QUIT) should_exit = true;
break;
}
if (event->type == SDL_KEYDOWN)
{
switch (event->key.keysym.scancode)
{ {
case SDL_SCANCODE_ESCAPE:
should_exit = true; should_exit = true;
break; break;
}
if (event->type == SDL_KEYDOWN)
{
switch (event->key.keysym.scancode)
{
case SDL_SCANCODE_ESCAPE: case SDL_SCANCODE_F1:
should_exit = true; screen->decWindowSize();
break; break;
case SDL_SCANCODE_1: case SDL_SCANCODE_F2:
screen->decWindowSize(); screen->incWindowSize();
break; break;
case SDL_SCANCODE_2: case SDL_SCANCODE_F3:
screen->incWindowSize(); ++fx %= fxTotal;
break; break;
case SDL_SCANCODE_N: case SDL_SCANCODE_F4:
screen->showNotification("Ejemplo de notificacion", "con 2 lineas de texto", 0); --fireModifier;
break; fireModifier = max(0, fireModifier);
break;
default: case SDL_SCANCODE_F5:
break; ++fireModifier;
} fireModifier = min(30, fireModifier);
break;
case SDL_SCANCODE_F6:
screen->showNotification("Ejemplo de notificacion", "con 2 lineas de texto", 0);
break;
case SDL_SCANCODE_F7:
if (osk == nullptr)
initOnScreenKeyboard();
else
deleteOnScreenKeyboard();
break;
case SDL_SCANCODE_F8:
break;
default:
break;
} }
} }
}
}
// Actualiza la lógica del programa // Comprueba el objeto input
if (SDL_GetTicks() - ticks > ticksSpeed) void checkInput()
{
inputPressed = "";
if (input->checkInput(INPUT_LEFT))
{
inputPressed = "Izquierda";
}
if (input->checkInput(INPUT_RIGHT))
{
inputPressed = "Derecha";
}
if (input->checkInput(INPUT_UP))
{
inputPressed = "Arriba";
}
if (input->checkInput(INPUT_DOWN))
{
inputPressed = "Abajo";
}
}
// Actualiza el sprite
void updateSprite()
{
if (sprite->getPosX() + sprite->getWidth() > options->screen.nativeWidth or sprite->getPosX() < 0)
{
sprite->undoMoveX();
int spr_direction = 1;
int spr_force = 1;
if (sprite->getVelX() > 0)
{ {
// Actualiza la variable spr_direction = -1;
ticks = SDL_GetTicks();
// Incrementa el contador
counter++;
// Actualiza el objeto screen
screen->update();
// Actualiza el sprite
if (sprite->getPosX() + sprite->getWidth() > options->screen.nativeWidth or sprite->getPosX() < 0)
{
sprite->undoMoveX();
int spr_direction = 1;
int spr_force = 1;
if (sprite->getVelX() > 0)
{
spr_direction = -1;
}
if (SDL_GetTicks() % 2 == 0)
{
spr_force = 2;
}
sprite->setVelX(spr_force * spr_direction);
JA_PlaySound(sound);
}
if (sprite->getPosY() + sprite->getHeight() > options->screen.nativeHeight or sprite->getPosY() < 0)
{
sprite->undoMoveY();
int spr_direction = 1;
int spr_force = 1;
if (sprite->getVelY() > 0)
{
spr_direction = -1;
}
if (SDL_GetTicks() % 2 == 0)
{
spr_force = 2;
}
sprite->setVelY(spr_force * spr_direction);
JA_PlaySound(sound);
}
sprite->update();
// Actualiza el degradado
if (counter % 1 == 0)
{
gradBreathDirection == 0 ? gradCurrentColor-- : gradCurrentColor++;
if (gradCurrentColor == gradColorMin)
{
gradBreathDirection = 1;
}
if (gradCurrentColor == gradColorMax)
{
gradBreathDirection = 0;
}
}
} }
if (SDL_GetTicks() % 2 == 0)
// Dibuja en pantalla
screen->start();
screen->clean();
// SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
// SDL_RenderClear(renderer);
// Dibuja un degradado de fondo
const int gradFirstLine = options->screen.nativeHeight / 3;
const int gradLastLine = options->screen.nativeHeight;
const int gradNumLines = gradLastLine - gradFirstLine;
const int gradColorFrom = 0;
for (int i = gradFirstLine; i < gradLastLine; ++i)
{ {
float step = ((float)(i - gradFirstLine) / gradNumLines); spr_force = 2;
int color = gradColorFrom + ((gradCurrentColor - gradColorFrom) * step);
SDL_SetRenderDrawColor(renderer, color, 0x00, 0x00, 0xFF);
SDL_RenderDrawLine(renderer, 0, i, options->screen.nativeWidth, i);
} }
sprite->setVelX(spr_force * spr_direction);
// Escribe el texto JA_PlaySound(sound);
text->setZoom(2);
text->writeCentered(options->screen.nativeWidth / 2, text->getCharacterSize(), "Jail Engine DEMO");
text->disableZoom();
text->writeCentered(options->screen.nativeWidth / 2, text->getCharacterSize() * 7, "Pulsa 'N' para mostrar");
text->writeCentered(options->screen.nativeWidth / 2, text->getCharacterSize() * 8, "una notificacion");
// Dibuja el sprite
sprite->render();
// Vuelca el buffer en pantalla
screen->blit();
// SDL_RenderPresent(renderer);
} }
if (sprite->getPosY() + sprite->getHeight() > options->screen.nativeHeight or sprite->getPosY() < 0)
{
sprite->undoMoveY();
int spr_direction = 1;
int spr_force = 1;
if (sprite->getVelY() > 0)
{
spr_direction = -1;
}
if (SDL_GetTicks() % 2 == 0)
{
spr_force = 2;
}
sprite->setVelY(spr_force * spr_direction);
JA_PlaySound(sound);
}
sprite->update();
}
// Actualiza el degradado
void updateGradient()
{
if (counter % 1 == 0)
{
gradBreathDirection == 0 ? gradCurrentColor-- : gradCurrentColor++;
if (gradCurrentColor == gradColorMin)
{
gradBreathDirection = 1;
}
if (gradCurrentColor == gradColorMax)
{
gradBreathDirection = 0;
}
}
}
// Actualiza el efecto de fuego
void updateFire()
{
const int w = fireWidth;
const int h = fireHeight;
const int mod = 157 - fireModifier;
// Bloquea la textura para poder escribir en los pixeles
SDL_LockTexture(fireTexture, NULL, (void **)&fireBuffer, &pitch);
// Crea la fila inferior del fuego con pixels aleatorios
for (int x = 0; x < w; ++x)
{
fire[h - 1][x] = rand() % 256;
fireBuffer[x + (h - 1) * 320] = palette[fire[h - 1][x]];
}
// Calcula los pixeles del efecto de fuego, desde la fila superior hasta la inferior
for (int y = 0; y < h - 1; ++y)
for (int x = 0; x < w; ++x)
{
fire[y][x] = ((fire[(y + 1) % h][(x - 1 + w) % w] + fire[(y + 1) % h][(x) % w] + fire[(y + 1) % h][(x + 1) % w] + fire[(y + 2) % h][(x) % w]) * 32) / mod;
fireBuffer[x + y * 320] = palette[fire[y][x]];
}
// Desbloquea la textura
SDL_UnlockTexture(fireTexture);
}
// Actualiza el efecto de fondo
void updateFX()
{
switch (fx)
{
case 0: // Degradado
updateGradient();
break;
case 1: // Fuego
updateFire();
break;
default:
break;
}
}
// Actualiza la lógica del programa
void update()
{
// Comprueba el teclado y los eventos
checkEvents();
// Comprueba el objeto input
checkInput();
// Actualiza la lógica del programa
if (SDL_GetTicks() - ticks > ticksSpeed)
{
// Actualiza la variable
ticks = SDL_GetTicks();
// Incrementa el contador
counter++;
// Actualiza los objetos
updateOnScreenKeyboard(); // Actualiza el teclado en pantalla
screen->update(); // Actualiza la pantalla
updateSprite(); // Actualiza el sprite
// Actualiza el efecto de fondo
updateFX();
}
}
// Dibuja un degradado de fondo
void renderGradient()
{
const int gradFirstLine = options->screen.nativeHeight / 3;
const int gradLastLine = options->screen.nativeHeight;
const int gradNumLines = gradLastLine - gradFirstLine;
const int gradColorFrom = 0;
for (int i = gradFirstLine; i < gradLastLine; ++i)
{
float step = ((float)(i - gradFirstLine) / gradNumLines);
int color = gradColorFrom + ((gradCurrentColor - gradColorFrom) * step);
SDL_SetRenderDrawColor(renderer, color, 0x00, 0x00, 0xFF);
SDL_RenderDrawLine(renderer, 0, i, options->screen.nativeWidth, i);
}
for (int i = gradLastLine; i > gradFirstLine; --i)
{
float step = ((float)(i - gradFirstLine) / gradNumLines);
int alpha = 0 + ((255 - 0) * step);
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0xFF, alpha);
SDL_RenderDrawLine(renderer, 0, gradLastLine - i, options->screen.nativeWidth, gradLastLine - i);
}
}
// Dibuja el efecto de fuego
void renderFire()
{
SDL_RenderCopy(renderer, fireTexture, &fireSource, NULL);
}
// Dibuja el efecto de fondo
void renderFX()
{
switch (fx)
{
case 0: // Degradado
renderGradient();
break;
case 1: // Fuego
renderFire();
break;
default:
break;
}
}
// Dibuja el texto
void renderText()
{
const string text1 = "Jail Engine DEMO";
const string text2 = "2023,2024 JailDesigner";
const string text3 = "Pulsa 'F1' o 'F2' para disminuir o aumentar la ventana";
const string text4 = "Pulsa 'F3' para cambiar el efecto de fondo: ";
const string text5 = "Pulsa 'F4' o 'F5' para modificar el efecto de fuego: ";
const string text6 = "Pulsa 'F6' para mostrar una notificacion";
const string text7 = "Pulsa 'F7' para mostrar u ocultar el teclado";
const string text8 = "Pulsa 'F8' para añadir o eliminar sprites";
const string text9 = "Controles:";
const string text10 = "Pulsa 'ESCAPE' para terminar el programa";
const string fxName = fx == 0 ? "Degradado" : "Fuego";
const int center = options->screen.nativeWidth / 2;
text->setZoom(2);
text->writeDX(TXT_CENTER | TXT_STROKE, center, text->getCharacterSize(), text1, 1, {255, 255, 255}, 1, {0, 0, 192});
text->disableZoom();
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 4, text2, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 7, text3, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 9, text4 + fxName, 1, {240, 240, 240}, 1, {0, 0, 192});
if (fxName == "Fuego")
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 10, text5 + to_string(fireModifier), 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 12, text6, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 13, text7, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 14, text8, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 16, text9, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 17, controllerName, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, text->getCharacterSize() * 18, inputPressed, 1, {240, 240, 240}, 1, {0, 0, 192});
debugText->writeDX(TXT_CENTER | TXT_COLOR | TXT_STROKE, center, options->screen.nativeHeight - (text->getCharacterSize() * 2), text10, 1, {240, 240, 240}, 1, {0, 0, 192});
}
// Dibuja los elementos del programa en pantalla
void render()
{
// Prepara el objeto screen para dibujar
screen->start();
screen->clean();
// Dibuja el efecto de fondo
renderFX();
// Dibuja el sprite
sprite->render();
// Dinuja el texto
renderText();
// Dibuja el teclado en pantalla
renderOnScreenKeyboard();
// Vuelca el buffer en pantalla
screen->blit();
}
// Libera la memoria reservada
void freeAll()
{
// Finaliza el sprite // Finaliza el sprite
if (sprite != nullptr) if (sprite != nullptr)
{
delete sprite; delete sprite;
}
if (texture != nullptr) if (texture != nullptr)
{
delete texture; delete texture;
}
// Finaliza el teclado en pantalla
if (osk != nullptr)
delete osk;
// Finaliza el texto // Finaliza el texto
if (text != nullptr) if (text != nullptr)
{
delete text; delete text;
} if (debugText != nullptr)
delete debugText;
// Finaliza el objeto input
if (input != nullptr)
delete input;
// Finaliza el objeto screen // Finaliza el objeto screen
if (screen != nullptr) if (screen != nullptr)
{
delete screen; delete screen;
}
// Finaliza jail_audio // Finaliza jail_audio
JA_DeleteSound(sound); JA_DeleteSound(sound);
@@ -263,24 +728,37 @@ int main(int argc, char *argv[])
// Finaliza el objeto con la lista de recuros // Finaliza el objeto con la lista de recuros
if (asset != nullptr) if (asset != nullptr)
{
delete asset; delete asset;
}
// Finaliza las opciones // Finaliza las opciones
if (options != nullptr) if (options != nullptr)
{
delete options; delete options;
}
// Finaliza SDL y la ventana // Finaliza SDL y la ventana
if (event != nullptr) if (event != nullptr)
{
delete event; delete event;
}
SDL_DestroyRenderer(renderer); SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();
}
int main(int argc, char *argv[])
{
// Inicializa todo
initAll(argv);
// Bucle principal
while (!should_exit)
{
// Actualiza la lógica del programa
update();
// Dibuja los elementos del programa en pantalla
render();
}
// Libera la memoria reservada
freeAll();
return 0; return 0;
} }

428
quickcg.cpp Normal file
View File

@@ -0,0 +1,428 @@
/*
QuickCG 20191227
Copyright (c) 2004-2019, Lode Vandevenne
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
QuickCG is an SDL codebase that wraps some of the SDL functionality.
It' used by Lode's Computer Graphics Tutorial to work with simple C++ calls
to demonstrate graphical programs.
QuickCG can handle some things that standard C++ doesn't but that are commonly useful, such as:
-drawing graphics
-a bitmap font
-simplified saving and loading of files
-reading keyboard and mouse input
-playing sound
-color models
-loading images
*/
#include "quickcg.h"
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <iostream>
#include <fstream>
namespace QuickCG
{
////////////////////////////////////////////////////////////////////////////////
// COLOR STRUCTS/////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
ColorRGB::ColorRGB(Uint8 r, Uint8 g, Uint8 b)
{
this->r = r;
this->g = g;
this->b = b;
}
ColorRGB::ColorRGB(const ColorRGB8bit &color)
{
this->r = color.r;
this->g = color.g;
this->b = color.b;
}
ColorRGB::ColorRGB()
{
this->r = 0;
this->g = 0;
this->b = 0;
}
ColorRGB8bit::ColorRGB8bit(Uint8 r, Uint8 g, Uint8 b)
{
this->r = r;
this->g = g;
this->b = b;
}
ColorRGB8bit::ColorRGB8bit(const ColorRGB &color)
{
this->r = color.r;
this->g = color.g;
this->b = color.b;
}
ColorRGB8bit::ColorRGB8bit()
{
this->r = 0;
this->g = 0;
this->b = 0;
}
// Add two colors
ColorRGB operator+(const ColorRGB &color, const ColorRGB &color2)
{
ColorRGB c;
c.r = color.r + color2.r;
c.g = color.g + color2.g;
c.b = color.b + color2.b;
return c;
}
// Subtract two colors
ColorRGB operator-(const ColorRGB &color, const ColorRGB &color2)
{
ColorRGB c;
c.r = color.r - color2.r;
c.g = color.g - color2.g;
c.b = color.b - color2.b;
return c;
}
// Multiplies a color with an integer
ColorRGB operator*(const ColorRGB &color, int a)
{
ColorRGB c;
c.r = color.r * a;
c.g = color.g * a;
c.b = color.b * a;
return c;
}
// Multiplies a color with an integer
ColorRGB operator*(int a, const ColorRGB &color)
{
ColorRGB c;
c.r = color.r * a;
c.g = color.g * a;
c.b = color.b * a;
return c;
}
// Divides a color through an integer
ColorRGB operator/(const ColorRGB &color, int a)
{
if (a == 0)
return color;
ColorRGB c;
c.r = color.r / a;
c.g = color.g / a;
c.b = color.b / a;
return c;
}
// Are both colors equal?
bool operator==(const ColorRGB &color, const ColorRGB &color2)
{
return (color.r == color2.r && color.g == color2.g && color.b == color2.b);
}
// Are both colors not equal?
bool operator!=(const ColorRGB &color, const ColorRGB &color2)
{
return (!(color.r == color2.r && color.g == color2.g && color.b == color2.b));
}
ColorHSL::ColorHSL(Uint8 h, Uint8 s, Uint8 l)
{
this->h = h;
this->s = s;
this->l = l;
}
ColorHSL::ColorHSL()
{
this->h = 0;
this->s = 0;
this->l = 0;
}
ColorHSV::ColorHSV(Uint8 h, Uint8 s, Uint8 v)
{
this->h = h;
this->s = s;
this->v = v;
}
ColorHSV::ColorHSV()
{
this->h = 0;
this->s = 0;
this->v = 0;
}
////////////////////////////////////////////////////////////////////////////////
// COLOR CONVERSIONS/////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
Convert colors from one type to another
r=red g=green b=blue h=hue s=saturation l=lightness v=value
Color components from the color structs are Uint8's between 0 and 255
color components used in the calculations are normalized between 0.0-1.0
*/
// Converts an RGB color to HSL color
ColorHSL RGBtoHSL(const ColorRGB &colorRGB)
{
float r, g, b, h = 0, s = 0, l; // this function works with floats between 0 and 1
r = colorRGB.r / 256.0;
g = colorRGB.g / 256.0;
b = colorRGB.b / 256.0;
float maxColor = std::max(r, std::max(g, b));
float minColor = std::min(r, std::min(g, b));
if (minColor == maxColor) // R = G = B, so it's a shade of grey
{
h = 0; // it doesn't matter what value it has
s = 0;
l = r; // doesn't matter if you pick r, g, or b
}
else
{
l = (minColor + maxColor) / 2;
if (l < 0.5)
s = (maxColor - minColor) / (maxColor + minColor);
if (l >= 0.5)
s = (maxColor - minColor) / (2.0 - maxColor - minColor);
if (r == maxColor)
h = (g - b) / (maxColor - minColor);
if (g == maxColor)
h = 2.0 + (b - r) / (maxColor - minColor);
if (b == maxColor)
h = 4.0 + (r - g) / (maxColor - minColor);
h /= 6; // to bring it to a number between 0 and 1
if (h < 0)
h += 1;
}
ColorHSL colorHSL;
colorHSL.h = int(h * 255.0);
colorHSL.s = int(s * 255.0);
colorHSL.l = int(l * 255.0);
return colorHSL;
}
// Converts an HSL color to RGB color
ColorRGB HSLtoRGB(const ColorHSL &colorHSL)
{
float r, g, b, h, s, l; // this function works with floats between 0 and 1
float temp1, temp2, tempr, tempg, tempb;
h = colorHSL.h / 256.0;
s = colorHSL.s / 256.0;
l = colorHSL.l / 256.0;
// If saturation is 0, the color is a shade of grey
if (s == 0)
r = g = b = l;
// If saturation > 0, more complex calculations are needed
else
{
// set the temporary values
if (l < 0.5)
temp2 = l * (1 + s);
else
temp2 = (l + s) - (l * s);
temp1 = 2 * l - temp2;
tempr = h + 1.0 / 3.0;
if (tempr > 1.0)
tempr--;
tempg = h;
tempb = h - 1.0 / 3.0;
if (tempb < 0.0)
tempb++;
// red
if (tempr < 1.0 / 6.0)
r = temp1 + (temp2 - temp1) * 6.0 * tempr;
else if (tempr < 0.5)
r = temp2;
else if (tempr < 2.0 / 3.0)
r = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - tempr) * 6.0;
else
r = temp1;
// green
if (tempg < 1.0 / 6.0)
g = temp1 + (temp2 - temp1) * 6.0 * tempg;
else if (tempg < 0.5)
g = temp2;
else if (tempg < 2.0 / 3.0)
g = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - tempg) * 6.0;
else
g = temp1;
// blue
if (tempb < 1.0 / 6.0)
b = temp1 + (temp2 - temp1) * 6.0 * tempb;
else if (tempb < 0.5)
b = temp2;
else if (tempb < 2.0 / 3.0)
b = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - tempb) * 6.0;
else
b = temp1;
}
ColorRGB colorRGB;
colorRGB.r = int(r * 255.0);
colorRGB.g = int(g * 255.0);
colorRGB.b = int(b * 255.0);
return colorRGB;
}
// Converts an RGB color to HSV color
ColorHSV RGBtoHSV(const ColorRGB &colorRGB)
{
float r, g, b, h = 0.0, s = 0.0, v; // this function works with floats between 0 and 1
r = colorRGB.r / 256.0;
g = colorRGB.g / 256.0;
b = colorRGB.b / 256.0;
float maxColor = std::max(r, std::max(g, b));
float minColor = std::min(r, std::min(g, b));
v = maxColor;
if (maxColor != 0.0) // avoid division by zero when the color is black
{
s = (maxColor - minColor) / maxColor;
}
if (s == 0.0)
{
h = 0.0; // it doesn't matter what value it has
}
else
{
if (r == maxColor)
h = (g - b) / (maxColor - minColor);
if (g == maxColor)
h = 2.0 + (b - r) / (maxColor - minColor);
if (b == maxColor)
h = 4.0 + (r - g) / (maxColor - minColor);
h /= 6.0; // to bring it to a number between 0 and 1
if (h < 0.0)
h++;
}
ColorHSV colorHSV;
colorHSV.h = int(h * 255.0);
colorHSV.s = int(s * 255.0);
colorHSV.v = int(v * 255.0);
return colorHSV;
}
// Converts an HSV color to RGB color
ColorRGB HSVtoRGB(const ColorHSV &colorHSV)
{
float r, g, b, h, s, v; // this function works with floats between 0 and 1
h = colorHSV.h / 256.0;
s = colorHSV.s / 256.0;
v = colorHSV.v / 256.0;
// if saturation is 0, the color is a shade of grey
if (s == 0.0)
r = g = b = v;
// if saturation > 0, more complex calculations are needed
else
{
float f, p, q, t;
int i;
h *= 6.0; // to bring hue to a number between 0 and 6, better for the calculations
i = int(floor(h)); // e.g. 2.7 becomes 2 and 3.01 becomes 3 or 4.9999 becomes 4
f = h - i; // the fractional part of h
p = v * (1.0 - s);
q = v * (1.0 - (s * f));
t = v * (1.0 - (s * (1.0 - f)));
switch (i)
{
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
default:
r = g = b = 0;
break;
}
}
ColorRGB colorRGB;
colorRGB.r = int(r * 255.0);
colorRGB.g = int(g * 255.0);
colorRGB.b = int(b * 255.0);
return colorRGB;
}
Uint32 RGBtoINT(const ColorRGB &colorRGB)
{
return 65536 * colorRGB.r + 256 * colorRGB.g + colorRGB.b;
}
ColorRGB INTtoRGB(Uint32 colorINT)
{
ColorRGB colorRGB;
colorRGB.r = (colorINT / 65536) % 256;
colorRGB.g = (colorINT / 256) % 256;
colorRGB.b = colorINT % 256;
return colorRGB;
}
}

189
quickcg.h Normal file
View File

@@ -0,0 +1,189 @@
/*
QuickCG 20191227
Copyright (c) 2004-2019, Lode Vandevenne
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
QuickCG is an SDL 1.2 codebase that wraps some of the SDL 1.2 functionality.
It's used by Lode's Computer Graphics Tutorial to work with simple function calls
to demonstrate graphical programs. It may or may not be of industrial strength
for games, though I've actually used it for some.
QuickCG can handle some things that standard C++ does not but that are useful, such as:
-drawing graphics
-a bitmap font
-simplified saving and loading of files
-reading keyboard and mouse input
-playing sound
-color models
-loading images
Contact info:
My email address is (puzzle the account and domain together with an @ symbol):
Domain: gmail dot com.
Account: lode dot vandevenne.
*/
#ifndef _quickcg_h_included
#define _quickcg_h_included
#include <SDL2/SDL.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <algorithm> //std::min and std::max
namespace QuickCG
{
////////////////////////////////////////////////////////////////////////////////
// useful templates//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// don't know why, but the standard C++ abs sometimes gives cryptic errors? if so use this :D
template <typename T>
const T template_abs(const T &a)
{
return (a < 0) ? -a : a;
}
// usage: std::string str = valtostr(25454.91654654f);
template <typename T>
std::string valtostr(const T &val)
{
std::ostringstream sstream;
sstream << val;
return sstream.str();
}
// usage: double val = strtoval<double>("465498.654");
template <typename T>
T strtoval(const std::string &s)
{
std::istringstream sstream(s);
T val;
sstream >> val;
return val;
}
// length is decimal precision of the floating point number
template <typename T>
std::string valtostr(const T &val, int length, bool fixed = true)
{
std::ostringstream sstream;
if (fixed)
sstream << std::fixed;
sstream << std::setprecision(length) << val;
return sstream.str();
}
////////////////////////////////////////////////////////////////////////////////
// COLOR STRUCTS/////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
struct ColorRGB8bit;
// a color with 3 components: r, g and b
struct ColorRGB
{
int r;
int g;
int b;
ColorRGB(Uint8 r, Uint8 g, Uint8 b);
ColorRGB(const ColorRGB8bit &color);
ColorRGB();
};
ColorRGB operator+(const ColorRGB &color, const ColorRGB &color2);
ColorRGB operator-(const ColorRGB &color, const ColorRGB &color2);
ColorRGB operator*(const ColorRGB &color, int a);
ColorRGB operator*(int a, const ColorRGB &color);
ColorRGB operator/(const ColorRGB &color, int a);
bool operator==(const ColorRGB &color, const ColorRGB &color2);
bool operator!=(const ColorRGB &color, const ColorRGB &color2);
static const ColorRGB RGB_Black(0, 0, 0);
static const ColorRGB RGB_Red(255, 0, 0);
static const ColorRGB RGB_Green(0, 255, 0);
static const ColorRGB RGB_Blue(0, 0, 255);
static const ColorRGB RGB_Cyan(0, 255, 255);
static const ColorRGB RGB_Magenta(255, 0, 255);
static const ColorRGB RGB_Yellow(255, 255, 0);
static const ColorRGB RGB_White(255, 255, 255);
static const ColorRGB RGB_Gray(128, 128, 128);
static const ColorRGB RGB_Grey(192, 192, 192);
static const ColorRGB RGB_Maroon(128, 0, 0);
static const ColorRGB RGB_Darkgreen(0, 128, 0);
static const ColorRGB RGB_Navy(0, 0, 128);
static const ColorRGB RGB_Teal(0, 128, 128);
static const ColorRGB RGB_Purple(128, 0, 128);
static const ColorRGB RGB_Olive(128, 128, 0);
// a color with 3 components: r, g and b
struct ColorRGB8bit
{
Uint8 r;
Uint8 g;
Uint8 b;
ColorRGB8bit(Uint8 r, Uint8 g, Uint8 b);
ColorRGB8bit(const ColorRGB &color);
ColorRGB8bit();
};
// a color with 3 components: h, s and l
struct ColorHSL
{
int h;
int s;
int l;
ColorHSL(Uint8 h, Uint8 s, Uint8 l);
ColorHSL();
};
// a color with 3 components: h, s and v
struct ColorHSV
{
int h;
int s;
int v;
ColorHSV(Uint8 h, Uint8 s, Uint8 v);
ColorHSV();
};
////////////////////////////////////////////////////////////////////////////////
// COLOR CONVERSIONS/////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
ColorHSL RGBtoHSL(const ColorRGB &colorRGB);
ColorRGB HSLtoRGB(const ColorHSL &colorHSL);
ColorHSV RGBtoHSV(const ColorRGB &colorRGB);
ColorRGB HSVtoRGB(const ColorHSV &colorHSV);
Uint32 RGBtoINT(const ColorRGB &colorRGB);
ColorRGB INTtoRGB(Uint32 colorINT);
}
#endif

View File

@@ -1,7 +1,7 @@
#include "animatedsprite.h" #include "animatedsprite.h"
// Carga la animación desde un fichero // Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose) animatedSprite_t loadAnimationFromFile(Texture *texture, string filePath, bool verbose)
{ {
// Inicializa variables // Inicializa variables
animatedSprite_t as; animatedSprite_t as;
@@ -11,9 +11,9 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
int frameHeight = 0; int frameHeight = 0;
int maxTiles = 0; int maxTiles = 0;
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1); const string filename = filePath.substr(filePath.find_last_of("\\/") + 1);
std::ifstream file(filePath); ifstream file(filePath);
std::string line; string line;
// El fichero se puede abrir // El fichero se puede abrir
if (file.good()) if (file.good())
@@ -21,9 +21,9 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
// Procesa el fichero linea a linea // Procesa el fichero linea a linea
if (verbose) if (verbose)
{ {
std::cout << "Animation loaded: " << filename << std::endl; cout << "Animation loaded: " << filename << endl;
} }
while (std::getline(file, line)) while (getline(file, line))
{ {
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación // Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]") if (line == "[animation]")
@@ -35,7 +35,7 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
do do
{ {
std::getline(file, line); getline(file, line);
// Encuentra la posición del caracter '=' // Encuentra la posición del caracter '='
int pos = line.find("="); int pos = line.find("=");
@@ -50,24 +50,24 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
else if (line.substr(0, pos) == "speed") else if (line.substr(0, pos) == "speed")
{ {
buffer.speed = std::stoi(line.substr(pos + 1, line.length())); buffer.speed = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "loop") else if (line.substr(0, pos) == "loop")
{ {
buffer.loop = std::stoi(line.substr(pos + 1, line.length())); buffer.loop = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frames") else if (line.substr(0, pos) == "frames")
{ {
// Se introducen los valores separados por comas en un vector // Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length())); stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp; string tmp;
SDL_Rect rect = {0, 0, frameWidth, frameHeight}; SDL_Rect rect = {0, 0, frameWidth, frameHeight};
while (getline(ss, tmp, ',')) while (getline(ss, tmp, ','))
{ {
// Comprueba que el tile no sea mayor que el maximo indice permitido // Comprueba que el tile no sea mayor que el maximo indice permitido
const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp); const int numTile = stoi(tmp) > maxTiles ? 0 : stoi(tmp);
rect.x = (numTile % framesPerRow) * frameWidth; rect.x = (numTile % framesPerRow) * frameWidth;
rect.y = (numTile / framesPerRow) * frameHeight; rect.y = (numTile / framesPerRow) * frameHeight;
buffer.frames.push_back(rect); buffer.frames.push_back(rect);
@@ -76,7 +76,7 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
else else
{ {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl; cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << endl;
} }
} }
} while (line != "[/animation]"); } while (line != "[/animation]");
@@ -96,22 +96,22 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
{ {
if (line.substr(0, pos) == "framesPerRow") if (line.substr(0, pos) == "framesPerRow")
{ {
framesPerRow = std::stoi(line.substr(pos + 1, line.length())); framesPerRow = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameWidth") else if (line.substr(0, pos) == "frameWidth")
{ {
frameWidth = std::stoi(line.substr(pos + 1, line.length())); frameWidth = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameHeight") else if (line.substr(0, pos) == "frameHeight")
{ {
frameHeight = std::stoi(line.substr(pos + 1, line.length())); frameHeight = stoi(line.substr(pos + 1, line.length()));
} }
else else
{ {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl; cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << endl;
} }
// Normaliza valores // Normaliza valores
@@ -138,7 +138,7 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
{ {
if (verbose) if (verbose)
{ {
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl; cout << "Warning: Unable to open " << filename.c_str() << " file" << endl;
} }
} }
@@ -146,9 +146,9 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector<std::string> *buffer) AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, string file, vector<string> *buffer)
{ {
//std::cout << "Creado AnimatedSprite" << std::endl; //cout << "Creado AnimatedSprite" << endl;
// Copia los punteros // Copia los punteros
setTexture(texture); setTexture(texture);
setRenderer(renderer); setRenderer(renderer);
@@ -177,7 +177,7 @@ AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::st
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation) AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation)
{ {
//std::cout << "Creado AnimatedSprite" << std::endl; //cout << "Creado AnimatedSprite" << endl;
// Copia los punteros // Copia los punteros
setTexture(animation->texture); setTexture(animation->texture);
setRenderer(renderer); setRenderer(renderer);
@@ -195,7 +195,7 @@ AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animati
// Destructor // Destructor
AnimatedSprite::~AnimatedSprite() AnimatedSprite::~AnimatedSprite()
{ {
//std::cout << "Destruido AnimatedSprite" << std::endl; //cout << "Destruido AnimatedSprite" << endl;
for (auto &a : animation) for (auto &a : animation)
{ {
a.frames.clear(); a.frames.clear();
@@ -204,7 +204,7 @@ AnimatedSprite::~AnimatedSprite()
} }
// Obtiene el indice de la animación a partir del nombre // Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name) int AnimatedSprite::getIndex(string name)
{ {
int index = -1; int index = -1;
@@ -217,7 +217,7 @@ int AnimatedSprite::getIndex(std::string name)
} }
} }
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl; cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << endl;
return -1; return -1;
} }
@@ -283,13 +283,13 @@ void AnimatedSprite::setCurrentFrame(int num)
} }
// Establece el valor del contador // Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num) void AnimatedSprite::setAnimationCounter(string name, int num)
{ {
animation[getIndex(name)].counter = num; animation[getIndex(name)].counter = num;
} }
// Establece la velocidad de una animación // Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed) void AnimatedSprite::setAnimationSpeed(string name, int speed)
{ {
animation[getIndex(name)].counter = speed; animation[getIndex(name)].counter = speed;
} }
@@ -301,7 +301,7 @@ void AnimatedSprite::setAnimationSpeed(int index, int speed)
} }
// Establece si la animación se reproduce en bucle // Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop) void AnimatedSprite::setAnimationLoop(string name, int loop)
{ {
animation[getIndex(name)].loop = loop; animation[getIndex(name)].loop = loop;
} }
@@ -313,7 +313,7 @@ void AnimatedSprite::setAnimationLoop(int index, int loop)
} }
// Establece el valor de la variable // Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value) void AnimatedSprite::setAnimationCompleted(string name, bool value)
{ {
animation[getIndex(name)].completed = value; animation[getIndex(name)].completed = value;
} }
@@ -331,7 +331,7 @@ bool AnimatedSprite::animationIsCompleted()
} }
// Devuelve el rectangulo de una animación y frame concreto // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index) SDL_Rect AnimatedSprite::getAnimationClip(string name, Uint8 index)
{ {
return animation[getIndex(name)].frames[index]; return animation[getIndex(name)].frames[index];
} }
@@ -343,7 +343,7 @@ SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
} }
// Carga la animación desde un vector // Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) bool AnimatedSprite::loadFromVector(vector<string> *source)
{ {
// Inicializa variables // Inicializa variables
int framesPerRow = 0; int framesPerRow = 0;
@@ -353,7 +353,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
// Indicador de éxito en el proceso // Indicador de éxito en el proceso
bool success = true; bool success = true;
std::string line; string line;
// Recorre todo el vector // Recorre todo el vector
int index = 0; int index = 0;
@@ -389,24 +389,24 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
else if (line.substr(0, pos) == "speed") else if (line.substr(0, pos) == "speed")
{ {
buffer.speed = std::stoi(line.substr(pos + 1, line.length())); buffer.speed = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "loop") else if (line.substr(0, pos) == "loop")
{ {
buffer.loop = std::stoi(line.substr(pos + 1, line.length())); buffer.loop = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frames") else if (line.substr(0, pos) == "frames")
{ {
// Se introducen los valores separados por comas en un vector // Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length())); stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp; string tmp;
SDL_Rect rect = {0, 0, frameWidth, frameHeight}; SDL_Rect rect = {0, 0, frameWidth, frameHeight};
while (getline(ss, tmp, ',')) while (getline(ss, tmp, ','))
{ {
// Comprueba que el tile no sea mayor que el maximo indice permitido // Comprueba que el tile no sea mayor que el maximo indice permitido
const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp); const int numTile = stoi(tmp) > maxTiles ? 0 : stoi(tmp);
rect.x = (numTile % framesPerRow) * frameWidth; rect.x = (numTile % framesPerRow) * frameWidth;
rect.y = (numTile / framesPerRow) * frameHeight; rect.y = (numTile / framesPerRow) * frameHeight;
buffer.frames.push_back(rect); buffer.frames.push_back(rect);
@@ -415,7 +415,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
else else
{ {
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl; cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << endl;
success = false; success = false;
} }
} }
@@ -436,22 +436,22 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
{ {
if (line.substr(0, pos) == "framesPerRow") if (line.substr(0, pos) == "framesPerRow")
{ {
framesPerRow = std::stoi(line.substr(pos + 1, line.length())); framesPerRow = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameWidth") else if (line.substr(0, pos) == "frameWidth")
{ {
frameWidth = std::stoi(line.substr(pos + 1, line.length())); frameWidth = stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameHeight") else if (line.substr(0, pos) == "frameHeight")
{ {
frameHeight = std::stoi(line.substr(pos + 1, line.length())); frameHeight = stoi(line.substr(pos + 1, line.length()));
} }
else else
{ {
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl; cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << endl;
success = false; success = false;
} }
@@ -481,7 +481,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
} }
// Establece la animacion actual // Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(std::string name) void AnimatedSprite::setCurrentAnimation(string name)
{ {
const int newAnimation = getIndex(name); const int newAnimation = getIndex(name);
if (currentAnimation != newAnimation) if (currentAnimation != newAnimation)

View File

@@ -11,10 +11,12 @@
#ifndef ANIMATEDSPRITE_H #ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H #define ANIMATEDSPRITE_H
using namespace std;
struct animation_t struct animation_t
{ {
std::string name; // Nombre de la animacion string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación int speed; // Velocidad de la animación
int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed; // Indica si ha finalizado la animación bool completed; // Indica si ha finalizado la animación
@@ -24,23 +26,23 @@ struct animation_t
struct animatedSprite_t struct animatedSprite_t
{ {
std::vector<animation_t> animations; // Vector con las diferentes animaciones vector<animation_t> animations; // Vector con las diferentes animaciones
Texture *texture; // Textura con los graficos para el sprite Texture *texture; // Textura con los graficos para el sprite
}; };
// Carga la animación desde un fichero // Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose = false); animatedSprite_t loadAnimationFromFile(Texture *texture, string filePath, bool verbose = false);
class AnimatedSprite : public MovingSprite class AnimatedSprite : public MovingSprite
{ {
private: private:
// Variables // Variables
std::vector<animation_t> animation; // Vector con las diferentes animaciones vector<animation_t> animation; // Vector con las diferentes animaciones
int currentAnimation; // Animacion activa int currentAnimation; // Animacion activa
public: public:
// Constructor // Constructor
AnimatedSprite(Texture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = "", std::vector<std::string> *buffer = nullptr); AnimatedSprite(Texture *texture = nullptr, SDL_Renderer *renderer = nullptr, string file = "", vector<string> *buffer = nullptr);
AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation); AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation);
// Destructor // Destructor
@@ -56,35 +58,35 @@ public:
void setCurrentFrame(int num); void setCurrentFrame(int num);
// Establece el valor del contador // Establece el valor del contador
void setAnimationCounter(std::string name, int num); void setAnimationCounter(string name, int num);
// Establece la velocidad de una animación // Establece la velocidad de una animación
void setAnimationSpeed(std::string name, int speed); void setAnimationSpeed(string name, int speed);
void setAnimationSpeed(int index, int speed); void setAnimationSpeed(int index, int speed);
// Establece el frame al que vuelve la animación al finalizar // Establece el frame al que vuelve la animación al finalizar
void setAnimationLoop(std::string name, int loop); void setAnimationLoop(string name, int loop);
void setAnimationLoop(int index, int loop); void setAnimationLoop(int index, int loop);
// Establece el valor de la variable // Establece el valor de la variable
void setAnimationCompleted(std::string name, bool value); void setAnimationCompleted(string name, bool value);
void setAnimationCompleted(int index, bool value); void setAnimationCompleted(int index, bool value);
// Comprueba si ha terminado la animación // Comprueba si ha terminado la animación
bool animationIsCompleted(); bool animationIsCompleted();
// Devuelve el rectangulo de una animación y frame concreto // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(std::string name = "default", Uint8 index = 0); SDL_Rect getAnimationClip(string name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0); SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0);
// Obtiene el indice de la animación a partir del nombre // Obtiene el indice de la animación a partir del nombre
int getIndex(std::string name); int getIndex(string name);
// Carga la animación desde un vector // Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source); bool loadFromVector(vector<string> *source);
// Establece la animacion actual // Establece la animacion actual
void setCurrentAnimation(std::string name = "default"); void setCurrentAnimation(string name = "default");
void setCurrentAnimation(int index = 0); void setCurrentAnimation(int index = 0);
// Actualiza las variables del objeto // Actualiza las variables del objeto

View File

@@ -2,9 +2,8 @@
#include <iostream> #include <iostream>
// Constructor // Constructor
Asset::Asset(std::string executablePath) Asset::Asset(string executablePath)
{ {
//std::cout << "Construido Asset" << std::endl;
this->executablePath = executablePath.substr(0, executablePath.find_last_of("\\/")); this->executablePath = executablePath.substr(0, executablePath.find_last_of("\\/"));
longestName = 0; longestName = 0;
verbose = true; verbose = true;
@@ -13,11 +12,10 @@ Asset::Asset(std::string executablePath)
// Destructot // Destructot
Asset::~Asset() Asset::~Asset()
{ {
//std::cout << "Destruido Asset" << std::endl;
} }
// Añade un elemento a la lista // Añade un elemento a la lista
void Asset::add(std::string file, enum assetType type, bool required, bool absolute) void Asset::add(string file, enum assetType type, bool required, bool absolute)
{ {
item_t temp; item_t temp;
temp.file = absolute ? file : executablePath + file; temp.file = absolute ? file : executablePath + file;
@@ -25,17 +23,17 @@ void Asset::add(std::string file, enum assetType type, bool required, bool absol
temp.required = required; temp.required = required;
fileList.push_back(temp); fileList.push_back(temp);
const std::string filename = file.substr(file.find_last_of("\\/") + 1); const string filename = file.substr(file.find_last_of("\\/") + 1);
longestName = SDL_max(longestName, filename.size()); longestName = SDL_max(longestName, filename.size());
} }
// Devuelve el fichero de un elemento de la lista a partir de una cadena // Devuelve el fichero de un elemento de la lista a partir de una cadena
std::string Asset::get(std::string text) string Asset::get(string text)
{ {
for (auto f : fileList) for (auto f : fileList)
{ {
const size_t lastIndex = f.file.find_last_of("/") + 1; const size_t lastIndex = f.file.find_last_of("/") + 1;
const std::string file = f.file.substr(lastIndex, std::string::npos); const string file = f.file.substr(lastIndex, string::npos);
if (file == text) if (file == text)
{ {
@@ -45,7 +43,7 @@ std::string Asset::get(std::string text)
if (verbose) if (verbose)
{ {
std::cout << "Warning: file " << text.c_str() << " not found" << std::endl; cout << "Warning: file " << text.c_str() << " not found" << endl;
} }
return ""; return "";
} }
@@ -57,10 +55,10 @@ bool Asset::check()
if (verbose) if (verbose)
{ {
std::cout << "\n** Checking files" << std::endl; cout << "\n** Checking files" << endl;
std::cout << "Executable path is: " << executablePath << std::endl; cout << "Executable path is: " << executablePath << endl;
std::cout << "Sample filepath: " << fileList.back().file << std::endl; cout << "Sample filepath: " << fileList.back().file << endl;
} }
// Comprueba la lista de ficheros clasificandolos por tipo // Comprueba la lista de ficheros clasificandolos por tipo
@@ -82,7 +80,7 @@ bool Asset::check()
{ {
if (verbose) if (verbose)
{ {
std::cout << "\n>> " << getTypeName(type).c_str() << " FILES" << std::endl; cout << "\n>> " << getTypeName(type).c_str() << " FILES" << endl;
} }
for (auto f : fileList) for (auto f : fileList)
@@ -100,13 +98,13 @@ bool Asset::check()
{ {
if (success) if (success)
{ {
std::cout << "\n** All files OK.\n" cout << "\n** All files OK.\n"
<< std::endl; << endl;
} }
else else
{ {
std::cout << "\n** A file is missing. Exiting.\n" cout << "\n** A file is missing. Exiting.\n"
<< std::endl; << endl;
} }
} }
@@ -114,13 +112,13 @@ bool Asset::check()
} }
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool Asset::checkFile(std::string path) bool Asset::checkFile(string path)
{ {
bool success = false; bool success = false;
std::string result = "ERROR"; string result = "ERROR";
// Comprueba si existe el fichero // Comprueba si existe el fichero
const std::string filename = path.substr(path.find_last_of("\\/") + 1); const string filename = path.substr(path.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(path.c_str(), "rb"); SDL_RWops *file = SDL_RWFromFile(path.c_str(), "rb");
if (file != nullptr) if (file != nullptr)
@@ -132,19 +130,19 @@ bool Asset::checkFile(std::string path)
if (verbose) if (verbose)
{ {
std::cout.setf(std::ios::left, std::ios::adjustfield); cout.setf(ios::left, ios::adjustfield);
std::cout << "Checking file: "; cout << "Checking file: ";
std::cout.width(longestName + 2); cout.width(longestName + 2);
std::cout.fill('.'); cout.fill('.');
std::cout << filename + " "; cout << filename + " ";
std::cout << " [" + result + "]" << std::endl; cout << " [" + result + "]" << endl;
} }
return success; return success;
} }
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
std::string Asset::getTypeName(int type) string Asset::getTypeName(int type)
{ {
switch (type) switch (type)
{ {

View File

@@ -7,6 +7,8 @@
#ifndef ASSET_H #ifndef ASSET_H
#define ASSET_H #define ASSET_H
using namespace std;
enum assetType enum assetType
{ {
t_bitmap, t_bitmap,
@@ -28,7 +30,7 @@ private:
// Estructura para definir un item // Estructura para definir un item
struct item_t struct item_t
{ {
std::string file; // Ruta del fichero desde la raiz del directorio string file; // Ruta del fichero desde la raiz del directorio
enum assetType type; // Indica el tipo de recurso enum assetType type; // Indica el tipo de recurso
bool required; // Indica si es un fichero que debe de existir bool required; // Indica si es un fichero que debe de existir
//bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta //bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta
@@ -36,28 +38,28 @@ private:
// Variables // Variables
int longestName; // Contiene la longitud del nombre de fichero mas largo int longestName; // Contiene la longitud del nombre de fichero mas largo
std::vector<item_t> fileList; // Listado con todas las rutas a los ficheros vector<item_t> fileList; // Listado con todas las rutas a los ficheros
std::string executablePath; // Ruta al ejecutable string executablePath; // Ruta al ejecutable
bool verbose; // Indica si ha de mostrar información por pantalla bool verbose; // Indica si ha de mostrar información por pantalla
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool checkFile(std::string executablePath); bool checkFile(string executablePath);
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
std::string getTypeName(int type); string getTypeName(int type);
public: public:
// Constructor // Constructor
Asset(std::string path); Asset(string path);
// Destructor // Destructor
~Asset(); ~Asset();
// Añade un elemento a la lista // Añade un elemento a la lista
void add(std::string file, enum assetType type, bool required = true, bool absolute = false); void add(string file, enum assetType type, bool required = true, bool absolute = false);
// Devuelve un elemento de la lista a partir de una cadena // Devuelve un elemento de la lista a partir de una cadena
std::string get(std::string text); string get(string text);
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
bool check(); bool check();

View File

@@ -39,7 +39,7 @@ void Debug::render()
for (auto s : slot) for (auto s : slot)
{ {
text->write(x, y, s); text->write(x, y, s);
w = (std::max(w, (int)s.length())); w = (max(w, (int)s.length()));
y += text->getCharacterSize() + 1; y += text->getCharacterSize() + 1;
if (y > 192 - text->getCharacterSize()) if (y > 192 - text->getCharacterSize())
{ {
@@ -64,7 +64,7 @@ void Debug::setPos(SDL_Point p)
} }
// Añade un texto para mostrar // Añade un texto para mostrar
void Debug::add(std::string text) void Debug::add(string text)
{ {
slot.push_back(text); slot.push_back(text);
} }
@@ -76,7 +76,7 @@ void Debug::clear()
} }
// Añade un texto para mostrar en el apartado log // Añade un texto para mostrar en el apartado log
void Debug::addToLog(std::string text) void Debug::addToLog(string text)
{ {
log.push_back(text); log.push_back(text);
} }

View File

@@ -12,6 +12,8 @@
#ifndef DEBUG_H #ifndef DEBUG_H
#define DEBUG_H #define DEBUG_H
using namespace std;
// Clase Debug // Clase Debug
class Debug class Debug
{ {
@@ -24,8 +26,8 @@ private:
Texture *texture; // Textura para el texto Texture *texture; // Textura para el texto
// Variables // Variables
std::vector<std::string> slot; // Vector con los textos a escribir vector<string> slot; // Vector con los textos a escribir
std::vector<std::string> log; // Vector con los textos a escribir vector<string> log; // Vector con los textos a escribir
int x; // Posicion donde escribir el texto de debug int x; // Posicion donde escribir el texto de debug
int y; // Posición donde escribir el texto de debug int y; // Posición donde escribir el texto de debug
bool enabled; // Indica si esta activo el modo debug bool enabled; // Indica si esta activo el modo debug
@@ -47,13 +49,13 @@ public:
void setPos(SDL_Point p); void setPos(SDL_Point p);
// Añade un texto para mostrar // Añade un texto para mostrar
void add(std::string text); void add(string text);
// Borra la información de debug // Borra la información de debug
void clear(); void clear();
// Añade un texto para mostrar en el apartado log // Añade un texto para mostrar en el apartado log
void addToLog(std::string text); void addToLog(string text);
// Borra la información de debug del apartado log // Borra la información de debug del apartado log
void clearLog(); void clearLog();

478
units/gif.c Normal file
View File

@@ -0,0 +1,478 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define EXTENSION_INTRODUCER 0x21
#define IMAGE_DESCRIPTOR 0x2C
#define TRAILER 0x3B
#define GRAPHIC_CONTROL 0xF9
#define APPLICATION_EXTENSION 0xFF
#define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct
{
unsigned short width;
unsigned short height;
unsigned char fields;
unsigned char background_color_index;
unsigned char pixel_aspect_ratio;
}
screen_descriptor_t;
typedef struct
{
unsigned char r;
unsigned char g;
unsigned char b;
}
rgb;
typedef struct
{
unsigned short image_left_position;
unsigned short image_top_position;
unsigned short image_width;
unsigned short image_height;
unsigned char fields;
}
image_descriptor_t;
typedef struct
{
unsigned char byte;
int prev;
int len;
}
dictionary_entry_t;
typedef struct
{
unsigned char extension_code;
unsigned char block_size;
}
extension_t;
typedef struct
{
unsigned char fields;
unsigned short delay_time;
unsigned char transparent_color_index;
}
graphic_control_extension_t;
typedef struct
{
unsigned char application_id[ 8 ];
unsigned char version[ 3 ];
}
application_extension_t;
typedef struct
{
unsigned short left;
unsigned short top;
unsigned short width;
unsigned short height;
unsigned char cell_width;
unsigned char cell_height;
unsigned char foreground_color;
unsigned char background_color;
}
plaintext_extension_t;
//static unsigned short width = 0;
//static unsigned short height = 0;
//static unsigned char* uncompressed_data = NULL;
void uncompress( int code_length,
const unsigned char *input,
int input_length,
unsigned char *out )
{
//int maxbits;
int i, bit;
int code, prev = -1;
dictionary_entry_t *dictionary;
int dictionary_ind;
unsigned int mask = 0x01;
int reset_code_length;
int clear_code; // This varies depending on code_length
int stop_code; // one more than clear code
int match_len;
clear_code = 1 << ( code_length );
stop_code = clear_code + 1;
// To handle clear codes
reset_code_length = code_length;
// Create a dictionary large enough to hold "code_length" entries.
// Once the dictionary overflows, code_length increases
dictionary = ( dictionary_entry_t * )
malloc( sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
// Initialize the first 2^code_len entries of the dictionary with their
// indices. The rest of the entries will be built up dynamically.
// Technically, it shouldn't be necessary to initialize the
// dictionary. The spec says that the encoder "should output a
// clear code as the first code in the image data stream". It doesn't
// say must, though...
for ( dictionary_ind = 0;
dictionary_ind < ( 1 << code_length );
dictionary_ind++ )
{
dictionary[ dictionary_ind ].byte = dictionary_ind;
// XXX this only works because prev is a 32-bit int (> 12 bits)
dictionary[ dictionary_ind ].prev = -1;
dictionary[ dictionary_ind ].len = 1;
}
// 2^code_len + 1 is the special "end" code; don't give it an entry here
dictionary_ind++;
dictionary_ind++;
// TODO verify that the very last byte is clear_code + 1
while ( input_length )
{
code = 0x0;
// Always read one more bit than the code length
for ( i = 0; i < ( code_length + 1 ); i++ )
{
// This is different than in the file read example; that
// was a call to "next_bit"
bit = ( *input & mask ) ? 1 : 0;
mask <<= 1;
if ( mask == 0x100 )
{
mask = 0x01;
input++;
input_length--;
}
code = code | ( bit << i );
}
if ( code == clear_code )
{
code_length = reset_code_length;
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
for ( dictionary_ind = 0;
dictionary_ind < ( 1 << code_length );
dictionary_ind++ )
{
dictionary[ dictionary_ind ].byte = dictionary_ind;
// XXX this only works because prev is a 32-bit int (> 12 bits)
dictionary[ dictionary_ind ].prev = -1;
dictionary[ dictionary_ind ].len = 1;
}
dictionary_ind++;
dictionary_ind++;
prev = -1;
continue;
}
else if ( code == stop_code )
{
/*if ( input_length > 1 )
{
fprintf( stderr, "Malformed GIF (early stop code)\n" );
exit( 0 );
}*/
break;
}
// Update the dictionary with this character plus the _entry_
// (character or string) that came before it
if ( ( prev > -1 ) && ( code_length < 12 ) )
{
if ( code > dictionary_ind )
{
fprintf( stderr, "code = %.02x, but dictionary_ind = %.02x\n",
code, dictionary_ind );
exit( 0 );
}
// Special handling for KwKwK
if ( code == dictionary_ind )
{
int ptr = prev;
while ( dictionary[ ptr ].prev != -1 )
{
ptr = dictionary[ ptr ].prev;
}
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
}
else
{
int ptr = code;
while ( dictionary[ ptr ].prev != -1 )
{
ptr = dictionary[ ptr ].prev;
}
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
}
dictionary[ dictionary_ind ].prev = prev;
dictionary[ dictionary_ind ].len = dictionary[ prev ].len + 1;
dictionary_ind++;
// GIF89a mandates that this stops at 12 bits
if ( ( dictionary_ind == ( 1 << ( code_length + 1 ) ) ) &&
( code_length < 11 ) )
{
code_length++;
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
}
}
prev = code;
// Now copy the dictionary entry backwards into "out"
match_len = dictionary[ code ].len;
while ( code != -1 )
{
out[ dictionary[ code ].len - 1 ] = dictionary[ code ].byte;
if ( dictionary[ code ].prev == code )
{
fprintf( stderr, "Internal error; self-reference." );
exit( 0 );
}
code = dictionary[ code ].prev;
}
out += match_len;
}
}
static int read_sub_blocks( unsigned char* buffer, unsigned char **data )
{
int data_length;
int index;
unsigned char block_size;
// Everything following are data sub-blocks, until a 0-sized block is
// encountered.
data_length = 0;
*data = NULL;
index = 0;
while ( 1 )
{
READ(&block_size, 1);
if ( block_size == 0 ) // end of sub-blocks
{
break;
}
data_length += block_size;
*data = (unsigned char*)realloc( *data, data_length );
// TODO this could be split across block size boundaries
READ(*data + index, block_size);
index += block_size;
}
return data_length;
}
unsigned char* process_image_descriptor( unsigned char* buffer,
rgb *gct,
int gct_size,
int resolution_bits )
{
image_descriptor_t image_descriptor;
int compressed_data_length;
unsigned char *compressed_data = NULL;
unsigned char lzw_code_size;
int uncompressed_data_length = 0;
unsigned char *uncompressed_data = NULL;
// TODO there could actually be lots of these
READ(&image_descriptor, 9);
// TODO if LCT = true, read the LCT
READ(&lzw_code_size, 1);
compressed_data_length = read_sub_blocks( buffer, &compressed_data );
// width = image_descriptor.image_width;
// height = image_descriptor.image_height;
uncompressed_data_length = image_descriptor.image_width *
image_descriptor.image_height;
uncompressed_data = (unsigned char*)malloc( uncompressed_data_length );
uncompress( lzw_code_size, compressed_data, compressed_data_length,
uncompressed_data );
if ( compressed_data ) free( compressed_data );
//if ( uncompressed_data )
// free( uncompressed_data );
return uncompressed_data;
}
/**
* @param gif_file the file descriptor of a file containing a
* GIF-encoded file. This should point to the first byte in
* the file when invoked.
*/
#define rb (*(buffer++))
uint32_t* LoadPalette(unsigned char *buffer) {
unsigned char header[7];
screen_descriptor_t screen_descriptor;
//int color_resolution_bits;
int global_color_table_size = 0; // number of entries in global_color_table
uint32_t *global_color_table = NULL;
READ(header, 6);
READ(&screen_descriptor, 7);
//color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
global_color_table = (uint32_t *)calloc(1, 1024);
if (screen_descriptor.fields & 0x80) {
global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
//global_color_table = (rgb *)malloc(3 * global_color_table_size);
//READ(global_color_table, 3 * global_color_table_size);
for (int i=0; i<global_color_table_size;++i) {
global_color_table[i] = (buffer[0]<<16) + (buffer[1]<<8) + buffer[2];
buffer+=3;
}
}
return global_color_table;
}
static unsigned char* process_gif_stream(unsigned char *buffer, unsigned short* w, unsigned short* h)
{
unsigned char header[ 7 ];
screen_descriptor_t screen_descriptor;
int color_resolution_bits;
int global_color_table_size =0; // number of entries in global_color_table
rgb *global_color_table = NULL;
unsigned char block_type = 0x0;
// A GIF file starts with a Header (section 17)
READ(header, 6);
header[ 6 ] = 0x0;
// XXX there's another format, GIF87a, that you may still find
// floating around.
/*if ( strcmp( "GIF89a", (char*)header ) )
{
fprintf( stderr,
"Invalid GIF file (header is '%s', should be 'GIF89a')\n",
header );
return NULL;
}*/
// Followed by a logical screen descriptor
// Note that this works because GIFs specify little-endian order; on a
// big-endian machine, the height & width would need to be reversed.
// Can't use sizeof here since GCC does byte alignment;
// sizeof( screen_descriptor_t ) = 8!
READ(&screen_descriptor, 7);
*w = screen_descriptor.width;
*h = screen_descriptor.height;
color_resolution_bits = ( ( screen_descriptor.fields & 0x70 ) >> 4 ) + 1;
if ( screen_descriptor.fields & 0x80 )
{
//int i;
// If bit 7 is set, the next block is a global color table; read it
global_color_table_size = 1 <<
( ( ( screen_descriptor.fields & 0x07 ) + 1 ) );
global_color_table = ( rgb * ) malloc( 3 * global_color_table_size );
// XXX this could conceivably return a short count...
READ(global_color_table, 3 * global_color_table_size);
}
while ( block_type != TRAILER )
{
READ(&block_type, 1);
unsigned char size;
switch ( block_type )
{
case IMAGE_DESCRIPTOR:
return process_image_descriptor(buffer,
global_color_table,
global_color_table_size,
color_resolution_bits);
break;
case EXTENSION_INTRODUCER:
buffer++;
size = *(buffer++);
buffer += size;
do {
size = *(buffer++);
buffer += size;
} while (size != 0);
/*if ( !process_extension( buffer ) )
{
return NULL;
}*/
break;
case TRAILER:
break;
default:
fprintf( stderr, "Bailing on unrecognized block type %.02x\n",
block_type );
return NULL;
}
}
return NULL;
}
unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h) {
return process_gif_stream(buffer, w, h);
}
/*int main( int argc, char *argv[] )
{
FILE* gif_file;
if ( argc < 2 )
{
fprintf( stderr, "Usage: %s <path-to-gif-file>\n", argv[ 0 ] );
exit( 0 );
}
gif_file = fopen( argv[ 1 ], "rb" );
if ( gif_file == NULL )
{
fprintf( stderr, "Unable to open file '%s'", argv[ 1 ] );
perror( ": " );
}
process_gif_stream( gif_file );
fclose( gif_file );
}*/

View File

@@ -2,7 +2,7 @@
#include <iostream> #include <iostream>
// Constructor // Constructor
Input::Input(std::string file) Input::Input(string file, bool verbose)
{ {
// Fichero gamecontrollerdb.txt // Fichero gamecontrollerdb.txt
dbPath = file; dbPath = file;
@@ -11,15 +11,20 @@ Input::Input(std::string file)
keyBindings_t kb; keyBindings_t kb;
kb.scancode = 0; kb.scancode = 0;
kb.active = false; kb.active = false;
keyBindings.resize(input_number_of_inputs, kb); keyBindings.clear();
keyBindings.resize(INPUT_TOTAL, kb);
GameControllerBindings_t gcb; GameControllerBindings_t gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID; gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false; gcb.active = false;
gameControllerBindings.resize(input_number_of_inputs, gcb); gameControllerBindings.clear();
gameControllerBindings.resize(INPUT_TOTAL, gcb);
verbose = true; this->verbose = verbose;
enabled = true; enabled = true;
setDefaultBindings();
discoverGameController();
} }
// Actualiza el estado del objeto // Actualiza el estado del objeto
@@ -201,7 +206,7 @@ bool Input::discoverGameController()
{ {
if (verbose) if (verbose)
{ {
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl; cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << endl;
} }
} }
@@ -219,14 +224,25 @@ bool Input::discoverGameController()
if (verbose) if (verbose)
{ {
std::cout << "\nChecking for game controllers...\n"; cout << "\n** Checking game controllers" << endl;
std::cout << nJoysticks << " joysticks found, " << numGamepads << " are gamepads\n"; if (nJoysticks > 0)
{
string stNumJoysticks = nJoysticks == 1 ? "joystick" : "joysticks";
string stNumGamePads = numGamepads == 1 ? "is a gamepad" : "are gamepads";
cout << nJoysticks << " " << stNumJoysticks << " found (" << numGamepads << " " << stNumGamePads << ")" << endl;
}
else
{
cout << ">> No game controllers found" << endl;
}
} }
if (numGamepads > 0) if (numGamepads > 0)
{ {
found = true; found = true;
cout << "\n>> GAMEPAD LIST:" << endl;
for (int i = 0; i < numGamepads; i++) for (int i = 0; i < numGamepads; i++)
{ {
// Abre el mando y lo añade a la lista // Abre el mando y lo añade a la lista
@@ -234,13 +250,14 @@ bool Input::discoverGameController()
if (SDL_GameControllerGetAttached(pad) == 1) if (SDL_GameControllerGetAttached(pad) == 1)
{ {
connectedControllers.push_back(pad); connectedControllers.push_back(pad);
const std::string separator(" #"); const string separator(" #");
std::string name = SDL_GameControllerNameForIndex(i); string name = SDL_GameControllerNameForIndex(i);
name.resize(25); // name.resize(25);
name = name + separator + std::to_string(i); // name = name + separator + to_string(i);
if (verbose) if (verbose)
{ {
std::cout << name << std::endl; // cout << " - " << name << endl;
cout << "#" << i + 1 << ": " << name << endl;
} }
controllerNames.push_back(name); controllerNames.push_back(name);
} }
@@ -248,11 +265,13 @@ bool Input::discoverGameController()
{ {
if (verbose) if (verbose)
{ {
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; cout << "SDL_GetError() = " << SDL_GetError() << endl;
} }
} }
} }
cout << endl;
SDL_GameControllerEventState(SDL_ENABLE); SDL_GameControllerEventState(SDL_ENABLE);
} }
@@ -273,7 +292,7 @@ bool Input::gameControllerFound()
} }
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
std::string Input::getControllerName(int index) string Input::getControllerName(int index)
{ {
if (numGamepads > 0) if (numGamepads > 0)
{ {
@@ -310,3 +329,58 @@ void Input::enable()
enabled = true; enabled = true;
disabledUntil = d_notDisabled; disabledUntil = d_notDisabled;
} }
// Establece unas teclas y botones del mando por defectp
void Input::setDefaultBindings()
{
// Teclado
bindKey(INPUT_UP, SDL_SCANCODE_UP);
bindKey(INPUT_DOWN, SDL_SCANCODE_DOWN);
bindKey(INPUT_LEFT, SDL_SCANCODE_LEFT);
bindKey(INPUT_RIGHT, SDL_SCANCODE_RIGHT);
bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Z);
bindKey(INPUT_BUTTON_2, SDL_SCANCODE_X);
bindKey(INPUT_ACCEPT, SDL_SCANCODE_RETURN);
bindKey(INPUT_CANCEL, SDL_SCANCODE_BACKSPACE);
bindKey(INPUT_PAUSE, SDL_SCANCODE_H);
bindKey(INPUT_EXIT, SDL_SCANCODE_ESCAPE);
// Mando
bindGameControllerButton(INPUT_UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
bindGameControllerButton(INPUT_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
bindGameControllerButton(INPUT_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
bindGameControllerButton(INPUT_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
bindGameControllerButton(INPUT_BUTTON_1, SDL_CONTROLLER_BUTTON_A);
bindGameControllerButton(INPUT_BUTTON_2, SDL_CONTROLLER_BUTTON_B);
bindGameControllerButton(INPUT_BUTTON_3, SDL_CONTROLLER_BUTTON_X);
bindGameControllerButton(INPUT_BUTTON_4, SDL_CONTROLLER_BUTTON_Y);
bindGameControllerButton(INPUT_BUTTON_5, SDL_CONTROLLER_BUTTON_BACK);
bindGameControllerButton(INPUT_BUTTON_6, SDL_CONTROLLER_BUTTON_START);
bindGameControllerButton(INPUT_BUTTON_7, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
bindGameControllerButton(INPUT_BUTTON_8, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
bindGameControllerButton(INPUT_ACCEPT, SDL_CONTROLLER_BUTTON_A);
bindGameControllerButton(INPUT_CANCEL, SDL_CONTROLLER_BUTTON_B);
bindGameControllerButton(INPUT_PAUSE, SDL_CONTROLLER_BUTTON_START);
bindGameControllerButton(INPUT_EXIT, SDL_CONTROLLER_BUTTON_BACK);
}
// Elimina todas las asociaciones de teclado y mando al objeto
void Input::clearBindings()
{
// Inicializa las variables
keyBindings_t kb;
kb.scancode = 0;
kb.active = false;
keyBindings.clear();
keyBindings.resize(INPUT_TOTAL, kb);
GameControllerBindings_t gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false;
gameControllerBindings.clear();
gameControllerBindings.resize(INPUT_TOTAL, gcb);
}

View File

@@ -7,35 +7,47 @@
#ifndef INPUT_H #ifndef INPUT_H
#define INPUT_H #define INPUT_H
enum inputs_e using namespace std;
{
// Inputs obligatorios
input_null,
input_up,
input_down,
input_left,
input_right,
input_pause,
input_exit,
input_accept,
input_cancel,
// Inputs personalizados // Tipos diferentes de eventos de entrada
input_jump, #define INPUT_NULL 0
input_window_fullscreen, #define INPUT_UP 1
input_window_inc_size, #define INPUT_DOWN 2
input_window_dec_size, #define INPUT_LEFT 3
input_toggle_border, #define INPUT_RIGHT 4
input_switch_music, #define INPUT_BUTTON_1 5
input_swap_palette, #define INPUT_BUTTON_2 6
#define INPUT_BUTTON_3 7
#define INPUT_BUTTON_4 8
#define INPUT_BUTTON_5 9
#define INPUT_BUTTON_6 10
#define INPUT_BUTTON_7 11
#define INPUT_BUTTON_8 12
#define INPUT_BUTTON_9 13
#define INPUT_BUTTON_10 14
#define INPUT_BUTTON_11 15
#define INPUT_BUTTON_12 16
#define INPUT_BUTTON_13 17
#define INPUT_BUTTON_14 18
#define INPUT_BUTTON_15 19
#define INPUT_BUTTON_16 20
#define INPUT_BUTTON_17 21
#define INPUT_BUTTON_18 22
#define INPUT_BUTTON_19 23
#define INPUT_BUTTON_20 24
// Input obligatorio #define INPUT_PAUSE 25
input_number_of_inputs #define INPUT_EXIT 26
}; #define INPUT_ACCEPT 27
#define INPUT_CANCEL 28
#define INPUT_TOTAL 29
// Para saber si el input se puede repetir sin soltarlo
#define REPEAT_TRUE true #define REPEAT_TRUE true
#define REPEAT_FALSE false #define REPEAT_FALSE false
// Tipo de control asociado
#define INPUT_USE_KEYBOARD 0 #define INPUT_USE_KEYBOARD 0
#define INPUT_USE_GAMECONTROLLER 1 #define INPUT_USE_GAMECONTROLLER 1
#define INPUT_USE_ANY 2 #define INPUT_USE_ANY 2
@@ -63,21 +75,21 @@ private:
}; };
// Objetos y punteros // Objetos y punteros
std::vector<SDL_GameController *> connectedControllers; // Vector con todos los mandos conectados vector<SDL_GameController *> connectedControllers; // Vector con todos los mandos conectados
// Variables // Variables
std::vector<keyBindings_t> keyBindings; // Vector con las teclas asociadas a los inputs predefinidos vector<keyBindings_t> keyBindings; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<GameControllerBindings_t> gameControllerBindings; // Vector con las teclas asociadas a los inputs predefinidos vector<GameControllerBindings_t> gameControllerBindings; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::string> controllerNames; // Vector con los nombres de los mandos vector<string> controllerNames; // Vector con los nombres de los mandos
int numGamepads; // Numero de mandos conectados int numGamepads; // Numero de mandos conectados
std::string dbPath; // Ruta al archivo gamecontrollerdb.txt string dbPath; // Ruta al archivo gamecontrollerdb.txt
bool verbose; // Indica si ha de mostrar mensajes bool verbose; // Indica si ha de mostrar mensajes
i_disable_e disabledUntil; // Tiempo que esta deshabilitado i_disable_e disabledUntil; // Tiempo que esta deshabilitado
bool enabled; // Indica si está habilitado bool enabled; // Indica si está habilitado
public: public:
// Constructor // Constructor
Input(std::string file); Input(string file, bool verbose=true);
// Actualiza el estado del objeto // Actualiza el estado del objeto
void update(); void update();
@@ -104,7 +116,7 @@ public:
int getNumControllers(); int getNumControllers();
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
std::string getControllerName(int index); string getControllerName(int index);
// Establece si ha de mostrar mensajes // Establece si ha de mostrar mensajes
void setVerbose(bool value); void setVerbose(bool value);
@@ -114,6 +126,12 @@ public:
// Hablita las entradas // Hablita las entradas
void enable(); void enable();
// Establece unas teclas y botones del mando por defectp
void setDefaultBindings();
// Elimina todas las asociaciones de teclado y mando al objeto
void clearBindings();
}; };
#endif #endif

View File

@@ -1,8 +1,8 @@
#include "menu.h" #include "menu.h"
// Constructor // Constructor
//Menu::Menu(SDL_Renderer *renderer, Resource *resource, Asset *asset, Input *input, std::string file) //Menu::Menu(SDL_Renderer *renderer, Resource *resource, Asset *asset, Input *input, string file)
Menu::Menu(SDL_Renderer *renderer, Asset *asset, Input *input, std::string file) Menu::Menu(SDL_Renderer *renderer, Asset *asset, Input *input, string file)
{ {
// Copia punteros // Copia punteros
this->renderer = renderer; this->renderer = renderer;
@@ -91,7 +91,7 @@ Menu::~Menu()
} }
// Carga la configuración del menu desde un archivo de texto // Carga la configuración del menu desde un archivo de texto
bool Menu::load(std::string file_path) bool Menu::load(string file_path)
{ {
// Indicador de éxito en la carga // Indicador de éxito en la carga
bool success = true; bool success = true;
@@ -99,16 +99,16 @@ bool Menu::load(std::string file_path)
// Indica si se ha creado ya el objeto de texto // Indica si se ha creado ya el objeto de texto
bool textAllocated = false; bool textAllocated = false;
const std::string filename = file_path.substr(file_path.find_last_of("\\/") + 1); const string filename = file_path.substr(file_path.find_last_of("\\/") + 1);
std::string line; string line;
std::ifstream file(file_path); ifstream file(file_path);
// El fichero se puede abrir // El fichero se puede abrir
if (file.good()) if (file.good())
{ {
// Procesa el fichero linea a linea // Procesa el fichero linea a linea
std::cout << "Reading file " << filename.c_str() << std::endl; cout << "Reading file " << filename.c_str() << endl;
while (std::getline(file, line)) while (getline(file, line))
{ {
if (line == "[item]") if (line == "[item]")
{ {
@@ -122,7 +122,7 @@ bool Menu::load(std::string file_path)
do do
{ {
// Lee la siguiente linea // Lee la siguiente linea
std::getline(file, line); getline(file, line);
// Encuentra la posición del caracter '=' // Encuentra la posición del caracter '='
int pos = line.find("="); int pos = line.find("=");
@@ -130,7 +130,7 @@ bool Menu::load(std::string file_path)
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (!setItem(&item, line.substr(0, pos), line.substr(pos + 1, line.length()))) if (!setItem(&item, line.substr(0, pos), line.substr(pos + 1, line.length())))
{ {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl; cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << endl;
success = false; success = false;
} }
@@ -147,7 +147,7 @@ bool Menu::load(std::string file_path)
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (!setVars(line.substr(0, pos), line.substr(pos + 1, line.length()))) if (!setVars(line.substr(0, pos), line.substr(pos + 1, line.length())))
{ {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl; cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << endl;
success = false; success = false;
} }
@@ -161,13 +161,13 @@ bool Menu::load(std::string file_path)
} }
// Cierra el fichero // Cierra el fichero
std::cout << "Closing file " << filename.c_str() << std::endl; cout << "Closing file " << filename.c_str() << endl;
file.close(); file.close();
} }
// El fichero no se puede abrir // El fichero no se puede abrir
else else
{ {
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl; cout << "Warning: Unable to open " << filename.c_str() << " file" << endl;
success = false; success = false;
} }
@@ -175,7 +175,7 @@ bool Menu::load(std::string file_path)
} }
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool Menu::setItem(item_t *item, std::string var, std::string value) bool Menu::setItem(item_t *item, string var, string value)
{ {
// Indicador de éxito en la asignación // Indicador de éxito en la asignación
bool success = true; bool success = true;
@@ -187,7 +187,7 @@ bool Menu::setItem(item_t *item, std::string var, std::string value)
else if (var == "hPaddingDown") else if (var == "hPaddingDown")
{ {
item->hPaddingDown = std::stoi(value); item->hPaddingDown = stoi(value);
} }
else if (var == "selectable") else if (var == "selectable")
@@ -218,7 +218,7 @@ bool Menu::setItem(item_t *item, std::string var, std::string value)
} }
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool Menu::setVars(std::string var, std::string value) bool Menu::setVars(string var, string value)
{ {
// Indicador de éxito en la asignación // Indicador de éxito en la asignación
bool success = true; bool success = true;
@@ -255,70 +255,70 @@ bool Menu::setVars(std::string var, std::string value)
else if (var == "x") else if (var == "x")
{ {
x = std::stoi(value); x = stoi(value);
} }
else if (var == "centerX") else if (var == "centerX")
{ {
centerX = std::stoi(value); centerX = stoi(value);
} }
else if (var == "centerY") else if (var == "centerY")
{ {
centerY = std::stoi(value); centerY = stoi(value);
} }
else if (var == "y") else if (var == "y")
{ {
y = std::stoi(value); y = stoi(value);
} }
else if (var == "backgroundType") else if (var == "backgroundType")
{ {
backgroundType = std::stoi(value); backgroundType = stoi(value);
} }
else if (var == "backgroundColor") else if (var == "backgroundColor")
{ {
// Se introducen los valores separados por comas en un vector // Se introducen los valores separados por comas en un vector
std::stringstream ss(value); stringstream ss(value);
std::string tmp; string tmp;
getline(ss, tmp, ','); getline(ss, tmp, ',');
rectBG.color.r = std::stoi(tmp); rectBG.color.r = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
rectBG.color.g = std::stoi(tmp); rectBG.color.g = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
rectBG.color.b = std::stoi(tmp); rectBG.color.b = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
rectBG.a = std::stoi(tmp); rectBG.a = stoi(tmp);
} }
else if (var == "selector_color") else if (var == "selector_color")
{ {
// Se introducen los valores separados por comas en un vector // Se introducen los valores separados por comas en un vector
std::stringstream ss(value); stringstream ss(value);
std::string tmp; string tmp;
getline(ss, tmp, ','); getline(ss, tmp, ',');
selector.color.r = std::stoi(tmp); selector.color.r = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
selector.color.g = std::stoi(tmp); selector.color.g = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
selector.color.b = std::stoi(tmp); selector.color.b = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
selector.a = std::stoi(tmp); selector.a = stoi(tmp);
} }
else if (var == "selector_text_color") else if (var == "selector_text_color")
{ {
// Se introducen los valores separados por comas en un vector // Se introducen los valores separados por comas en un vector
std::stringstream ss(value); stringstream ss(value);
std::string tmp; string tmp;
getline(ss, tmp, ','); getline(ss, tmp, ',');
selector.itemColor.r = std::stoi(tmp); selector.itemColor.r = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
selector.itemColor.g = std::stoi(tmp); selector.itemColor.g = stoi(tmp);
getline(ss, tmp, ','); getline(ss, tmp, ',');
selector.itemColor.b = std::stoi(tmp); selector.itemColor.b = stoi(tmp);
} }
else if (var == "areElementsCenteredOnX") else if (var == "areElementsCenteredOnX")
@@ -338,7 +338,7 @@ bool Menu::setVars(std::string var, std::string value)
else if (var == "defaultActionWhenCancel") else if (var == "defaultActionWhenCancel")
{ {
defaultActionWhenCancel = std::stoi(value); defaultActionWhenCancel = stoi(value);
} }
else if (var == "") else if (var == "")
@@ -354,7 +354,7 @@ bool Menu::setVars(std::string var, std::string value)
} }
// Carga los ficheros de audio // Carga los ficheros de audio
void Menu::loadAudioFile(std::string file, int sound) void Menu::loadAudioFile(string file, int sound)
{ {
switch (sound) switch (sound)
{ {
@@ -376,7 +376,7 @@ void Menu::loadAudioFile(std::string file, int sound)
} }
// Obtiene el nombre del menu // Obtiene el nombre del menu
std::string Menu::getName() string Menu::getName()
{ {
return name; return name;
} }
@@ -475,7 +475,7 @@ int Menu::getWidestItem()
// Obtenemos la anchura del item mas ancho // Obtenemos la anchura del item mas ancho
for (auto &i : item) for (auto &i : item)
{ {
result = std::max(result, i.rect.w); result = max(result, i.rect.w);
} }
return result; return result;
@@ -797,7 +797,7 @@ void Menu::centerMenuElementsOnX()
} }
// Añade un item al menu // Añade un item al menu
void Menu::addItem(std::string text, int hPaddingDown, bool selectable, bool greyed, bool linkedDown) void Menu::addItem(string text, int hPaddingDown, bool selectable, bool greyed, bool linkedDown)
{ {
item_t temp; item_t temp;
@@ -833,7 +833,7 @@ void Menu::addItem(std::string text, int hPaddingDown, bool selectable, bool gre
} }
// Cambia el texto de un item // Cambia el texto de un item
void Menu::setItemCaption(int index, std::string text) void Menu::setItemCaption(int index, string text)
{ {
item[index].label = text; item[index].label = text;
item[index].rect.w = this->text->lenght(item[index].label); item[index].rect.w = this->text->lenght(item[index].label);
@@ -850,7 +850,7 @@ void Menu::setDefaultActionWhenCancel(int item)
// Gestiona la entrada de teclado y mando durante el menu // Gestiona la entrada de teclado y mando durante el menu
void Menu::checkInput() void Menu::checkInput()
{ {
if (input->checkInput(input_up, REPEAT_FALSE)) if (input->checkInput(INPUT_UP, REPEAT_FALSE))
{ {
if (decreaseSelectorIndex()) if (decreaseSelectorIndex())
{ {
@@ -861,7 +861,7 @@ void Menu::checkInput()
} }
} }
if (input->checkInput(input_down, REPEAT_FALSE)) if (input->checkInput(INPUT_DOWN, REPEAT_FALSE))
{ {
if (increaseSelectorIndex()) if (increaseSelectorIndex())
{ {
@@ -872,7 +872,7 @@ void Menu::checkInput()
} }
} }
if (input->checkInput(input_accept, REPEAT_FALSE)) if (input->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
{ {
itemSelected = selector.index; itemSelected = selector.index;
if (soundAccept) if (soundAccept)
@@ -881,7 +881,7 @@ void Menu::checkInput()
} }
} }
if (input->checkInput(input_cancel, REPEAT_FALSE)) if (input->checkInput(INPUT_CANCEL, REPEAT_FALSE))
{ {
itemSelected = defaultActionWhenCancel; itemSelected = defaultActionWhenCancel;
if (soundCancel) if (soundCancel)
@@ -954,7 +954,7 @@ int Menu::getSelectorHeight(int value)
} }
// Establece el nombre del menu // Establece el nombre del menu
void Menu::setName(std::string name) void Menu::setName(string name)
{ {
this->name = name; this->name = name;
} }
@@ -973,7 +973,7 @@ void Menu::setBackgroundType(int value)
} }
// Establece la fuente de texto que se utilizará // Establece la fuente de texto que se utilizará
void Menu::setText(std::string font_png, std::string font_txt) void Menu::setText(string font_png, string font_txt)
{ {
if (!text) if (!text)
{ {

View File

@@ -15,6 +15,8 @@
#ifndef MENU_H #ifndef MENU_H
#define MENU_H #define MENU_H
using namespace std;
// Tipos de fondos para el menu // Tipos de fondos para el menu
#define MENU_BACKGROUND_TRANSPARENT 0 #define MENU_BACKGROUND_TRANSPARENT 0
#define MENU_BACKGROUND_SOLID 1 #define MENU_BACKGROUND_SOLID 1
@@ -40,7 +42,7 @@ private:
struct item_t struct item_t
{ {
std::string label; // Texto string label; // Texto
SDL_Rect rect; // Rectangulo que delimita el elemento SDL_Rect rect; // Rectangulo que delimita el elemento
int hPaddingDown; // Espaciado bajo el elemento int hPaddingDown; // Espaciado bajo el elemento
bool selectable; // Indica si se puede seleccionar bool selectable; // Indica si se puede seleccionar
@@ -77,7 +79,7 @@ private:
Input *input; // Gestor de eventos de entrada de teclado o gamepad Input *input; // Gestor de eventos de entrada de teclado o gamepad
// Variables // Variables
std::string name; // Nombre del menu string name; // Nombre del menu
int x; // Posición en el eje X de la primera letra del primer elemento int x; // Posición en el eje X de la primera letra del primer elemento
int y; // Posición en el eje Y de la primera letra del primer elemento int y; // Posición en el eje Y de la primera letra del primer elemento
int h; // Altura del menu int h; // Altura del menu
@@ -96,19 +98,19 @@ private:
JA_Sound_t* soundMove; // Sonido al mover el selector JA_Sound_t* soundMove; // Sonido al mover el selector
color_t colorGreyed; // Color para los elementos agrisados color_t colorGreyed; // Color para los elementos agrisados
rectangle_t rectBG; // Rectangulo de fondo del menu rectangle_t rectBG; // Rectangulo de fondo del menu
std::vector<item_t> item; // Estructura para cada elemento del menu vector<item_t> item; // Estructura para cada elemento del menu
selector_t selector; // Variables para pintar el selector del menu selector_t selector; // Variables para pintar el selector del menu
std::string font_png; string font_png;
std::string font_txt; string font_txt;
// Carga la configuración del menu desde un archivo de texto // Carga la configuración del menu desde un archivo de texto
bool load(std::string file_path); bool load(string file_path);
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setVars(std::string var, std::string value); bool setVars(string var, string value);
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setItem(item_t *item, std::string var, std::string value); bool setItem(item_t *item, string var, string value);
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño // Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void reorganize(); void reorganize();
@@ -142,17 +144,17 @@ private:
public: public:
// Constructor // Constructor
//Menu(SDL_Renderer *renderer, Resource *resource, Asset *asset, Input *input, std::string file = ""); //Menu(SDL_Renderer *renderer, Resource *resource, Asset *asset, Input *input, string file = "");
Menu(SDL_Renderer *renderer, Asset *asset, Input *input, std::string file = ""); Menu(SDL_Renderer *renderer, Asset *asset, Input *input, string file = "");
// Destructor // Destructor
~Menu(); ~Menu();
// Carga los ficheros de audio // Carga los ficheros de audio
void loadAudioFile(std::string file, int sound); void loadAudioFile(string file, int sound);
// Obtiene el nombre del menu // Obtiene el nombre del menu
std::string getName(); string getName();
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getItemSelected(); int getItemSelected();
@@ -188,10 +190,10 @@ public:
void centerMenuElementsOnX(); void centerMenuElementsOnX();
// Añade un item al menu // Añade un item al menu
void addItem(std::string text, int hPaddingDown = 1, bool selectable = true, bool greyed = false, bool linkedDown = false); void addItem(string text, int hPaddingDown = 1, bool selectable = true, bool greyed = false, bool linkedDown = false);
// Cambia el texto de un item // Cambia el texto de un item
void setItemCaption(int index, std::string text); void setItemCaption(int index, string text);
// Establece el indice del item que se usará por defecto al cancelar el menu // Establece el indice del item que se usará por defecto al cancelar el menu
void setDefaultActionWhenCancel(int item); void setDefaultActionWhenCancel(int item);
@@ -209,7 +211,7 @@ public:
void setLinkedDown(int index, bool value); void setLinkedDown(int index, bool value);
// Establece el nombre del menu // Establece el nombre del menu
void setName(std::string name); void setName(string name);
// Establece la posición del menu // Establece la posición del menu
void setPos(int x, int y); void setPos(int x, int y);
@@ -218,7 +220,7 @@ public:
void setBackgroundType(int value); void setBackgroundType(int value);
// Establece la fuente de texto que se utilizará // Establece la fuente de texto que se utilizará
void setText(std::string font_png, std::string font_txt); void setText(string font_png, string font_txt);
// Establece el rectangulo de fondo del menu // Establece el rectangulo de fondo del menu
void setRectSize(int w = 0, int h = 0); void setRectSize(int w = 0, int h = 0);

View File

@@ -5,7 +5,6 @@
// Constructor // Constructor
MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture, SDL_Renderer *renderer) MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture, SDL_Renderer *renderer)
{ {
//std::cout << "Construido MovingSprite" << std::endl;
// Copia los punteros // Copia los punteros
this->texture = texture; this->texture = texture;
this->renderer = renderer; this->renderer = renderer;
@@ -58,7 +57,6 @@ MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vel
// Destructor // Destructor
MovingSprite::~MovingSprite() MovingSprite::~MovingSprite()
{ {
//std::cout << "Destruido MovingSprite" << std::endl;
} }
// Reinicia todas las variables // Reinicia todas las variables

View File

@@ -6,8 +6,6 @@
// Constructor // Constructor
Notify::Notify(SDL_Renderer *renderer, string iconFile, string bitmapFile, string textFile, string soundFile, options_t *options) Notify::Notify(SDL_Renderer *renderer, string iconFile, string bitmapFile, string textFile, string soundFile, options_t *options)
{ {
//std::cout << "Construido Notify" << std::endl;
// Inicializa variables // Inicializa variables
this->renderer = renderer; this->renderer = renderer;
this->options = options; this->options = options;
@@ -23,8 +21,6 @@ Notify::Notify(SDL_Renderer *renderer, string iconFile, string bitmapFile, strin
// Destructor // Destructor
Notify::~Notify() Notify::~Notify()
{ {
//std::cout << "Destruido Notify" << std::endl;
// Libera la memoria de los objetos // Libera la memoria de los objetos
if (iconTexture != nullptr) if (iconTexture != nullptr)
{ {

View File

@@ -0,0 +1,300 @@
#include "on_screen_keyboard.h"
// #include <iostream>
// Constructor
OnScreenKeyboard::OnScreenKeyboard(SDL_Renderer *renderer, Input *input, string bitmapFile, string textFile, options_t *options, int width, int height, string output, color_t color)
{
// Inicializa variables
this->renderer = renderer;
this->options = options;
this->input = input;
this->width = width;
this->height = height;
// Crea objetos
text = new Text(textFile, bitmapFile, renderer);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
textureCursor = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, text->getCharacterSize() * 2, text->getCharacterSize() * 2);
SDL_SetTextureBlendMode(textureCursor, SDL_BLENDMODE_BLEND);
// Inicializa variables
this->output = output;
char_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char_lower = "abcdefghijklmnopqrstuvwxyz";
char_numbers = "0123456789";
char_symbol = " !\"#$%&'()*+,-./:;<=>?@[]";
use_char_upper = true;
use_char_lower = false;
use_char_numbers = false;
use_char_symbol = false;
setLayout();
caption = "";
dest = {(options->screen.nativeWidth - width) / 2, (options->screen.nativeHeight - height) / 2, width, height};
cursor.col = 0;
cursor.row = 0;
cursor.dest = {0, 0, 16, 16};
// Rellena la textura de fondo con el color y el texto
fillTexture();
// Rellena la textura del cursor
SDL_SetRenderTarget(renderer, textureCursor);
color_t c = {192, 0, 0};
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 255);
SDL_RenderClear(renderer);
c = lightenColor(c, 20);
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, 255);
SDL_RenderDrawRect(renderer, NULL);
SDL_SetRenderTarget(renderer, nullptr);
}
// Destructor
OnScreenKeyboard::~OnScreenKeyboard()
{
// Libera la memoria de los objetos
if (text != nullptr)
{
delete text;
}
if (texture != nullptr)
{
SDL_DestroyTexture(texture);
}
}
// Rellena la textura de fondo con el color y el texto
void OnScreenKeyboard::fillTexture()
{
// Destruye la textura si la hubiera
if (texture)
SDL_DestroyTexture(texture);
// Crea la textura
height = (text->getCharacterSize() * 4) + (text->getCharacterSize() * rows * 2);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
dest = {(options->screen.nativeWidth - width) / 2, (options->screen.nativeHeight - height) / 2, width, height};
// Empieza a dibujar en la textura
SDL_SetRenderTarget(renderer, texture);
// Establece el color de fondo
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(renderer);
color_t color = lightenColor(bgColor, 20);
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
SDL_RenderDrawRect(renderer, NULL);
// Escribe el texto que aparece en el objeto
text->write(text->getCharacterSize(), text->getCharacterSize(), caption);
// Dibuja el cuadro donde va el texto que se escribirá
const color_t darkColor = darkenColor(bgColor, 10);
SDL_SetRenderDrawColor(renderer, darkColor.r, darkColor.g, darkColor.b, 255);
const int x_rect = (text->getCharacterSize() * 2) + text->lenght(caption);
const int y_rect = text->getCharacterSize();
const int w_rect = width - text->getCharacterSize() - x_rect;
const int h_rect = text->getCharacterSize();
outputDest = {x_rect, y_rect, w_rect, h_rect};
SDL_RenderFillRect(renderer, &outputDest);
// Dibuja los caracteres que conformaran el teclado
const int dist = text->getCharacterSize() * 2;
const int offset_x = text->getCharacterSize();
const int offset_y = text->getCharacterSize() * 3;
for (int j = 0; j < rows; ++j)
for (int i = 0; i < columns; ++i)
{
const int pos = i + (j * columns);
if (pos < (int)layout.size())
{
// color_t color = randColor();
// SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
// SDL_Rect rect = {offset_x + (layout.at(pos).col * dist), offset_y + (layout.at(pos).row * dist), dist, dist};
// SDL_RenderFillRect(renderer, &rect);
// text->write(offset_x + (layout.at(pos).col * dist) + (dist / 2), offset_y + (layout.at(pos).row * dist) + (dist / 2), layout.at(pos).caption);
text->writeCentered(offset_x + (layout.at(pos).col * dist) + (dist / 2), offset_y + (layout.at(pos).row * dist) + (dist / 4), layout.at(pos).caption);
}
}
// Deja de dibujar en la textura
SDL_SetRenderTarget(renderer, nullptr);
}
// Calcula cuantos caracteres se utilizaran para crear el teclado
int OnScreenKeyboard::getTotalChars()
{
int total = 0;
total += use_char_upper ? char_upper.length() : 0;
total += use_char_lower ? char_lower.length() : 0;
total += use_char_numbers ? char_numbers.length() : 0;
total += use_char_symbol ? char_symbol.length() : 0;
return total;
}
// Calcula cuantas columnas necesita el teclado
int OnScreenKeyboard::getColumns()
{
const int keyWidth = text->getCharacterSize() * 2;
int rowWidth = width - text->getCharacterSize();
return rowWidth / keyWidth;
}
// Calcula cuantas filas necesita el teclado
int OnScreenKeyboard::getRows()
{
return (totalChars / getColumns()) + 1;
}
// Establece la disposición del teclado
void OnScreenKeyboard::setLayout()
{
totalChars = getTotalChars();
columns = getColumns();
rows = getRows();
int index_col = 0;
int index_row = 0;
// Establece los caracteres a escribir
string allChars = "";
allChars = use_char_upper ? allChars + char_upper : allChars;
allChars = use_char_lower ? allChars + char_lower : allChars;
allChars = use_char_numbers ? allChars + char_numbers : allChars;
allChars = use_char_symbol ? allChars + char_symbol : allChars;
layout.clear();
for (int i = 0; i < (int)allChars.length(); ++i)
{
key_t key;
key.col = index_col;
key.row = index_row;
key.caption = allChars.substr(i, 1);
layout.push_back(key);
++index_col;
if (index_col == columns)
{
index_col = 0;
++index_row;
}
}
}
// Comprueba las entradas
void OnScreenKeyboard::checkInput()
{
if (input->checkInput(INPUT_LEFT, REPEAT_FALSE))
decCursorCol();
if (input->checkInput(INPUT_RIGHT, REPEAT_FALSE))
incCursorCol();
if (input->checkInput(INPUT_UP, REPEAT_FALSE))
decCursorRow();
if (input->checkInput(INPUT_DOWN, REPEAT_FALSE))
incCursorRow();
if (input->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
addChar();
if (input->checkInput(INPUT_CANCEL, REPEAT_FALSE))
removeChar();
}
// Disminuye en una columna la posición del cursor
void OnScreenKeyboard::decCursorCol()
{
cursor.col = cursor.col > 0 ? cursor.col - 1 : columns - 1;
}
// Incrementa en una columna la posición del cursor
void OnScreenKeyboard::incCursorCol()
{
++cursor.col %= columns;
}
// Disminuye en una fila la posición del cursor
void OnScreenKeyboard::decCursorRow()
{
cursor.row = cursor.row > 0 ? cursor.row - 1 : rows - 1;
}
// Aumenta en una fila la posición del cursor
void OnScreenKeyboard::incCursorRow()
{
++cursor.row %= rows;
}
// Actualiza la posición de la textura del cursor
void OnScreenKeyboard::updateCursor()
{
const int offset_x = text->getCharacterSize();
const int offset_y = text->getCharacterSize() * 3;
cursor.dest.x = dest.x + offset_x + (cursor.col * cursor.dest.w);
cursor.dest.y = dest.y + offset_y + (cursor.row * cursor.dest.h);
}
// Añade un caracter a la salida
void OnScreenKeyboard::addChar()
{
const int pos = cursor.col + cursor.row * columns;
if (pos < (int)layout.size())
output = output + layout.at(pos).caption;
}
// Borra el último caracter de la salida
void OnScreenKeyboard::removeChar()
{
if (output.length() > 0)
output = output.substr(0, output.length() - 1);
}
// Actualiza la lógica del objeto
void OnScreenKeyboard::update()
{
// Comprueba las entradas
checkInput();
// Actualiza la posición de la textura del cursor
updateCursor();
}
// Dibuja el objeto en pantalla
void OnScreenKeyboard::render()
{
SDL_RenderCopy(renderer, texture, nullptr, &dest);
SDL_RenderCopy(renderer, textureCursor, nullptr, &cursor.dest);
const int pos = cursor.col + cursor.row * columns;
const string key = pos < (int)layout.size() ? layout.at(pos).caption : "";
text->writeDX(TXT_CENTER | TXT_COLOR, cursor.dest.x + cursor.dest.w / 2, cursor.dest.y + cursor.dest.w / 4, key, 1, {0, 255, 0});
text->write(dest.x + outputDest.x, dest.y + outputDest.y, output);
}
// Establece el color de fondo
void OnScreenKeyboard::setBgColor(color_t color)
{
bgColor = color;
fillTexture();
}
// Establece el texto a mostrar junto al texto a introducir
void OnScreenKeyboard::setCaption(string text)
{
caption = text;
fillTexture();
}
// Establece qué caracteres ofrecerá el objeto
void OnScreenKeyboard::setChars(Uint8 mode)
{
use_char_upper = ((mode & USE_UPPER) == USE_UPPER);
use_char_lower = ((mode & USE_LOWER) == USE_LOWER);
use_char_numbers = ((mode & USE_NUMBER) == USE_NUMBER);
use_char_symbol = ((mode & USE_SYMBOL) == USE_SYMBOL);
setLayout();
fillTexture();
}

128
units/on_screen_keyboard.h Normal file
View File

@@ -0,0 +1,128 @@
#pragma once
#include <SDL2/SDL.h>
#include "utils.h"
#include "text.h"
#include "input.h"
#ifndef ON_SCREEN_KEYBOARD_H
#define ON_SCREEN_KEYBOARD_H
#define USE_UPPER 1
#define USE_LOWER 2
#define USE_NUMBER 4
#define USE_SYMBOL 8
using namespace std;
class OnScreenKeyboard
{
private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Text *text; // Objeto para dibujar texto
Input *input; // Gestor de eventos de entrada de teclado o gamepad
options_t *options; // Variable con todas las opciones del programa
SDL_Texture *texture; // Textura donde dibujar el objeto
SDL_Texture *textureCursor; // Textura para dibujar el cursor
// Estructuras
struct key_t
{
int col; // Posición horizontal de la tecla
int row; // Posición vertical de la tecla
string caption; // Texto de la tecla
};
struct cursor_t
{
int col;
int row;
SDL_Rect dest;
};
// Variables
string char_upper; // Cadena de texto con las letras en mayúscula
string char_lower; // Cadena de texto con las letras en minuscula
string char_numbers; // Cadena de texto con los números
string char_symbol; // Cadena de texto con los símbolos
bool use_char_upper; // Indica si se utilizará ese set de caracteres
bool use_char_lower; // Indica si se utilizará ese set de caracteres
bool use_char_numbers; // Indica si se utilizará ese set de caracteres
bool use_char_symbol; // Indica si se utilizará ese set de caracteres
int totalChars; // Cantidad de caracteres a utilizar
int columns; // Cantidad de caracteres que hay en una fila del teclado
int rows; // Cantidad de filas de caracteres que tendrá el teclado
color_t bgColor; // Color usado para el fondo
string caption; // Texto a mostrar junto al texto a introducir
int width; // Ancho del objeto
int height; // Altura del objeto
SDL_Rect dest; // Coordenadas donde se dibuja el objeto en pantalla
vector<key_t> layout; // Contiene la disposición del teclado
cursor_t cursor; // Variable para gestionar el cursor
string output; // Texto de salida
SDL_Rect outputDest; // Rectangulo con el texto de salida
// Rellena la textura de fondo con el color y el texto
void fillTexture();
// Calcula cuantos caracteres se utilizaran para crear el teclado
int getTotalChars();
// Calcula cuantas columnas necesita el teclado
int getColumns();
// Calcula cuantas filas necesita el teclado
int getRows();
// Establece la disposición del teclado
void setLayout();
// Comprueba las entradas
void checkInput();
// Disminuye en una columna la posición del cursor
void decCursorCol();
// Incrementa en una columna la posición del cursor
void incCursorCol();
// Disminuye en una fila la posición del cursor
void decCursorRow();
// Aumenta en una columna la posición del cursor
void incCursorRow();
// Actualiza la posición de la textura del cursor
void updateCursor();
// Añade un caracter a la salida
void addChar();
// Borra el último caracter de la salida
void removeChar();
public:
// Constructor
OnScreenKeyboard(SDL_Renderer *renderer, Input *input, string bitmapFile, string textFile, options_t *options, int width, int height, string output = "", color_t color = {0, 0, 0});
// Destructor
~OnScreenKeyboard();
// Actualiza la lógica del objeto
void update();
// Dibuja el objeto en pantalla
void render();
// Establece el color de fondo
void setBgColor(color_t color);
// Establece el texto a mostrar junto al texto a introducir
void setCaption(string text);
// Establece qué caracteres ofrecerá el objeto
void setChars(Uint8 mode);
};
#endif

165
units/paleta.cpp Normal file
View File

@@ -0,0 +1,165 @@
#include "paleta.h"
#include "gif.c"
#include <stdio.h>
struct jSurface_s
{
Uint8 *data;
Uint16 w, h;
};
static SDL_Window *jWin = NULL;
static SDL_Renderer *jRen = NULL;
static SDL_Texture *jTex = NULL;
static jSurface jScreen;
static jSurface jDestSurf;
static jSurface jSourceSurf = NULL;
static Uint32 paleta[256];
static int jWidth = 320;
static int jHeight = 240;
static int jZoom = 2;
static int transparentColor = 0;
jSurface jNewSurface(int w, int h)
{
jSurface surf = (jSurface)malloc(sizeof(jSurface_s));
surf->w = w;
surf->h = h;
surf->data = (Uint8 *)malloc(w * h);
return surf;
}
void jDeleteSurface(jSurface surf)
{
if (surf == NULL)
return;
if (surf->data != NULL)
free(surf->data);
free(surf);
}
void jSetDest(jSurface surf)
{
if (surf == NULL)
jDestSurf = jScreen;
else
jDestSurf = surf;
}
void jSetSource(jSurface surf)
{
jSourceSurf = surf;
}
void jBlit(int dx, int dy, int sx, int sy, int w, int h)
{
if (jSourceSurf == NULL)
return;
for (int iy = 0; iy < h; ++iy)
{
for (int ix = 0; ix < w; ++ix)
jPutPixel(dx + ix, dy + iy, jGetPixel(sx + ix, sy + iy));
}
}
jSurface jLoadSurface(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (!f)
return NULL;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8 *)malloc(size);
fread(buffer, size, 1, f);
fclose(f);
Uint16 w, h;
Uint8 *pixels = LoadGif(buffer, &w, &h);
if (pixels == NULL)
{
return NULL;
}
jSurface surf = (jSurface)malloc(sizeof(jSurface_s));
surf->w = w;
surf->h = h;
surf->data = pixels;
free(buffer);
return surf;
}
void jLoadPal(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (!f)
return;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8 *)malloc(size);
fread(buffer, size, 1, f);
fclose(f);
Uint32 *pal = LoadPalette(buffer);
if (pal == NULL)
{
return;
}
free(buffer);
for (int i = 0; i < 256; ++i)
{
paleta[i] = pal[i];
}
}
void jInit(const char *titol, int w, int h, int z)
{
SDL_Init(SDL_INIT_EVERYTHING);
jWidth = w;
jHeight = h;
jZoom = z;
jWin = SDL_CreateWindow(titol, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w * z, h * z, SDL_WINDOW_SHOWN);
jRen = SDL_CreateRenderer(jWin, -1, 0);
SDL_RenderSetLogicalSize(jRen, w, h);
jTex = SDL_CreateTexture(jRen, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h);
jScreen = jNewSurface(w, h);
jDestSurf = jScreen;
}
void jSetPal(int index, Uint32 color)
{
paleta[index] = color;
}
void jCls(Uint8 color)
{
for (int i = 0; i < jDestSurf->w * jDestSurf->h; ++i)
jDestSurf->data[i] = color;
}
void jFlip()
{
Uint32 *pixels;
int pitch;
SDL_LockTexture(jTex, NULL, (void **)&pixels, &pitch);
for (int i = 0; i < jWidth * jHeight; ++i)
pixels[i] = paleta[jScreen->data[i]];
SDL_UnlockTexture(jTex);
SDL_RenderCopy(jRen, jTex, NULL, NULL);
SDL_RenderPresent(jRen);
}
void jPutPixel(int x, int y, Uint8 color)
{
if (x < 0 || y < 0 || x >= jDestSurf->w || y >= jDestSurf->h || color == transparentColor)
return;
jDestSurf->data[x + y * jDestSurf->w] = color;
}
Uint8 jGetPixel(int x, int y)
{
return jSourceSurf->data[x + y * jSourceSurf->w];
}

28
units/paleta.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include <SDL2/SDL.h>
typedef struct jSurface_s *jSurface;
void init();
void update();
jSurface jNewSurface(int w, int h);
void jDeleteSurface(jSurface surf);
void jSetDest(jSurface surf);
void jSetSource(jSurface surf);
jSurface jLoadSurface(const char* filename);
void jPutPixel(int x, int y, Uint8 color);
Uint8 jGetPixel(int x, int y);
void jBlit(int dx, int dy, int sx, int sy, int w, int h);
void jInit(const char *titol, int w, int h, int z);
void jSetPal(int index, Uint32 color);
void jLoadPal(const char *filename);
void jCls(Uint8 color);
void jFlip();

View File

@@ -5,7 +5,6 @@
// Constructor // Constructor
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options) Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options)
{ {
//std::cout << "Construido Screen" << std::endl;
// Inicializa variables // Inicializa variables
this->window = window; this->window = window;
this->renderer = renderer; this->renderer = renderer;
@@ -26,9 +25,10 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options)
{ {
if (options->console) if (options->console)
{ {
std::cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << std::endl; cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << endl;
} }
} }
SDL_SetTextureBlendMode(gameCanvas, SDL_BLENDMODE_BLEND);
// Establece el modo de video // Establece el modo de video
setVideoMode(options->screen.mode); setVideoMode(options->screen.mode);
@@ -37,7 +37,6 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options)
// Destructor // Destructor
Screen::~Screen() Screen::~Screen()
{ {
//std::cout << "Destruido Screen" << std::endl;
if (notify != nullptr) if (notify != nullptr)
{ {
delete notify; delete notify;
@@ -56,6 +55,7 @@ void Screen::clean(color_t color)
void Screen::start() void Screen::start()
{ {
SDL_SetRenderTarget(renderer, gameCanvas); SDL_SetRenderTarget(renderer, gameCanvas);
SDL_RenderSetLogicalSize(renderer, options->screen.nativeWidth, options->screen.nativeHeight);
} }
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
@@ -68,6 +68,8 @@ void Screen::blit()
SDL_SetRenderDrawColor(renderer, borderColor.r, borderColor.g, borderColor.b, 0xFF); SDL_SetRenderDrawColor(renderer, borderColor.r, borderColor.g, borderColor.b, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
SDL_RenderSetLogicalSize(renderer, gameWidth, gameHeight);
// Copia la textura de juego en el renderizador en la posición adecuada // Copia la textura de juego en el renderizador en la posición adecuada
SDL_RenderCopy(renderer, gameCanvas, nullptr, &dest); SDL_RenderCopy(renderer, gameCanvas, nullptr, &dest);
@@ -167,7 +169,7 @@ void Screen::setVideoMode(int videoMode)
// Modifica el tamaño del renderizador // Modifica el tamaño del renderizador
// SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight); // SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
SDL_RenderSetLogicalSize(renderer, gameWidth, gameHeight); //SDL_RenderSetLogicalSize(renderer, gameWidth, gameHeight);
// Actualiza las opciones // Actualiza las opciones
options->screen.mode = videoMode; options->screen.mode = videoMode;
@@ -191,7 +193,7 @@ void Screen::setWindowSize(int size)
void Screen::decWindowSize() void Screen::decWindowSize()
{ {
--options->screen.windowZoom; --options->screen.windowZoom;
options->screen.windowZoom = std::max(options->screen.windowZoom, 1); options->screen.windowZoom = max(options->screen.windowZoom, 1);
setVideoMode(0); setVideoMode(0);
} }
@@ -199,7 +201,7 @@ void Screen::decWindowSize()
void Screen::incWindowSize() void Screen::incWindowSize()
{ {
++options->screen.windowZoom; ++options->screen.windowZoom;
options->screen.windowZoom = std::min(options->screen.windowZoom, 4); options->screen.windowZoom = min(options->screen.windowZoom, 4);
setVideoMode(0); setVideoMode(0);
} }
@@ -323,7 +325,7 @@ void Screen::iniSpectrumFade()
spectrumColor.clear(); spectrumColor.clear();
// Inicializa el vector de colores // Inicializa el vector de colores
const std::vector<std::string> vColors = {"black", "blue", "red", "magenta", "green", "cyan", "yellow", "bright_white"}; const vector<string> vColors = {"black", "blue", "red", "magenta", "green", "cyan", "yellow", "bright_white"};
for (auto v : vColors) for (auto v : vColors)
{ {
spectrumColor.push_back(stringToColor(options->palette, v)); spectrumColor.push_back(stringToColor(options->palette, v));
@@ -388,7 +390,7 @@ void Screen::updateNotifier()
} }
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void Screen::showNotification(std::string text1, std::string text2, int icon) void Screen::showNotification(string text1, string text2, int icon)
{ {
notify->showText(text1, text2, icon); notify->showText(text1, text2, icon);
} }

View File

@@ -8,6 +8,8 @@
#ifndef SCREEN_H #ifndef SCREEN_H
#define SCREEN_H #define SCREEN_H
using namespace std;
#define FILTER_NEAREST 0 #define FILTER_NEAREST 0
#define FILTER_LINEAL 1 #define FILTER_LINEAL 1
@@ -38,7 +40,7 @@ private:
bool spectrumFade; // Indica si esta activo el efecto de fade spectrum bool spectrumFade; // Indica si esta activo el efecto de fade spectrum
int spectrumFadeCounter; // Temporizador para el efecto de fade spectrum int spectrumFadeCounter; // Temporizador para el efecto de fade spectrum
int spectrumFadeLenght; // Duración del fade spectrum int spectrumFadeLenght; // Duración del fade spectrum
std::vector<color_t> spectrumColor; // Colores para el fade spectrum vector<color_t> spectrumColor; // Colores para el fade spectrum
// Inicializa las variables para el fade // Inicializa las variables para el fade
void iniFade(); void iniFade();
@@ -133,7 +135,7 @@ public:
void updateNotifier(); void updateNotifier();
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void showNotification(std::string text1 = "", std::string text2 = "", int icon = -1); void showNotification(string text1 = "", string text2 = "", int icon = -1);
// Actualiza la lógica del objeto // Actualiza la lógica del objeto
void update(); void update();

View File

@@ -4,7 +4,6 @@
// Constructor // Constructor
Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *renderer) Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *renderer)
{ {
//std::cout << "Construido Sprite" << std::endl;
// Establece la posición X,Y del sprite // Establece la posición X,Y del sprite
this->x = x; this->x = x;
this->y = y; this->y = y;
@@ -30,7 +29,6 @@ Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *rende
Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer) Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer)
{ {
//std::cout << "Construido Sprite" << std::endl;
// Establece la posición X,Y del sprite // Establece la posición X,Y del sprite
this->x = rect.x; this->x = rect.x;
this->y = rect.y; this->y = rect.y;
@@ -57,7 +55,6 @@ Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer)
// Destructor // Destructor
Sprite::~Sprite() Sprite::~Sprite()
{ {
//std::cout << "Destruido Sprite" << std::endl;
} }
// Muestra el sprite por pantalla // Muestra el sprite por pantalla

View File

@@ -79,7 +79,6 @@ textFile_t LoadTextFile(string file, bool verbose)
// Constructor // Constructor
Text::Text(string textFile, string bitmapFile, SDL_Renderer *renderer) Text::Text(string textFile, string bitmapFile, SDL_Renderer *renderer)
{ {
//std::cout << "Construido Text" << std::endl;
// Carga los offsets desde el fichero // Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile); textFile_t tf = LoadTextFile(textFile);
@@ -105,7 +104,6 @@ Text::Text(string textFile, string bitmapFile, SDL_Renderer *renderer)
// Constructor // Constructor
Text::Text(string textFile, Texture *texture, SDL_Renderer *renderer) Text::Text(string textFile, Texture *texture, SDL_Renderer *renderer)
{ {
//std::cout << "Construido Text" << std::endl;
// Carga los offsets desde el fichero // Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile); textFile_t tf = LoadTextFile(textFile);
@@ -130,7 +128,6 @@ Text::Text(string textFile, Texture *texture, SDL_Renderer *renderer)
// Constructor // Constructor
Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer) Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer)
{ {
//std::cout << "Construido Text" << std::endl;
// Inicializa variables desde la estructura // Inicializa variables desde la estructura
boxHeight = textFile->boxHeight; boxHeight = textFile->boxHeight;
boxWidth = textFile->boxWidth; boxWidth = textFile->boxWidth;
@@ -152,7 +149,6 @@ Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer)
// Destructor // Destructor
Text::~Text() Text::~Text()
{ {
//std::cout << "Destruido Text" << std::endl;
if (sprite != nullptr) if (sprite != nullptr)
{ {
delete sprite; delete sprite;

View File

@@ -5,9 +5,8 @@
#include <iostream> #include <iostream>
// Constructor // Constructor
Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose) Texture::Texture(SDL_Renderer *renderer, string path, bool verbose)
{ {
//std::cout << "Construido Texture" << std::endl;
// Copia punteros // Copia punteros
this->renderer = renderer; this->renderer = renderer;
this->path = path; this->path = path;
@@ -27,16 +26,14 @@ Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose)
// Destructor // Destructor
Texture::~Texture() Texture::~Texture()
{ {
//std::cout << "Destruido Texture" << std::endl;
// Libera memoria // Libera memoria
unload(); unload();
} }
// Carga una imagen desde un fichero // Carga una imagen desde un fichero
bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose) bool Texture::loadFromFile(string path, SDL_Renderer *renderer, bool verbose)
{ {
const std::string filename = path.substr(path.find_last_of("\\/") + 1); const string filename = path.substr(path.find_last_of("\\/") + 1);
int req_format = STBI_rgb_alpha; int req_format = STBI_rgb_alpha;
int width, height, orig_format; int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format); unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format);
@@ -49,7 +46,7 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbos
{ {
if (verbose) if (verbose)
{ {
std::cout << "Image loaded: " << filename.c_str() << std::endl; cout << "Image loaded: " << filename.c_str() << endl;
} }
} }
@@ -80,7 +77,7 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbos
{ {
if (verbose) if (verbose)
{ {
std::cout << "Unable to load image " << path.c_str() << std::endl; cout << "Unable to load image " << path.c_str() << endl;
} }
} }
else else
@@ -91,7 +88,7 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbos
{ {
if (verbose) if (verbose)
{ {
std::cout << "Unable to create texture from " << path.c_str() << "! SDL Error: " << SDL_GetError() << std::endl; cout << "Unable to create texture from " << path.c_str() << "! SDL Error: " << SDL_GetError() << endl;
} }
} }
else else
@@ -118,7 +115,7 @@ bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_Tex
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height); texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height);
if (texture == nullptr) if (texture == nullptr)
{ {
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl; cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << endl;
} }
else else
{ {

View File

@@ -7,6 +7,8 @@
#ifndef TEXTURE_H #ifndef TEXTURE_H
#define TEXTURE_H #define TEXTURE_H
using namespace std;
class Texture class Texture
{ {
private: private:
@@ -17,17 +19,17 @@ private:
// Variables // Variables
int width; // Ancho de la imagen int width; // Ancho de la imagen
int height; // Alto de la imagen int height; // Alto de la imagen
std::string path; // Ruta de la imagen de la textura string path; // Ruta de la imagen de la textura
public: public:
// Constructor // Constructor
Texture(SDL_Renderer *renderer, std::string path = "", bool verbose = false); Texture(SDL_Renderer *renderer, string path = "", bool verbose = false);
// Destructor // Destructor
~Texture(); ~Texture();
// Carga una imagen desde un fichero // Carga una imagen desde un fichero
bool loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose = false); bool loadFromFile(string path, SDL_Renderer *renderer, bool verbose = false);
// Crea una textura en blanco // Crea una textura en blanco
bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);

View File

@@ -1,6 +1,8 @@
#include "utils.h" #include "utils.h"
#include <math.h> #include <math.h>
using namespace std;
// Calcula el cuadrado de la distancia entre dos puntos // Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2) double distanceSquared(int x1, int y1, int x2, int y2)
{ {
@@ -576,7 +578,37 @@ void initOptions(options_t *options)
options->screen.borderHeight = 0; options->screen.borderHeight = 0;
options->notifications.posV = pos_top; options->notifications.posV = pos_top;
options->notifications.posH = pos_left; options->notifications.posH = pos_left;
options->notifications.sound = true; options->notifications.sound = true;
options->notifications.color = {48, 48, 48}; options->notifications.color = {48, 48, 48};
}
// Oscurece un color
color_t darkenColor(color_t color, int amount)
{
color_t newColor;
newColor.r = max(0, color.r - amount);
newColor.g = max(0, color.g - amount);
newColor.b = max(0, color.b - amount);
return newColor;
}
// Aclara un color
color_t lightenColor(color_t color, int amount)
{
color_t newColor;
newColor.r = min(255, color.r + amount);
newColor.g = min(255, color.g + amount);
newColor.b = min(255, color.b + amount);
return newColor;
}
// Obtiene un color aleatorio
color_t randColor()
{
color_t newColor;
newColor.r = rand() % 256;
newColor.g = rand() % 256;
newColor.b = rand() % 256;
return newColor;
} }

View File

@@ -201,4 +201,13 @@ bool colorAreEqual(color_t color1, color_t color2);
// Inicializa la estructura de opciones // Inicializa la estructura de opciones
void initOptions(options_t *options); void initOptions(options_t *options);
// Oscurece un color
color_t darkenColor(color_t color, int amount);
// Aclara un color
color_t lightenColor(color_t color, int amount);
// Obtiene un color aleatorio
color_t randColor();
#endif #endif