Commit to continue on other pc

This commit is contained in:
2021-09-06 20:02:58 +02:00
parent 2bc504f704
commit 012ad0be08
47 changed files with 23553 additions and 0 deletions

9
Makefile Normal file
View File

@@ -0,0 +1,9 @@
executable = njg
macos:
mkdir -p bin
g++ -std=c++11 -Wall -O2 source/*.cpp -o bin/$(executable)_macos -lSDL2
linux:
mkdir -p bin
g++ source/*.cpp -std=c++11 -Os -lSDL2 -ffunction-sections -fdata-sections -Wl,--gc-sections -o bin/$(executable)_linux
strip -s -R .comment -R .gnu.version bin/$(executable)_linux --strip-unneeded

BIN
media/font/8bithud.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

194
media/font/8bithud.txt Normal file
View File

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

BIN
media/font/nokia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

194
media/font/nokia.txt Normal file
View File

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

BIN
media/font/nokia2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

194
media/font/nokia2.txt Normal file
View File

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

BIN
media/font/smb2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

194
media/font/smb2.txt Normal file
View File

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

158
media/lang/ba_BA.txt Normal file
View File

@@ -0,0 +1,158 @@
## 0 - MENU DEL TITULO
JUGAR
## 1 - MENU DEL TITULO
OPCIONS
## 2 - MENU DEL TITULO
INSTRUCCIONS
## 3 - MENU DEL TITULO
EIXIR
## 4 - MENU DE OPCIONES
FINESTRA
## 5 - MENU DE OPCIONES
PANTALLA COMPLETA
## 6 - MENU DE OPCIONES
PANTALLA COMPLETA FALSA
## 7 - MENU DE OPCIONES
TAMANY DE FINESTRA
## 8 - MENU DE OPCIONES
IDIOMA
## 9 - MENU DE OPCIONES
[ ACEPTAR ]
## 10 - MENU DE OPCIONES
[ CANCELAR ]
## 11 - INSTRUCCIONES
OBJECTIU
## 12 - INSTRUCCIONES
HAS D'EXPLOTAR
## 13 - INSTRUCCIONES
TANTS GLOBUS COM PUGUES
## 14 - INSTRUCCIONES
LA DIFICULTAT AUGMENTA
## 15 - INSTRUCCIONES
A MESURA QUE VAS PUNTUANT
## 16 - INSTRUCCIONES
OBJECTES
## 17 - INSTRUCCIONES
1.000 PUNTS
## 18 - INSTRUCCIONES
2.500 PUNTS
## 19 - INSTRUCCIONES
5.000 PUNTS
## 20 - INSTRUCCIONES
PARA EL TEMPS
## 21 - INSTRUCCIONES
VIDA EXTRA
## 22 - INSTRUCCIONES
PREM UNA TECLA PER A TORNAR
## 23 - TITULO
PREM QUALSEVOL TECLA
## 24 - MENU SELECCION DE IDIOMA
ESPA{OL (ESPANYOL)
## 25 - MENU SELECCION DE IDIOMA
BALOONCIA
## 26 - MENU SELECCION DE IDIOMA
ENGLISH (ANGLES)
## 27 - INTRO
Un dia qualsevol de l'any 2000
## 28 - INTRO
Tot esta tranquil a la UPV
## 29 - INTRO
Fins que un desaprensiu...
## 30 - INTRO
HEY! ME ANE A FERME UN CORTAET...
## 31 - INTRO
UAAAAAAAAAAAAA!!!
## 32 - INTRO
Espera un moment...
## 33 - INTRO
Si resulta que no tinc solt!
## 34 - INTRO
MERDA DE MAQUINA!
## 35 - INTRO
Blop... blop... blop...
## 36 - TEXTOS DEL JUEGO
Temps detes:
## 37 - TEXTOS DEL JUEGO
D E M O
## 38 - TEXTOS DEL JUEGO
Pantalla
## 39 - MARCADOR
PUNTS
## 40 - MARCADOR
MAX.PUNT.
## 41 - MARCADOR
MULT
## 42 - MARCADOR
PANTALLA
## 43 - PANTALLA DE GAME OVER
FI DEL JOC
## 44 - PANTALLA DE GAME OVER
ELS TEUS PUNTS:
## 45 - PANTALLA DE GAME OVER
REINTENTAR?
## 46 - MENU DE PAUSA
CONTINUAR
## 47 - MENU DE PAUSA
EIXIR DEL JOC
## 48 - MENU GAME OVER
SI
## 49 - MENU GAME OVER
NO
## 50 - TEXTO DE COMPLETAR EL JUEGO
Felicitats!!
## 51 - MENU DEL TITULO
1 JUGADOR
## 52 - MENU DEL TITULO
2 JUGADORS
## 53 MARCADOR
jugador 1
## 54 MARCADOR
jugador 2
## 55 MARCADOR
mult
## 56 MARCADOR
max. puntuacio
## 57 MARCADOR
pantalla
## 58 - MENU DE OPCIONES
MODE DE VISUALITZACIO
## 59 - MENU DE OPCIONES
DIFICULTAT
## 60 - MENU DE OPCIONES
FILTRE
## 61 - MENU DE OPCIONES
SINC. VERTICAL
## 62 - MENU DE OPCIONES
CONTROLS DEL JUGADOR 1
## 63 - MENU DE OPCIONES
CONTROLS DEL JUGADOR 2
## 64 - MENU DE OPCIONES
TECLAT
## 65 - MENU DE OPCIONES
MANDO
## 66 - MENU DE OPCIONES
FACIL
## 67 - MENU DE OPCIONES
NORMAL
## 68 - MENU DE OPCIONES
DIFICIL
## 69 - MENU DE OPCIONES
TECLAT
## 70 - MENU DE OPCIONES
MANDO
## 71 - MENU DE OPCIONES
LINEAL
## 72 - MENU DE OPCIONES
NEAREST
## 73 - MENU DE OPCIONES
ACTIVADA
## 74 - MENU DE OPCIONES
DESACTIVADA
## 75 - JUEGO
Endavant!
## 76 - JUEGO
1.000.000 de punts!
## 77 - PANTALLA DE GAME OVER
PUNTS J1:
## 78 - PANTALLA DE GAME OVER
PUNTS J2:

158
media/lang/en_UK.txt Normal file
View File

@@ -0,0 +1,158 @@
## 0 - MENU DEL TITULO
PLAY
## 1 - MENU DEL TITULO
OPTIONS
## 2 - MENU DEL TITULO
HOW TO PLAY
## 3 - MENU DEL TITULO
QUIT
## 4 - MENU DE OPCIONES
WINDOW
## 5 - MENU DE OPCIONES
FULLSCREEN
## 6 - MENU DE OPCIONES
FAKE FULLSCREEN
## 7 - MENU DE OPCIONES
WINDOW SIZE
## 8 - MENU DE OPCIONES
LANGUAGE
## 9 - MENU DE OPCIONES
[ ACCEPT ]
## 10 - MENU DE OPCIONES
[ CANCEL ]
## 11 - INSTRUCCIONES
OBJECTIVE
## 12 - INSTRUCCIONES
YOU HAVE TO POP AS MANY
## 13 - INSTRUCCIONES
BALLOONS AS YOU CAN
## 14 - INSTRUCCIONES
DIFFICULTY WILL BE INCREASED
## 15 - INSTRUCCIONES
AS YOU SCORE POINTS
## 16 - INSTRUCCIONES
ITEMS
## 17 - INSTRUCCIONES
1.000 POINTS
## 18 - INSTRUCCIONES
2.500 POINTS
## 19 - INSTRUCCIONES
5.000 POINTS
## 20 - INSTRUCCIONES
TIME STOPPER
## 21 - INSTRUCCIONES
EXTRA HIT
## 22 - INSTRUCCIONES
PRESS ANY KEY TO RETURN
## 23 - TITULO
PRESS ANY KEY
## 24 - MENU SELECCION DE IDIOMA
ESPA{OL (SPANISH)
## 25 - MENU SELECCION DE IDIOMA
BALOONCIA (VALENCIAN)
## 26 - MENU SELECCION DE IDIOMA
ENGLISH
## 27 - INTRO
Any day of the year 2000
## 28 - INTRO
Everything is quiet at the UPV
## 29 - INTRO
Until a bastard arrives...
## 30 - INTRO
YO! GONNA TAKE A CAFELITO...
## 31 - INTRO
AAAAAAAARGHHHH!!!
## 32 - INTRO
Wait a moment...
## 33 - INTRO
I don't have any loose!
## 34 - INTRO
FUCKING MACHINE!
## 35 - INTRO
Blop... blop... blop...
## 36 - TEXTOS DEL JUEGO
Time stopped:
## 37 - TEXTOS DEL JUEGO
D E M O
## 38 - TEXTOS DEL JUEGO
Stage
## 39 - MARCADOR
SCORE
## 40 - MARCADOR
HI-SCORE
## 41 - MARCADOR
MULT
## 42 - MARCADOR
STAGE
## 43 - PANTALLA DE GAME OVER
GAME OVER
## 44 - PANTALLA DE GAME OVER
YOUR SCORE:
## 45 - PANTALLA DE GAME OVER
RETRY?
## 46 - MENU DE PAUSA
CONTINUE
## 47 - MENU DE PAUSA
LEAVE GAME
## 48 - MENU GAME OVER
YES
## 49 - MENU GAME OVER
NO
## 50 - TEXTO DE COMPLETAR EL JUEGO
Congratulations!!
## 51 - MENU DEL TITULO
1 PLAYER
## 52 - MENU DEL TITULO
2 PLAYERS
## 53 - MARCADOR
player 1
## 54 - MARCADOR
player 2
## 55 - MARCADOR
mult
## 56 - MARCADOR
high score
## 57 - MARCADOR
stage
## 58 - MENU DE OPCIONES
DISPLAY MODE
## 59 - MENU DE OPCIONES
DIFFICULTY
## 60 - MENU DE OPCIONES
FILTER
## 61 - MENU DE OPCIONES
VSYNC
## 62 - MENU DE OPCIONES
PLAYER 1 CONTROLS
## 63 - MENU DE OPCIONES
PLAYER 2 CONTROLS
## 64 - MENU DE OPCIONES
KEYBOARD
## 65 - MENU DE OPCIONES
GAME CONTROLLER
## 66 - MENU DE OPCIONES
EASY
## 67 - MENU DE OPCIONES
NORMAL
## 68 - MENU DE OPCIONES
HARD
## 69 - MENU DE OPCIONES
KEYBOARD
## 70 - MENU DE OPCIONES
GAME CONTROLLER
## 71 - MENU DE OPCIONES
LINEAL
## 72 - MENU DE OPCIONES
NEAREST
## 73 - MENU DE OPCIONES
ON
## 74 - MENU DE OPCIONES
OFF
## 75 - JUEGO
Get Ready!
## 76 - JUEGO
1.000.000 points!
## 77 - PANTALLA DE GAME OVER
PLAYER1 SCORE:
## 78 - PANTALLA DE GAME OVER
PLAYER2 SCORE:

158
media/lang/es_ES.txt Normal file
View File

@@ -0,0 +1,158 @@
## 0 - MENU DEL TITULO
JUGAR
## 1 - MENU DEL TITULO
OPCIONES
## 2 - MENU DEL TITULO
INSTRUCCIONES
## 3 - MENU DEL TITULO
SALIR
## 4 - MENU DE OPCIONES
VENTANA
## 5 - MENU DE OPCIONES
PANTALLA COMPLETA
## 6 - MENU DE OPCIONES
PANTALLA COMPLETA FALSA
## 7 - MENU DE OPCIONES
TAMA{O DE VENTANA
## 8 - MENU DE OPCIONES
IDIOMA
## 9 - MENU DE OPCIONES
[ ACEPTAR ]
## 10 - MENU DE OPCIONES
[ CANCELAR ]
## 11 - INSTRUCCIONES
OBJETIVO
## 12 - INSTRUCCIONES
TIENES QUE EXPLOTAR
## 13 - INSTRUCCIONES
TANTOS GLOBOS COMO PUEDAS
## 14 - INSTRUCCIONES
LA DIFICULTAD SE INCREMENTA
## 15 - INSTRUCCIONES
A MEDIDA QUE VAS PUNTUANDO
## 16 - INSTRUCCIONES
OBJETOS
## 17 - INSTRUCCIONES
1.000 PUNTOS
## 18 - INSTRUCCIONES
2.500 PUNTOS
## 19 - INSTRUCCIONES
5.000 PUNTOS
## 20 - INSTRUCCIONES
DETIENE EL TIEMPO
## 21 - INSTRUCCIONES
VIDA EXTRA
## 22 - INSTRUCCIONES
PULSA UNA TECLA PARA VOLVER
## 23 - TITULO
PULSA CUALQUIER TECLA
## 24 - MENU SELECCION DE IDIOMA
ESPA{OL
## 25 - MENU SELECCION DE IDIOMA
BALOONCIA (VALENCIANO)
## 26 - MENU SELECCION DE IDIOMA
ENGLISH (INGLES)
## 27 - INTRO
Un dia cualquiera del a{o 2000
## 28 - INTRO
Todo esta tranquilo en la UPV
## 29 - INTRO
Hasta que un desaprensivo...
## 30 - INTRO
HEY! VOY A SACARME UN TALLADET...
## 31 - INTRO
UAAAAAAAAAAAAA!!!
## 32 - INTRO
Espera un momento...
## 33 - INTRO
Si no llevo suelto encima!
## 34 - INTRO
MIERDA DE MAQUINA!
## 35 - INTRO
Blop... blop... blop...
## 36 - TEXTOS DEL JUEGO
Tiempo:
## 37 - TEXTOS DEL JUEGO
D E M O
## 38 - TEXTOS DEL JUEGO
Fase
## 39 - MARCADOR
PUNTOS
## 40 - MARCADOR
MAX.PUNT.
## 41 - MARCADOR
MULT
## 42 - MARCADOR
FASE
## 43 - PANTALLA DE GAME OVER
FIN DE JUEGO
## 44 - PANTALLA DE GAME OVER
TU PUNTUACION:
## 45 - PANTALLA DE GAME OVER
REINTENTAR?
## 46 - MENU DE PAUSA
CONTINUAR
## 47 - MENU DE PAUSA
SALIR DEL JUEGO
## 48 - MENU GAME OVER
SI
## 49 - MENU GAME OVER
NO
## 50 - TEXTO DE COMPLETAR EL JUEGO
Felicidades!!
## 51 - MENU DEL TITULO
1 JUGADOR
## 52 - MENU DEL TITULO
2 JUGADORES
## 53 - MARCADOR
jugador 1
## 54 - MARCADOR
jugador 2
## 55 - MARCADOR
mult
## 56 - MARCADOR
max. puntuacion
## 57 - MARCADOR
fase
## 58 - MENU DE OPCIONES
MODO DE VISUALIZACION
## 59 - MENU DE OPCIONES
DIFICULTAD
## 60 - MENU DE OPCIONES
FILTRO
## 61 - MENU DE OPCIONES
SINC. VERTICAL
## 62 - MENU DE OPCIONES
CONTROLES DEL JUGADOR 1
## 63 - MENU DE OPCIONES
CONTROLES DEL JUGADOR 2
## 64 - MENU DE OPCIONES
TECLADO
## 65 - MENU DE OPCIONES
MANDO
## 66 - MENU DE OPCIONES
FACIL
## 67 - MENU DE OPCIONES
NORMAL
## 68 - MENU DE OPCIONES
DIFICIL
## 69 - MENU DE OPCIONES
TECLADO
## 70 - MENU DE OPCIONES
MANDO
## 71 - MENU DE OPCIONES
LINEAL
## 72 - MENU DE OPCIONES
NEAREST
## 73 - MENU DE OPCIONES
ACTIVADA
## 74 - MENU DE OPCIONES
DESACTIVADA
## 75 - JUEGO
Adelante!
## 76 - JUEGO
1.000.000 de puntos!
## 77 - PANTALLA DE GAME OVER
PUNTUACION J1:
## 78 - PANTALLA DE GAME OVER
PUNTUACION J2:

123
source/animatedsprite.cpp Normal file
View File

@@ -0,0 +1,123 @@
#include "const.h"
#include "animatedsprite.h"
// Constructor
AnimatedSprite::AnimatedSprite()
{
//init(nullptr, nullptr);
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
//init(nullptr, nullptr);
}
// Iniciador
void AnimatedSprite::init(LTexture *texture, SDL_Renderer *renderer)
{
mRenderer = renderer;
mTexture = texture;
for (int i = 0; i < 20; i++)
{
mAnimation[i].numFrames = 0;
mAnimation[i].speed = 0;
mAnimation[i].loop = true;
mAnimation[i].completed = false;
for (int j = 0; i < 20; i++)
{
mAnimation[i].frames[j].x = 0;
mAnimation[i].frames[j].y = 0;
mAnimation[i].frames[j].w = 0;
mAnimation[i].frames[j].h = 0;
}
}
mCurrentFrame = 0;
mAnimationCounter = 0;
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate(int index)
{
if (mEnabled)
{
// Calculamos el frame actual a partir del contador
mCurrentFrame = mAnimationCounter / mAnimation[index].speed;
// Si alcanzamos el final de la animación, reiniciamos el contador de la animación
// en función de la variable loop
if (mCurrentFrame >= mAnimation[index].numFrames)
{
if (mAnimation[index].loop)
mAnimationCounter = 0;
else
mCurrentFrame = mAnimation[index].numFrames;
}
// En caso contrario
else
{
// Escogemos el frame correspondiente de la animación
setSpriteClip(mAnimation[index].frames[mCurrentFrame]);
// Incrementamos el contador de la animacion
mAnimationCounter++;
}
}
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(Uint8 num)
{
mCurrentFrame = num;
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(Uint16 num)
{
mAnimationCounter = num;
}
// Establece el rectangulo para un frame de una animación
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{
mAnimation[index_animation].frames[index_frame].x = x;
mAnimation[index_animation].frames[index_frame].y = y;
mAnimation[index_animation].frames[index_frame].w = w;
mAnimation[index_animation].frames[index_frame].h = h;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(Uint8 index, Uint8 speed)
{
mAnimation[index].speed = speed;
}
// Establece el numero de frames de una animación
void AnimatedSprite::setAnimationNumFrames(Uint8 index, Uint8 num)
{
mAnimation[index].numFrames = num;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(Uint8 index, bool loop)
{
mAnimation[index].loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setCompleted(Uint8 index, bool value)
{
mAnimation[index].completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::isCompleted(Uint8 index)
{
return mAnimation[index].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(Uint8 index_animation, Uint8 index_frame)
{
return mAnimation[index_animation].frames[index_frame];
}

69
source/animatedsprite.h Normal file
View File

@@ -0,0 +1,69 @@
#pragma once
#include "ifdefs.h"
#include "movingsprite.h"
#ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H
#define MAX_FRAMES 30
#define MAX_ANIMATIONS 20
// Clase AnimatedSprite
class AnimatedSprite : public MovingSprite
{
private:
struct sAnimation
{
SDL_Rect frames[MAX_FRAMES]; // Cada uno de los frames que componen la animación
Uint8 numFrames; // Numero de frames que componen la animación
Uint8 speed; // Velocidad de la animación
bool loop; // Indica si la animación se reproduce en bucle
bool completed; // Indica si ha finalizado la animación
};
sAnimation mAnimation[MAX_ANIMATIONS]; // Vector con las diferentes animaciones
Uint8 mCurrentFrame; // Frame actual
Uint16 mAnimationCounter; // Contador para las animaciones
public:
// Constructor
AnimatedSprite();
// Destructor
~AnimatedSprite();
// Iniciador
void init(LTexture *texture, SDL_Renderer *renderer);
// Calcula el frame correspondiente a la animación
void animate(int index);
// Establece el frame actual de la animación
void setCurrentFrame(Uint8 num);
// Establece el valor del contador
void setAnimationCounter(Uint16 num);
// Establece el rectangulo para un frame de una animación
void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h);
// Establece la velocidad de una animación
void setAnimationSpeed(Uint8 index, Uint8 speed);
// Establece el numero de frames de una animación
void setAnimationNumFrames(Uint8 index, Uint8 num);
// Establece si la animación se reproduce en bucle
void setAnimationLoop(Uint8 index, bool loop);
// Establece el valor de la variable
void setCompleted(Uint8 index, bool value);
// Comprueba si ha terminado la animación
bool isCompleted(Uint8 index);
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(Uint8 index_animation, Uint8 index_frame);
};
#endif

358
source/const.h Normal file
View File

@@ -0,0 +1,358 @@
#pragma once
#include "ifdefs.h"
#include "utils.h"
#include "lang.h"
#include <string>
#ifndef CONST_H
#define CONST_H
// Textos
#define WINDOW_CAPTION "Coffee Crisis"
#define TEXT_COPYRIGHT "@2020,2021 JailDesigner (v2.0.1)"
// Recursos
#define BINFILE_SCORE 0
#define BINFILE_DEMO 1
#define BINFILE_CONFIG 2
#define TOTAL_BINFILE 3
#define MUSIC_INTRO 0
#define MUSIC_PLAYING 1
#define MUSIC_TITLE 2
#define TOTAL_MUSIC 3
#define SOUND_BALLOON 0
#define SOUND_BUBBLE1 1
#define SOUND_BUBBLE2 2
#define SOUND_BUBBLE3 3
#define SOUND_BUBBLE4 4
#define SOUND_BULLET 5
#define SOUND_COFFEE_OUT 6
#define SOUND_HISCORE 7
#define SOUND_ITEM_DROP 8
#define SOUND_ITEM_PICKUP 9
#define SOUND_MENU_CANCEL 10
#define SOUND_MENU_MOVE 11
#define SOUND_MENU_SELECT 12
#define SOUND_PLAYER_COLLISION 13
#define SOUND_STAGE_CHANGE 14
#define SOUND_TITLE 15
#define SOUND_CLOCK 16
#define SOUND_POWERBALL 17
#define TOTAL_SOUND 18
#define TEXTURE_BALLOON 0
#define TEXTURE_BULLET 1
#define TEXTURE_FONT_BLACK 2
#define TEXTURE_FONT_BLACK_X2 3
#define TEXTURE_FONT_NOKIA 4
#define TEXTURE_FONT_WHITE 5
#define TEXTURE_FONT_WHITE_X2 6
#define TEXTURE_GAME_BG 7
#define TEXTURE_GAME_TEXT 8
#define TEXTURE_INTRO 9
#define TEXTURE_ITEMS 10
#define TEXTURE_LOGO 11
#define TEXTURE_MENU 12
#define TEXTURE_PLAYER_BODY 13
#define TEXTURE_PLAYER_DEATH 14
#define TEXTURE_PLAYER_LEGS 15
#define TEXTURE_TITLE 16
#define TOTAL_TEXTURE 17
// Tamaño de bloque
#define BLOCK 8
#define HALF_BLOCK BLOCK / 2
// Tamaño de la pantalla real
#define SCREEN_WIDTH 256
const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4;
// Tamaño de la pantalla que se muestra
const int VIEW_WIDTH = SCREEN_WIDTH * 3;
const int VIEW_HEIGHT = SCREEN_HEIGHT * 3;
// Cantidad de enteros a escribir en los ficheros de datos
#define TOTAL_SCORE_DATA 3
#define TOTAL_DEMO_DATA 2000
// Zona de juego
const int PLAY_AREA_TOP = (0 * BLOCK);
const int PLAY_AREA_BOTTOM = SCREEN_HEIGHT - (4 * BLOCK);
const int PLAY_AREA_LEFT = (0 * BLOCK);
const int PLAY_AREA_RIGHT = SCREEN_WIDTH - (0 * BLOCK);
const int PLAY_AREA_WIDTH = PLAY_AREA_RIGHT - PLAY_AREA_LEFT;
const int PLAY_AREA_HEIGHT = PLAY_AREA_BOTTOM - PLAY_AREA_TOP;
const int PLAY_AREA_CENTER_X = PLAY_AREA_LEFT + (PLAY_AREA_WIDTH / 2);
const int PLAY_AREA_CENTER_FIRST_QUARTER_X = (PLAY_AREA_WIDTH / 4);
const int PLAY_AREA_CENTER_THIRD_QUARTER_X = (PLAY_AREA_WIDTH / 4) * 3;
const int PLAY_AREA_CENTER_Y = PLAY_AREA_TOP + (PLAY_AREA_HEIGHT / 2);
const int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4;
const int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3;
// Anclajes de pantalla
const int SCREEN_CENTER_X = SCREEN_WIDTH / 2;
const int SCREEN_FIRST_QUARTER_X = SCREEN_WIDTH / 4;
const int SCREEN_THIRD_QUARTER_X = (SCREEN_WIDTH / 4) * 3;
const int SCREEN_CENTER_Y = SCREEN_HEIGHT / 2;
const int SCREEN_FIRST_QUARTER_Y = SCREEN_HEIGHT / 4;
const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3;
// Opciones de menu
#define MENU_NO_OPTION -1
#define MENU_OPTION_START 0
#define MENU_OPTION_QUIT 1
#define MENU_OPTION_TOTAL 2
// Tipos de fondos para el menu
#define MENU_BACKGROUND_TRANSPARENT 0
#define MENU_BACKGROUND_SOLID 1
// Estados del jugador
#define PLAYER_STATUS_WALKING_LEFT 0
#define PLAYER_STATUS_WALKING_RIGHT 1
#define PLAYER_STATUS_WALKING_STOP 2
#define PLAYER_STATUS_FIRING_UP 0
#define PLAYER_STATUS_FIRING_LEFT 1
#define PLAYER_STATUS_FIRING_RIGHT 2
#define PLAYER_STATUS_FIRING_NO 3
#define PLAYER_ANIMATION_LEGS_WALKING_LEFT 0
#define PLAYER_ANIMATION_LEGS_WALKING_RIGHT 1
#define PLAYER_ANIMATION_LEGS_WALKING_STOP 2
#define PLAYER_ANIMATION_BODY_WALKING_LEFT 0
#define PLAYER_ANIMATION_BODY_FIRING_LEFT 1
#define PLAYER_ANIMATION_BODY_WALKING_RIGHT 2
#define PLAYER_ANIMATION_BODY_FIRING_RIGHT 3
#define PLAYER_ANIMATION_BODY_WALKING_STOP 4
#define PLAYER_ANIMATION_BODY_FIRING_UP 5
#define PLAYER_ANIMATION_HEAD_WALKING_LEFT 0
#define PLAYER_ANIMATION_HEAD_FIRING_LEFT 1
#define PLAYER_ANIMATION_HEAD_WALKING_RIGHT 2
#define PLAYER_ANIMATION_HEAD_FIRING_RIGHT 3
#define PLAYER_ANIMATION_HEAD_WALKING_STOP 4
#define PLAYER_ANIMATION_HEAD_FIRING_UP 5
// Variables del jugador
#define PLAYER_INVULNERABLE_COUNTER 200
#define PLAYER_POWERUP_COUNTER 1500
// Secciones del programa
#define PROG_SECTION_LOGO 0
#define PROG_SECTION_INTRO 1
#define PROG_SECTION_TITLE 2
#define PROG_SECTION_GAME 3
#define PROG_SECTION_QUIT 4
// Subsecciones
#define GAME_SECTION_PLAY_1P 0
#define GAME_SECTION_PLAY_2P 1
#define GAME_SECTION_PAUSE 2
#define GAME_SECTION_GAMEOVER 3
#define TITLE_SECTION_1 3
#define TITLE_SECTION_2 4
#define TITLE_SECTION_3 5
#define TITLE_SECTION_INSTRUCTIONS 6
// Modo para las instrucciones
#define INSTRUCTIONS_MODE_MANUAL 0
#define INSTRUCTIONS_MODE_AUTO 1
// Estados de cada elemento que pertenece a un evento
#define EVENT_WAITING 1
#define EVENT_RUNNING 2
#define EVENT_COMPLETED 3
// Cantidad de eventos de la intro
#define INTRO_TOTAL_BITMAPS 6
#define INTRO_TOTAL_TEXTS 9
const int INTRO_TOTAL_EVENTS = INTRO_TOTAL_BITMAPS + INTRO_TOTAL_TEXTS;
// Cantidad de eventos de la pantalla de titulo
#define TITLE_TOTAL_EVENTS 2
// Relaciones de Id con nomnbres
#define BITMAP0 0
#define BITMAP1 1
#define BITMAP2 2
#define BITMAP3 3
#define BITMAP4 4
#define BITMAP5 5
#define TEXT0 6
#define TEXT1 7
#define TEXT2 8
#define TEXT3 9
#define TEXT4 10
#define TEXT5 11
#define TEXT6 12
#define TEXT7 13
#define TEXT8 14
// Anclajes para el marcador de puntos
const int SCORE_WORD_X = (SCREEN_WIDTH / 4) - ((5 * BLOCK) / 2);
const int SCORE_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int SCORE_NUMBER_X = (SCREEN_WIDTH / 4) - ((6 * BLOCK) / 2);
const int SCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
const int HISCORE_WORD_X = ((SCREEN_WIDTH / 4) * 3) - ((8 * BLOCK) / 2);
const int HISCORE_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int HISCORE_NUMBER_X = ((SCREEN_WIDTH / 4) * 3) - ((6 * BLOCK) / 2);
const int HISCORE_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
const int MULTIPLIER_WORD_X = (SCREEN_WIDTH / 2) - ((4 * BLOCK) / 2);
const int MULTIPLIER_WORD_Y = SCREEN_HEIGHT - (3 * BLOCK) + 2;
const int MULTIPLIER_NUMBER_X = (SCREEN_WIDTH / 2) - ((3 * BLOCK) / 2);
const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
// Ningun tipo
#define NO_KIND 0
// Tipos de globo
#define BALLOON_1 1
#define BALLOON_2 2
#define BALLOON_3 3
#define BALLOON_4 4
#define HEXAGON_1 5
#define HEXAGON_2 6
#define HEXAGON_3 7
#define HEXAGON_4 8
#define POWER_BALL 9
// Puntos de globo
#define BALLOON_SCORE_1 50
#define BALLOON_SCORE_2 100
#define BALLOON_SCORE_3 200
#define BALLOON_SCORE_4 400
// Tamaños de globo
#define BALLOON_SIZE_1 1
#define BALLOON_SIZE_2 2
#define BALLOON_SIZE_3 3
#define BALLOON_SIZE_4 4
// Clases de globo
#define BALLOON_CLASS 0
#define HEXAGON_CLASS 1
// Velocidad del globo
#define BALLOON_VELX_POSITIVE 0.7f
#define BALLOON_VELX_NEGATIVE -0.7f
// Indice para las animaciones de los globos
#define BALLOON_MOVING_ANIMATION 0
#define BALLOON_POP_ANIMATION 1
#define BALLOON_BORN_ANIMATION 2
// Cantidad posible de globos
#define MAX_BALLOONS 100
// Velocidades a las que se mueven los enemigos
#define BALLOON_SPEED_1 0.60f
#define BALLOON_SPEED_2 0.70f
#define BALLOON_SPEED_3 0.80f
#define BALLOON_SPEED_4 0.90f
#define BALLOON_SPEED_5 1.00f
// Tamaño de los globos
#define BALLOON_WIDTH_1 8
#define BALLOON_WIDTH_2 13
#define BALLOON_WIDTH_3 21
#define BALLOON_WIDTH_4 37
// PowerBall
#define POWERBALL_SCREENPOWER_MINIMUM 10
#define POWERBALL_COUNTER 8
// Tipos de bala
#define BULLET_UP 1
#define BULLET_LEFT 2
#define BULLET_RIGHT 3
// Cantidad posible de globos
#define MAX_BULLETS 50
// Tipos de objetos
#define ITEM_POINTS_1_DISK 1
#define ITEM_POINTS_2_GAVINA 2
#define ITEM_POINTS_3_PACMAR 3
#define ITEM_CLOCK 4
#define ITEM_COFFEE 5
#define ITEM_POWER_BALL 6
#define ITEM_COFFEE_MACHINE 7
// Porcentaje de aparición de los objetos
#define ITEM_POINTS_1_DISK_ODDS 10
#define ITEM_POINTS_2_GAVINA_ODDS 6
#define ITEM_POINTS_3_PACMAR_ODDS 3
#define ITEM_CLOCK_ODDS 5
#define ITEM_COFFEE_ODDS 5
#define ITEM_POWER_BALL_ODDS 0
#define ITEM_COFFEE_MACHINE_ODDS 4
// Cantidad de objetos simultaneos
#define MAX_ITEMS 10
// Valores para las variables asociadas a los objetos
#define REMAINING_EXPLOSIONS 3
#define REMAINING_EXPLOSIONS_COUNTER 50
#define TIME_STOPPED_COUNTER 300
// Estados de entrada
#define NO_INPUT 0
#define INPUT_FIRE_LEFT 7
#define INPUT_FIRE_UP 8
#define INPUT_FIRE_RIGHT 9
#define INPUT_PAUSE 10
// Zona muerta del mando analógico
#define JOYSTICK_DEAD_ZONE 8000
// Tipos de mensajes para el retorno de las funciones
#define MSG_OK 0
#define MSG_BULLET_OUT 1
// Tipos de texto
#define TEXT_FIXED 0
#define TEXT_VARIABLE 1
// Cantidad de elementos del vector de SmartSprites
#define MAX_SMART_SPRITES 10
// Cantidad máxima de gotas de café
#define MAX_COFFEE_DROPS 100
// Contadores
#define TITLE_COUNTER 800
#define STAGE_COUNTER 200
#define INSTRUCTIONS_COUNTER 600
#define DEATH_COUNTER 350
#define SHAKE_COUNTER 10
#define HELP_COUNTER 1000
// Colores
const color_t bgColor = {0x27, 0x27, 0x36};
const color_t noColor = {0xFF, 0xFF, 0xFF};
const color_t shdwTxtColor = {0x43, 0x43, 0x4F};
// Formaciones enemigas
#define NUMBER_OF_ENEMY_FORMATIONS 100
#define MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION 50
// Dificultad del juego
#define DIFFICULTY_EASY 0
#define DIFFICULTY_NORMAL 1
#define DIFFICULTY_HARD 2
// Tipo de filtro
#define FILTER_NEAREST 0
#define FILTER_LINEAL 1
#endif

538
source/director.cpp Normal file
View File

@@ -0,0 +1,538 @@
#include "const.h"
#include "utils.h"
#include "director.h"
#include <iostream>
#include <string>
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
// Constructor
Director::Director(std::string path)
{
// Inicializa la ruta
setExecutablePath(path);
// Establece la lista de ficheros
setFileList();
// Si falta algún fichero no inicies el programa
Uint8 section = PROG_SECTION_LOGO;
if (!checkFileList())
section = PROG_SECTION_QUIT;
// Inicializa el objeto de idioma
mLang = new Lang(mFileList);
// Crea el puntero a la estructura y carga el fichero de configuración
mOptions = new options_t;
if (!loadConfigFile())
{
mOptions->fullScreenMode = 0;
mOptions->windowSize = 3;
mOptions->language = en_UK;
mOptions->difficulty = DIFFICULTY_NORMAL;
mOptions->input[0].deviceType = INPUT_USE_KEYBOARD;
mOptions->input[1].deviceType = INPUT_USE_GAMECONTROLLER;
mOptions->filter = FILTER_NEAREST;
mOptions->vSync = true;
}
// Crea los objetos
mInput = new Input(mFileList[53]);
// Inicializa SDL
initSDL();
// Inicializa JailAudio
initJailAudio();
// Aplica las opciones
SDL_SetWindowFullscreen(mWindow, mOptions->fullScreenMode);
SDL_SetWindowSize(mWindow, SCREEN_WIDTH * mOptions->windowSize, SCREEN_HEIGHT * mOptions->windowSize);
mLang->setLang(mOptions->language);
#ifdef __MIPSEL__
DIR *dir = opendir("/media/data/local/home/.coffee_crisis");
if (dir)
{
closedir(dir);
}
else if (ENOENT == errno)
{
int status = mkdir("/media/data/local/home/.coffee_crisis", 755);
}
#endif
// Inicializa el resto de variables
init(section);
}
Director::~Director()
{
saveConfigFile();
delete mInput;
mInput = nullptr;
delete mLang;
mLang = nullptr;
delete mOptions;
mOptions = nullptr;
SDL_DestroyRenderer(mRenderer);
SDL_DestroyWindow(mWindow);
mRenderer = nullptr;
mWindow = nullptr;
SDL_Quit();
}
// Inicia las variables necesarias para arrancar el programa
void Director::init(Uint8 name)
{
// Sección
mSection.name = name;
mSection.subsection = 0;
// Textos
mLang->setLang(mOptions->language);
// Controles
mInput->bindKey(INPUT_UP, SDL_SCANCODE_UP);
mInput->bindKey(INPUT_DOWN, SDL_SCANCODE_DOWN);
mInput->bindKey(INPUT_LEFT, SDL_SCANCODE_LEFT);
mInput->bindKey(INPUT_RIGHT, SDL_SCANCODE_RIGHT);
mInput->bindKey(INPUT_ACCEPT, SDL_SCANCODE_RETURN);
mInput->bindKey(INPUT_CANCEL, SDL_SCANCODE_ESCAPE);
#ifdef __MIPSEL__
mInput->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_LSHIFT);
mInput->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_SPACE);
mInput->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_LCTRL);
#else
mInput->bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Q);
mInput->bindKey(INPUT_BUTTON_2, SDL_SCANCODE_W);
mInput->bindKey(INPUT_BUTTON_3, SDL_SCANCODE_E);
#endif
mInput->bindKey(INPUT_BUTTON_PAUSE, SDL_SCANCODE_ESCAPE); // PAUSE
mInput->bindKey(INPUT_BUTTON_ESCAPE, SDL_SCANCODE_ESCAPE); // ESCAPE
mInput->bindGameControllerButton(INPUT_UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
mInput->bindGameControllerButton(INPUT_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
mInput->bindGameControllerButton(INPUT_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
mInput->bindGameControllerButton(INPUT_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
mInput->bindGameControllerButton(INPUT_ACCEPT, SDL_CONTROLLER_BUTTON_B);
mInput->bindGameControllerButton(INPUT_CANCEL, SDL_CONTROLLER_BUTTON_A);
mInput->bindGameControllerButton(INPUT_BUTTON_1, SDL_CONTROLLER_BUTTON_X);
mInput->bindGameControllerButton(INPUT_BUTTON_2, SDL_CONTROLLER_BUTTON_Y);
mInput->bindGameControllerButton(INPUT_BUTTON_3, SDL_CONTROLLER_BUTTON_B);
mInput->bindGameControllerButton(INPUT_BUTTON_PAUSE, SDL_CONTROLLER_BUTTON_GUIDE); // PAUSE
mInput->bindGameControllerButton(INPUT_BUTTON_ESCAPE, SDL_CONTROLLER_BUTTON_GUIDE); // ESCAPE
}
// Inicializa JailAudio
void Director::initJailAudio()
{
JA_Init(48000, AUDIO_S16, 2);
}
// Arranca SDL y crea la ventana
bool Director::initSDL()
{
// Indicador de éxito
bool success = true;
// Inicializa SDL
//if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0)
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
printf("SDL could not initialize!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Inicia el generador de numeros aleatorios
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
// Establece el filtro de la textura a nearest
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(mOptions->filter).c_str()))
{
printf("Warning: Nearest texture filtering not enabled!\n");
}
// Crea la ventana
mWindow = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, VIEW_WIDTH, VIEW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
if (mWindow == NULL)
{
printf("Window could not be created!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Crea un renderizador para la ventana. El vsync se activa en funcion de las opciones
if (mOptions->vSync)
mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
else
mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED);
if (mRenderer == NULL)
{
printf("Renderer could not be created!\nSDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
// Inicializa el color de renderizado
SDL_SetRenderDrawColor(mRenderer, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(mRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(mRenderer, SDL_BLENDMODE_BLEND);
}
}
}
printf("\n");
return success;
}
// Crea el indice de ficheros
void Director::setFileList()
{
// Inicializa el vector
for (int i = 0; i < MAX_FILE_LIST; i++)
mFileList[i] = "";
// Ficheros binarios
#ifdef __MIPSEL__
mFileList[0] = "/media/data/local/home/.coffee_crisis/score.bin";
mFileList[1] = "/media/data/local/home/.coffee_crisis/demo.bin";
mFileList[2] = "/media/data/local/home/.coffee_crisis/config.bin";
#else
mFileList[0] = mExecutablePath + "/" + "../data/score.bin";
mFileList[1] = mExecutablePath + "/" + "../data/demo.bin";
mFileList[2] = mExecutablePath + "/" + "../data/config.bin";
#endif
// Musicas
mFileList[3] = mExecutablePath + "/" + "../media/music/intro.ogg";
mFileList[4] = mExecutablePath + "/" + "../media/music/playing.ogg";
mFileList[5] = mExecutablePath + "/" + "../media/music/title.ogg";
// Sonidos
mFileList[6] = mExecutablePath + "/" + "../media/sound/balloon.wav";
mFileList[7] = mExecutablePath + "/" + "../media/sound/bubble1.wav";
mFileList[8] = mExecutablePath + "/" + "../media/sound/bubble2.wav";
mFileList[9] = mExecutablePath + "/" + "../media/sound/bubble3.wav";
mFileList[10] = mExecutablePath + "/" + "../media/sound/bubble4.wav";
mFileList[11] = mExecutablePath + "/" + "../media/sound/bullet.wav";
mFileList[12] = mExecutablePath + "/" + "../media/sound/coffeeout.wav";
mFileList[13] = mExecutablePath + "/" + "../media/sound/hiscore.wav";
mFileList[14] = mExecutablePath + "/" + "../media/sound/itemdrop.wav";
mFileList[15] = mExecutablePath + "/" + "../media/sound/itempickup.wav";
mFileList[16] = mExecutablePath + "/" + "../media/sound/menu_cancel.wav";
mFileList[17] = mExecutablePath + "/" + "../media/sound/menu_move.wav";
mFileList[18] = mExecutablePath + "/" + "../media/sound/menu_select.wav";
mFileList[19] = mExecutablePath + "/" + "../media/sound/player_collision.wav";
mFileList[20] = mExecutablePath + "/" + "../media/sound/stage_change.wav";
mFileList[21] = mExecutablePath + "/" + "../media/sound/title.wav";
mFileList[22] = mExecutablePath + "/" + "../media/sound/clock.wav";
mFileList[23] = mExecutablePath + "/" + "../media/sound/powerball.wav";
// Texturas
mFileList[24] = mExecutablePath + "/" + "../media/gfx/balloon.png";
mFileList[25] = mExecutablePath + "/" + "../media/gfx/bullet.png";
mFileList[31] = mExecutablePath + "/" + "../media/gfx/game_bg.png";
mFileList[32] = mExecutablePath + "/" + "../media/gfx/game_text.png";
mFileList[33] = mExecutablePath + "/" + "../media/gfx/intro.png";
mFileList[34] = mExecutablePath + "/" + "../media/gfx/items.png";
mFileList[35] = mExecutablePath + "/" + "../media/gfx/logo.png";
mFileList[37] = mExecutablePath + "/" + "../media/gfx/player1_body.png";
mFileList[38] = mExecutablePath + "/" + "../media/gfx/player1_death.png";
mFileList[39] = mExecutablePath + "/" + "../media/gfx/player1_legs.png";
mFileList[40] = mExecutablePath + "/" + "../media/gfx/title.png";
mFileList[41] = mExecutablePath + "/" + "../media/gfx/player1_head.png";
mFileList[42] = mExecutablePath + "/" + "../media/gfx/player2_body.png";
mFileList[43] = mExecutablePath + "/" + "../media/gfx/player2_death.png";
mFileList[44] = mExecutablePath + "/" + "../media/gfx/player2_legs.png";
mFileList[45] = mExecutablePath + "/" + "../media/gfx/player2_head.png";
// Fuentes
mFileList[27] = mExecutablePath + "/" + "../media/font/8bithud.png";
mFileList[46] = mExecutablePath + "/" + "../media/font/8bithud.txt";
mFileList[28] = mExecutablePath + "/" + "../media/font/nokia.png";
mFileList[54] = mExecutablePath + "/" + "../media/font/nokia_big2.png";
mFileList[52] = mExecutablePath + "/" + "../media/font/nokia.txt";
mFileList[56] = mExecutablePath + "/" + "../media/font/nokia2.png";
mFileList[57] = mExecutablePath + "/" + "../media/font/nokia2.txt";
mFileList[55] = mExecutablePath + "/" + "../media/font/nokia_big2.txt";
mFileList[29] = mExecutablePath + "/" + "../media/font/smb2_big.png";
mFileList[47] = mExecutablePath + "/" + "../media/font/smb2_big.txt";
mFileList[30] = mExecutablePath + "/" + "../media/font/smb2.png";
mFileList[48] = mExecutablePath + "/" + "../media/font/smb2.txt";
// Textos
mFileList[49] = mExecutablePath + "/" + "../media/lang/es_ES.txt";
mFileList[50] = mExecutablePath + "/" + "../media/lang/en_UK.txt";
mFileList[51] = mExecutablePath + "/" + "../media/lang/ba_BA.txt";
// DATA
mFileList[53] = mExecutablePath + "/" + "../data/gamecontrollerdb.txt";
}
// Comprueba los ficheros del vector de ficheros que coinciden con una ruta dada
bool Director::checkFolder(std::string name, std::string path)
{
bool success = true;
std::string p;
std::string filename;
SDL_RWops *file;
// Comprueba los ficheros de la carpeta
printf("\n>> %s FILES\n", name.c_str());
for (int i = 3; i < MAX_FILE_LIST; i++)
{
if (mFileList[i].find(path.c_str()) != std::string::npos)
{
p = mFileList[i].c_str();
filename = p.substr(p.find_last_of("\\/") + 1);
file = SDL_RWFromFile(p.c_str(), "r+b");
if (file != NULL)
{
printf("Checking file %-20s [OK]\n", filename.c_str());
}
else
{
printf("Checking file %-20s [ERROR]\n", filename.c_str());
success = false;
break;
}
SDL_RWclose(file);
}
}
return success;
}
// Comprueba que todos los ficheros existen
bool Director::checkFileList()
{
bool success = true;
printf("Checking files...\n");
if (success)
success &= checkFolder("MUSIC", "/media/music/");
if (success)
success &= checkFolder("SOUND", "/media/sound/");
if (success)
success &= checkFolder("BITMAP", "/media/gfx/");
if (success)
success &= checkFolder("FONT", "/media/font/");
if (success)
success &= checkFolder("LANG", "/media/lang/");
// Resultado
if (success)
printf("\n** All files OK.\n\n");
else
printf("\n** A file is missing. Exiting.\n\n");
return success;
}
// Carga el fichero de configuración
bool Director::loadConfigFile()
{
// Pone unos valores por defecto
mOptions->fullScreenMode = 0;
mOptions->windowSize = 3;
mOptions->language = en_UK;
mOptions->difficulty = DIFFICULTY_NORMAL;
mOptions->input[0].deviceType = INPUT_USE_KEYBOARD;
mOptions->input[1].deviceType = INPUT_USE_GAMECONTROLLER;
mOptions->filter = FILTER_NEAREST;
mOptions->vSync = true;
// Indicador de éxito en la carga
bool success = true;
const std::string p = mFileList[2];
std::string filename = p.substr(p.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b");
// El fichero no existe
if (file == NULL)
{
printf("Warning: Unable to open %s file\n", filename.c_str());
// Crea el fichero para escritura
file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != NULL)
{
printf("New file (%s) created!\n", filename.c_str());
// Escribe los datos
SDL_RWwrite(file, &mOptions->fullScreenMode, sizeof(mOptions->fullScreenMode), 1);
SDL_RWwrite(file, &mOptions->windowSize, sizeof(mOptions->windowSize), 1);
SDL_RWwrite(file, &mOptions->language, sizeof(mOptions->language), 1);
SDL_RWwrite(file, &mOptions->difficulty, sizeof(mOptions->difficulty), 1);
SDL_RWwrite(file, &mOptions->input[0].deviceType, sizeof(mOptions->input[0].deviceType), 1);
SDL_RWwrite(file, &mOptions->input[1].deviceType, sizeof(mOptions->input[1].deviceType), 1);
SDL_RWwrite(file, &mOptions->filter, sizeof(mOptions->filter), 1);
SDL_RWwrite(file, &mOptions->vSync, sizeof(mOptions->vSync), 1);
// Cierra el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to create file %s\n", filename.c_str());
success = false;
}
}
// El fichero existe
else
{
// Carga los datos
printf("Reading file %s\n", filename.c_str());
SDL_RWread(file, &mOptions->fullScreenMode, sizeof(mOptions->fullScreenMode), 1);
SDL_RWread(file, &mOptions->windowSize, sizeof(mOptions->windowSize), 1);
SDL_RWread(file, &mOptions->language, sizeof(mOptions->language), 1);
SDL_RWread(file, &mOptions->difficulty, sizeof(mOptions->difficulty), 1);
SDL_RWread(file, &mOptions->input[0].deviceType, sizeof(mOptions->input[0].deviceType), 1);
SDL_RWread(file, &mOptions->input[1].deviceType, sizeof(mOptions->input[1].deviceType), 1);
SDL_RWread(file, &mOptions->filter, sizeof(mOptions->filter), 1);
SDL_RWread(file, &mOptions->vSync, sizeof(mOptions->vSync), 1);
// Normaliza los valores
if (!((mOptions->fullScreenMode == 0) ||
(mOptions->fullScreenMode == SDL_WINDOW_FULLSCREEN) ||
(mOptions->fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP)))
mOptions->fullScreenMode = 0;
if ((mOptions->windowSize < 1) || (mOptions->windowSize > 4))
mOptions->windowSize = 3;
if ((mOptions->language < 0) || (mOptions->language > MAX_LANGUAGES))
mOptions->language = en_UK;
// Cierra el fichero
SDL_RWclose(file);
}
return success;
}
// Guarda el fichero de configuración
bool Director::saveConfigFile()
{
bool success = true;
const std::string p = mFileList[2];
std::string filename = p.substr(p.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(p.c_str(), "w+b");
if (file != NULL)
{
// Guarda los datos
SDL_RWwrite(file, &mOptions->fullScreenMode, sizeof(mOptions->fullScreenMode), 1);
SDL_RWwrite(file, &mOptions->windowSize, sizeof(mOptions->windowSize), 1);
SDL_RWwrite(file, &mOptions->language, sizeof(mOptions->language), 1);
SDL_RWwrite(file, &mOptions->difficulty, sizeof(mOptions->difficulty), 1);
SDL_RWwrite(file, &mOptions->input[0].deviceType, sizeof(mOptions->input[0].deviceType), 1);
SDL_RWwrite(file, &mOptions->input[1].deviceType, sizeof(mOptions->input[1].deviceType), 1);
SDL_RWwrite(file, &mOptions->filter, sizeof(mOptions->filter), 1);
SDL_RWwrite(file, &mOptions->vSync, sizeof(mOptions->vSync), 1);
printf("Writing file %s\n", filename.c_str());
// Cierra el fichero
SDL_RWclose(file);
}
else
{
printf("Error: Unable to save %s file! %s\n", filename.c_str(), SDL_GetError());
}
return success;
}
// Establece el valor de la variable
void Director::setExecutablePath(std::string path)
{
mExecutablePath = path.substr(0, path.find_last_of("\\/"));
}
// Obtiene el valor de la variable
Uint8 Director::getSubsection()
{
return mSection.subsection;
}
// Obtiene el valor de la variable
Uint8 Director::getSection()
{
return mSection.name;
}
// Establece el valor de la variable
void Director::setSection(section_t section)
{
mSection = section;
}
void Director::runLogo()
{
mLogo = new Logo(mRenderer, mFileList);
setSection(mLogo->run());
delete mLogo;
}
void Director::runIntro()
{
mIntro = new Intro(mRenderer, mFileList, mLang);
setSection(mIntro->run());
delete mIntro;
}
void Director::runTitle()
{
mTitle = new Title(mWindow, mRenderer, mInput, mFileList, mOptions, mLang);
setSection(mTitle->run(mSection.subsection));
delete mTitle;
}
void Director::runGame()
{
if (mSection.subsection == GAME_SECTION_PLAY_1P)
mGame = new Game(1, mRenderer, mFileList, mLang, mInput, false, mOptions);
if (mSection.subsection == GAME_SECTION_PLAY_2P)
mGame = new Game(2, mRenderer, mFileList, mLang, mInput, false, mOptions);
setSection(mGame->run());
delete mGame;
}
void Director::run()
{
// Bucle principal
while (!(getSection() == PROG_SECTION_QUIT))
{
switch (getSection())
{
case PROG_SECTION_LOGO:
runLogo();
break;
case PROG_SECTION_INTRO:
runIntro();
break;
case PROG_SECTION_TITLE:
runTitle();
break;
case PROG_SECTION_GAME:
runGame();
break;
}
}
}

109
source/director.h Normal file
View File

@@ -0,0 +1,109 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "player.h"
#include "balloon.h"
#include "bullet.h"
#include "coffeedrop.h"
#include "item.h"
#include "text.h"
#include "writer.h"
#include "menu.h"
#include "const.h"
#include "jail_audio.h"
#include "utils.h"
#include "logo.h"
#include "intro.h"
#include "title.h"
#include "game.h"
#include "input.h"
#include "fade.h"
//#include <math.h>
#ifndef DIRECTOR_H
#define DIRECTOR_H
#define MAX_FILE_LIST 100
// Director
class Director
{
private:
SDL_Window *mWindow; // La ventana donde dibujamos
SDL_Renderer *mRenderer; // El renderizador de la ventana
Logo *mLogo; // Objeto para la sección del logo
Intro *mIntro; // Objeto para la sección de la intro
Title *mTitle; // Objeto para la sección del titulo y el menu de opciones
Game *mGame; // Objeto para la sección del juego
Input *mInput; // Objeto Input para gestionar las entradas
Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas
std::string mFileList[MAX_FILE_LIST]; // Vector con las rutas a los ficheros de recursos
struct options_t *mOptions; // Variable con todas las opciones del programa
std::string mExecutablePath; // Path del ejecutable
section_t mSection; // Sección y subsección actual del programa;
// Inicializa jail_audio
void initJailAudio();
// Arranca SDL y crea la ventana
bool initSDL();
// Crea el indice de ficheros
void setFileList();
// Comprueba que todos los ficheros existen
bool checkFileList();
// Carga el fichero de configuración
bool loadConfigFile();
// Guarda el fichero de configuración
bool saveConfigFile();
// Establece el valor de la variable
void setExecutablePath(std::string path);
// Obtiene el valor de la variable
Uint8 getSubsection();
// Obtiene el valor de la variable
Uint8 getSection();
// Establece el valor de la variable
void setSection(section_t section);
// Ejecuta la seccion de juego con el logo
void runLogo();
// Ejecuta la seccion de juego de la introducción
void runIntro();
// Ejecuta la seccion de juego con el titulo y los menus
void runTitle();
// Ejecuta la seccion de juego donde se juega
void runGame();
// Comprueba los ficheros del vector de ficheros que coinciden con una ruta dada
bool checkFolder(std::string name, std::string path);
public:
// Constructor
Director(std::string path);
// Destructor
~Director();
// Inicia las variables necesarias para arrancar el programa
void init(Uint8 name);
// Bucle principal
void run();
};
#endif

172
source/fade.cpp Normal file
View File

@@ -0,0 +1,172 @@
#include "fade.h"
#include "const.h"
// Constructor
Fade::Fade(SDL_Renderer *renderer)
{
mRenderer = renderer;
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
if (mBackbuffer == NULL)
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
}
// Destructor
Fade::~Fade()
{
SDL_DestroyTexture(mBackbuffer);
mBackbuffer = nullptr;
}
// Inicializa las variables
void Fade::init(Uint8 r, Uint8 g, Uint8 b)
{
mFadeType = FADE_CENTER;
mEnabled = false;
mFinished = false;
mCounter = 0;
//mR = 0x27;
//mG = 0x27;
//mB = 0x36;
mR = r;
mG = g;
mB = b;
}
// Pinta una transición en pantalla
void Fade::render()
{
if (mEnabled && !mFinished)
{
switch (mFadeType)
{
case FADE_FULLSCREEN:
mRect1 = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
for (int i = 0; i < 256; i += 4)
{
// Dibujamos sobre el renderizador
SDL_SetRenderTarget(mRenderer, NULL);
// Copia el backbuffer con la imagen que había al renderizador
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, i);
SDL_RenderFillRect(mRenderer, &mRect1);
// Vuelca el renderizador en pantalla
SDL_RenderPresent(mRenderer);
}
// Deja todos los buffers del mismo color
SDL_SetRenderTarget(mRenderer, mBackbuffer);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 255);
SDL_RenderClear(mRenderer);
SDL_SetRenderTarget(mRenderer, NULL);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 255);
SDL_RenderClear(mRenderer);
break;
case FADE_CENTER:
mRect1 = {0, 0, SCREEN_WIDTH, 0};
mRect2 = {0, 0, SCREEN_WIDTH, 0};
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 64);
for (int i = 0; i < mCounter; i++)
{
mRect1.h = mRect2.h = i * 4;
mRect2.y = SCREEN_HEIGHT - (i * 4);
SDL_RenderFillRect(mRenderer, &mRect1);
SDL_RenderFillRect(mRenderer, &mRect2);
}
if ((mCounter * 4) > SCREEN_HEIGHT)
mFinished = true;
break;
case FADE_RANDOM_SQUARE:
mRect1 = {0, 0, 32, 32};
for (Uint16 i = 0; i < 50; i++)
{
// Crea un color al azar
mR = 255 * (rand() % 2);
mG = 255 * (rand() % 2);
mB = 255 * (rand() % 2);
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 64);
// Dibujamos sobre el backbuffer
SDL_SetRenderTarget(mRenderer, mBackbuffer);
mRect1.x = rand() % (SCREEN_WIDTH - mRect1.w);
mRect1.y = rand() % (SCREEN_HEIGHT - mRect1.h);
SDL_RenderFillRect(mRenderer, &mRect1);
// Volvemos a usar el renderizador de forma normal
SDL_SetRenderTarget(mRenderer, NULL);
// Copiamos el backbuffer al renderizador
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, NULL);
// Volcamos el renderizador en pantalla
SDL_RenderPresent(mRenderer);
SDL_Delay(100);
}
break;
default:
break;
}
}
if (mFinished)
{
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 255);
SDL_RenderClear(mRenderer);
}
}
// Actualiza las variables internas
void Fade::update()
{
if (mEnabled)
mCounter++;
}
// Activa el fade
void Fade::activateFade()
{
mEnabled = true;
mFinished = false;
mCounter = 0;
}
// Comprueba si está activo
bool Fade::isEnabled()
{
return mEnabled;
}
// Comprueba si ha terminado la transicion
bool Fade::hasEnded()
{
if (mFinished)
{
//mEnabled = false;
//mFinished = false;
return true;
}
else
{
return false;
}
}
// Establece el tipo de fade
void Fade::setFadeType(Uint8 fadeType)
{
mFadeType = fadeType;
}

55
source/fade.h Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include "ifdefs.h"
#include "ltexture.h"
#ifndef FADE_H
#define FADE_H
#define FADE_FULLSCREEN 0
#define FADE_CENTER 1
#define FADE_RANDOM_SQUARE 2
// Fade
class Fade
{
private:
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
Uint8 mFadeType; // Tipo de fade a realizar
Uint16 mCounter; // Contador interno
bool mEnabled; // Indica si el fade está activo
bool mFinished; // Indica si ha terminado la transición
Uint8 mR, mG, mB; // Colores para el fade
SDL_Rect mRect1; // Rectangulo usado para crear los efectos de transición
SDL_Rect mRect2; // Rectangulo usado para crear los efectos de transición
public:
// Constructor
Fade(SDL_Renderer *renderer);
// Destructor
~Fade();
// Inicializa las variables
void init(Uint8 r, Uint8 g, Uint8 b);
// Pinta una transición en pantalla
void render();
// Actualiza las variables internas
void update();
// Activa el fade
void activateFade();
// Comprueba si ha terminado la transicion
bool hasEnded();
// Comprueba si está activo
bool isEnabled();
// Establece el tipo de fade
void setFadeType(Uint8 fadeType);
};
#endif

3483
source/game.cpp Normal file

File diff suppressed because it is too large Load Diff

512
source/game.h Normal file
View File

@@ -0,0 +1,512 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "player.h"
#include "balloon.h"
#include "bullet.h"
#include "item.h"
#include "text.h"
#include "writer.h"
#include "menu.h"
#include "input.h"
#include "fade.h"
#include "jail_audio.h"
#ifndef GAME_H
#define GAME_H
// Game
class Game
{
private:
struct enemyInits_t
{
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float velX; // Velocidad inicial en el eje X
Uint8 kind; // Tipo de enemigo
Uint16 creationCounter; // Temporizador para la creación del enemigo
};
struct enemyFormation_t // Contiene la información de una formación enemiga
{
Uint8 numberOfEnemies; // Cantidad de enemigos que forman la formación
enemyInits_t init[MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
};
enemyFormation_t mEnemyFormation[NUMBER_OF_ENEMY_FORMATIONS]; // Vector con todas las formaciones enemigas
struct enemyPool_t
{
enemyFormation_t *set[10]; // Conjunto de formaciones enemigas
};
enemyPool_t mEnemyPool[10]; // Variable con los diferentes conjuntos de formaciones enemigas
struct stage_t // Contiene todas las variables relacionadas con una fase
{
enemyPool_t *enemyPool; // El conjunto de formaciones enemigas de la fase
Uint16 currentPower; // Cantidad actual de poder
Uint16 powerToComplete; // Cantidad de poder que se necesita para completar la fase
Uint8 maxMenace; // Umbral máximo de amenaza de la fase
Uint8 minMenace; // Umbral mínimo de amenaza de la fase
Uint8 number; // Numero de fase
};
struct effect_t
{
bool flash; // Indica si se ha de pintar la pantalla de blanco
bool shake; // Indica si se ha de agitar la pantalla
Uint8 shakeCounter; // Contador para medir el tiempo que dura el efecto
};
struct helper_t
{
bool needCoffee; // Indica si se necesitan cafes
bool needCoffeeMachine; // Indica si se necesita PowerUp
bool needPowerBall; // Indica si se necesita una PowerBall
int counter; // Contador para no dar ayudas consecutivas
int itemPoints1Odds; // Probabilidad de aparición del objeto
int itemPoints2Odds; // Probabilidad de aparición del objeto
int itemPoints3Odds; // Probabilidad de aparición del objeto
int itemClockOdds; // Probabilidad de aparición del objeto
int itemCoffeeOdds; // Probabilidad de aparición del objeto
int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto
};
SDL_Renderer *mRenderer; // El renderizador de la ventana
std::string *mFileList; // Lista de ficheros con los recursos
Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas
int mNumPlayers; // Numero de jugadores
Player *mPlayer[2]; // Vector con los jugadores jugador
Input *mInput; // Manejador de entrada
Balloon *mBalloon[MAX_BALLOONS]; // Vector con los objetos globo
Bullet *mBullet[MAX_BULLETS]; // Vector con los objetos bala
Item *mItem[MAX_ITEMS]; // Vector con los objetos item
SmartSprite *mSmartSprite[MAX_SMART_SPRITES]; // Vector para almacenar y gestionar SmartSprites
LTexture *mTextureBalloon; // Textura para los enemigos
LTexture *mTextureBullet; // Textura para las balas
LTexture *mTextureGameBG; // Textura para el fondo del juego
LTexture *mTextureGameText; // Textura para los sprites con textos
LTexture *mTextureItems; // Textura para los items
LTexture *mTexturePlayer1Head; // Textura para la cabeza del jugador1
LTexture *mTexturePlayer1Body; // Textura para el cuerpo del jugador1
LTexture *mTexturePlayer1Death; // Textura para la animación de muerte del jugador1
LTexture *mTexturePlayer1Legs; // Textura para las piernas del jugador
LTexture *mTexturePlayer2Head; // Textura para la cabeza del jugador2
LTexture *mTexturePlayer2Body; // Textura para el cuerpo del jugador2
LTexture *mTexturePlayer2Death; // Textura para la animación de muerte del jugador2
LTexture *mTexturePlayer2Legs; // Textura para las piernas del jugador
LTexture *mTextureText; // Textura para el texto del juego
LTexture *mTextureTextScoreBoard; // Textura para el texto del marcador
LTexture *mTextureTextBig; // Textura para el texto grande
LTexture *mTextureTextNokia2; // Textura para la fuente de texto Nokia
LTexture *mTextureTextNokiaBig2; // Textura para la fuente de texto Nokia grande
Text *mText; // Fuente para los textos del juego
Text *mTextBig; // Fuente de texto grande
Text *mTextScoreBoard; // Fuente para el marcador del juego
Text *mTextNokia2; // Otra fuente de texto para mesajes
Text *mTextNokiaBig2; // Y la versión en grande
Menu *mMenuGameOver; // Menú de la pantalla de game over
Menu *mMenuPause; // Menú de la pantalla de pausa
Fade *mFade; // Objeto para renderizar fades
SDL_Event *mEventHandler; // Manejador de eventos
MovingSprite *mClouds1a; // Sprite para las nubes superiores
MovingSprite *mClouds1b; // Sprite para las nubes superiores
MovingSprite *mClouds2a; // Sprite para las nubes inferiores
MovingSprite *mClouds2b; // Sprite para las nubes inferiores
SmartSprite *m1000Bitmap; // Sprite con el texto 1.000
SmartSprite *m2500Bitmap; // Sprite con el texto 2.500
SmartSprite *m5000Bitmap; // Sprite con el texto 5.000
Sprite *mSpriteBackground; // Sprite con los graficos frontales del fondo
Sprite *mSpriteGetReady; // Sprite para el texto de GetReady del principio de la partida
Sprite *mSpriteGradient; // Sprite con los graficos del degradado de color de fondo
Sprite *mSpriteGrass; // Sprite para la hierba
Sprite *mSpritePowerMeter; // Sprite para el medidor de poder de la fase
Sprite *mSpriteScoreBoard; // Sprite para el fondo del marcador
JA_Sound mSoundBalloon; // Sonido para la explosión del globo
JA_Sound mSoundBullet; // Sonido para los disparos
JA_Sound mSoundPlayerCollision; // Sonido para la colisión del jugador con un enemigo
JA_Sound mSoundHiScore; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound mSoundItemDrop; // Sonido para cuando se genera un item
JA_Sound mSoundItemPickup; // Sonido para cuando se recoge un item
JA_Sound mSoundCoffeeOut; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound mSoundStageChange; // Sonido para cuando se cambia de fase
JA_Sound mSoundBubble1; // Sonido para cuando el jugador muere
JA_Sound mSoundBubble2; // Sonido para cuando el jugador muere
JA_Sound mSoundBubble3; // Sonido para cuando el jugador muere
JA_Sound mSoundBubble4; // Sonido para cuando el jugador muere
JA_Sound mSoundClock; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound mSoundPowerBall; // Sonido para cuando se explota una Power Ball
JA_Sound mSoundCollision; // Sonido para cuando la máquina de café toca el suelo
JA_Music mMusicPlaying; // Musica de fondo
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
Uint32 mHiScore; // Puntuación máxima
bool mHiScoreAchieved; // Indica si se ha superado la puntuación máxima
section_t mSection; // Seccion actual dentro del juego
stage_t mStage[10]; // Variable con los datos de cada pantalla
Uint8 mCurrentStage; // Indica la fase actual
Uint8 mStageBitmapCounter; // Contador para el tiempo visible del texto de Stage
float mStageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
float mGetReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
Uint16 mDeathCounter; // Contador para la animación de muerte del jugador
Uint8 mDeathIndex; // Indice del vector de smartsprites que contiene el sprite del jugador
Uint8 mMenaceCurrent; // Nivel de amenaza actual
Uint8 mMenaceThreshold; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el numero de globos
bool mTimeStopped; // Indica si el tiempo está detenido
Uint16 mTimeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido
Uint8 mRemainingExplosions; // Cantidad de explosiones restantes
Uint16 mRemainingExplosionsCounter; // Temporizador para la cantidad de explosiones restantes
bool mExplosionTime; // Indica si las explosiones estan en marcha
Uint32 mCounter; // Contador para el juego
Uint32 mScoreDataFile[TOTAL_SCORE_DATA]; // Datos del fichero de puntos
SDL_Rect mGradientRect[4]; // Vector con las coordenadas de los 4 gradientes
Uint16 mBalloonsPopped; // Lleva la cuenta de los globos explotados
Uint8 mLastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir;
Uint8 mEnemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float mEnemySpeed; // Velocidad a la que se mueven los enemigos
float mDefaultEnemySpeed; // Velocidad base de los enemigos, sin incrementar
effect_t mEffect; // Variable para gestionar los efectos visuales
helper_t mHelper; // Variable para gestionar las ayudas
bool mPowerBallEnabled; // Indica si hay una powerball ya activa
Uint8 mPowerBallCounter; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
bool mCoffeeMachineEnabled; // Indica si hay una máquina de café en el terreno de juego
Uint8 mPostFade; // Qué hacer al acabar el fade
float mSin[360]; // Vector con los valores del seno para 360 grados
bool mGameCompleted; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
int mGameCompletedCounter; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
Uint8 mDifficulty; // Dificultad del juego
float mDifficultyScoreMultiplier; // Multiplicador de puntos en función de la dificultad
struct options_t *mOptions; // Variable con todas las variables de las opciones del programa
Uint8 mOnePlayerControl; // Variable para almacenar el valor de las opciones
struct demo_t
{
bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo
Uint16 counter; // Contador para el modo demo
demoKeys_t keys; // Variable con las pulsaciones de teclas del modo demo
demoKeys_t dataFile[TOTAL_DEMO_DATA]; // Datos del fichero con los movimientos para la demo
};
demo_t mDemo; // Variable con todas las variables relacionadas con el modo demo
struct debug_t
{
bool enabled; // Indica si se va a mostrar la información de debug
Uint8 enemySet; // Escoge el set enemigo a generar
Uint8 gradR, gradG, gradB; // Colores RGB para modificar el color del gradiente de fondo
float hudW, hudH; // Multiplica el tamaño del hud de debug;
};
debug_t mDebug;
// Inicializa el vector con los valores del seno
void initSin();
// Inicializa las variables necesarias para la sección 'Game'
void init();
// Carga los recursos necesarios para la sección 'Game'
bool loadMedia();
// Carga el fichero de puntos
bool loadScoreFile();
// Carga el fichero de datos para la demo
bool loadDemoFile();
// Guarda el fichero de puntos
bool saveScoreFile();
// Guarda el fichero de datos para la demo
bool saveDemoFile();
// Inicializa las formaciones enemigas
void initEnemyFormations();
// Inicializa los conjuntos de formaciones
void initEnemyPools();
// Inicializa las fases del juego
void initGameStages();
// Crea una formación de enemigos
void deployEnemyFormation();
// Aumenta el poder de la fase
void increaseStageCurrentPower(Uint8 power);
// Establece el valor de la variable
void setHiScore(Uint32 score);
// Actualiza el valor de HiScore en caso necesario
void updateHiScore();
// Transforma un valor numérico en una cadena de 6 cifras
std::string updateScoreText(Uint32 num);
// Pinta el marcador en pantalla usando un objeto texto
void renderScoreBoard();
// Actualiza las variables del jugador
void updatePlayer();
// Actualiza las variables de la fase
void updateStage();
// Actualiza el estado de muerte
void updateDeath();
// Renderiza el fade final cuando se acaba la partida
void renderDeathFade(int counter);
// Actualiza los globos
void updateBalloons();
// Pinta en pantalla todos los globos activos
void renderBalloons();
// Devuelve el primer indice no activo del vector de globos
Uint8 getBalloonFreeIndex();
// Crea un globo nuevo en el vector de globos
Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, float speed, Uint16 stoppedcounter, LTexture *texture);
// Crea una PowerBall
void createPowerBall();
// Establece a cero todos los valores del vector de objetos globo
void resetBalloons();
// Establece la velocidad de los globos
void setBalloonSpeed(float speed);
// Incrementa la velocidad de los globos
void incBalloonSpeed();
// Decrementa la velocidad de los globos
void decBalloonSpeed();
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void updateBalloonSpeed();
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(Uint8 index);
// Explosiona un globo. Lo destruye
void destroyBalloon(Uint8 index);
// Explosiona todos los globos
void popAllBalloons();
// Destruye todos los globos
void destroyAllBalloons();
// Detiene todos los globos
void stopAllBalloons(Uint16 time);
// Pone en marcha todos los globos
void startAllBalloons();
// Obtiene el numero de globos activos
Uint8 countBalloons();
// Comprueba la colisión entre el jugador y los globos activos
bool checkPlayerBalloonCollision(int index);
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(int index);
// Comprueba la colisión entre las balas y los globos
void checkBulletBalloonCollision();
// Mueve las balas activas
void moveBullets();
// Pinta las balas activas
void renderBullets();
// Devuelve el primer indice no activo del vector de balas
Uint8 getBulletFreeIndex();
// Establece a cero todos los valores del vector de objetos bala
void resetBullets();
// Crea un objeto bala
void createBullet(int x, int y, Uint8 kind, bool poweredUp, int owner);
// Actualiza los items
void updateItems();
// Pinta los items activos
void renderItems();
// Devuelve el primer indice no activo del vector de items
Uint8 getItemFreeIndex();
// Establece a cero todos los valores del vector de objetos item
void resetItems();
// Devuelve un item en función del azar
Uint8 dropItem();
// Crea un objeto item
void createItem(int x, int y, Uint8 kind);
// Crea un objeto SmartSprite
void createItemScoreSprite(int x, int y, SmartSprite *sprite);
// Dibuja el efecto de flash
void renderFlashEffect();
// Actualiza el efecto de agitar la pantalla
void updateShakeEffect();
// Crea un SmartSprite para arrojar el item café al recibir un impacto
void throwCoffee(int x, int y);
// Crea un SmartSprite para arrojar al jugador al morir
void throwPlayer(int x, int y, int index);
// Actualiza los SmartSprites
void updateSmartSprites();
// Pinta los SmartSprites activos
void renderSmartSprites();
// Devuelve el primer indice no activo del vector de SmartSprites
Uint8 getSmartSpriteFreeIndex();
// Establece a cero todos los valores del vector de objetos SmafrtSprite
void resetSmartSprites();
// Acciones a realizar cuando el jugador muere
void killPlayer(int index);
// Obtiene el valor de la variable
Uint8 getSubsection();
// Calcula y establece el valor de amenaza en funcion de los globos activos
void evaluateAndSetMenace();
// Obtiene el valor de la variable
Uint8 getMenace();
// Establece el valor de la variable
void setTimeStopped(bool value);
// Obtiene el valor de la variable
bool isTimeStopped();
// Establece el valor de la variable
void setTimeStoppedCounter(Uint16 value);
// Incrementa el valor de la variable
void incTimeStoppedCounter(Uint16 value);
// Actualiza la variable EnemyDeployCounter
void updateEnemyDeployCounter();
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter();
// Establece el valor de la variable
void setExplosionTime(bool value);
// Obtiene el valor de la variable
bool isExplosionTime();
// Establece el valor de la variable
void setRemainingExplosions(Uint8 value);
// Actualiza y comprueba el valor de la variable
void updateRemainingExplosionsCounter();
// Gestiona el nivel de amenaza
void updateMenace();
// Actualiza el campo de juego
void updatePlayField();
// Actualiza el fondo
void updateBackground();
// Dibuja el fondo
void renderBackground();
// Dibuja el campo de juego
void renderPlayField();
// Gestiona las entradas desde el mando de juego
bool checkGameController(Uint8 state);
// Gestiona la entrada durante el juego
void checkGameInput();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
// Habilita el efecto del item de detener el tiempo
void enableTimeStopItem();
// Deshabilita el efecto del item de detener el tiempo
void disableTimeStopItem();
// Agita la pantalla
void shakeScreen();
// Bucle para el menu de pausa del juego
void runPausedGame();
// Bucle para la pantalla de game over
void runGameOverScreen();
// Dibuja la informacion de debug en pantalla
void renderDebugInfo();
// Indica si se puede crear una powerball
bool canPowerBallBeCreated();
// Calcula el poder actual de los globos en pantalla
int calculateScreenPower();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Actualiza el tramo final de juego, una vez completado
void updateGameCompleted();
// Actualiza las variables de ayuda
void updateHelper();
// Comprueba si todos los jugadores han muerto
bool allPlayersAreDead();
public:
// Constructor
Game(int numPlayers, SDL_Renderer *renderer, std::string *filelist, Lang *lang, Input *input, bool demo, options_t *options);
// Destructor
~Game();
// Bucle para el juego
section_t run();
};
#endif

22
source/ifdefs.h Normal file
View File

@@ -0,0 +1,22 @@
#ifdef _WIN64
#include "C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\SDL2\SDL.h"
#endif
#ifdef _WIN32
#include "C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\SDL2\SDL.h"
#endif
#ifdef __APPLE__
//#include "/Library/Frameworks/SDL2.framework/Versions/A/Headers/SDL.h"
#include <SDL2/SDL.h>
#endif
#ifdef __linux__
#ifdef __MIPSEL__
#include "SDL.h"
#else
#include <SDL2/SDL.h>
#endif
#endif
#define UNUSED

209
source/input.cpp Normal file
View File

@@ -0,0 +1,209 @@
#include "input.h"
#include <iostream>
// Contestar cuantos joystics ha detectado
// Preguntarlepor los joystics que ha encontrado para ir poniendolos en la variable de opciones
// Constructor
Input::Input(std::string file)
{
// Fichero gamecontrollerdb.txt
mDBpath = file;
// Inicializa las variables
for (int i = 0; i < 17; i++)
{
mKeyBindings[i].scancode = 0;
mKeyBindings[i].active = false;
mGameControllerBindings[i].button = SDL_CONTROLLER_BUTTON_INVALID;
mGameControllerBindings[i].active = false;
}
discoverGameController();
}
// Destructor
Input::~Input()
{
for (int i = 0; i < mNumGamepads; i++)
mConnectedControllers[i] = nullptr;
}
// Asigna uno de los posibles inputs a una tecla del teclado
void Input::bindKey(Uint8 input, SDL_Scancode code)
{
mKeyBindings[input].scancode = code;
}
// Asigna uno de los posibles inputs a un botón del mando
void Input::bindGameControllerButton(Uint8 input, SDL_GameControllerButton button)
{
mGameControllerBindings[input].button = button;
}
// Comprueba si un input esta activo
bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
{
bool successKeyboard = false;
bool successGameController = false;
if (device == INPUT_USE_ANY)
index = 0;
if ((device == INPUT_USE_KEYBOARD) || (device == INPUT_USE_ANY))
{
const Uint8 *mKeystates = SDL_GetKeyboardState(NULL);
if (repeat)
{
if (mKeystates[mKeyBindings[input].scancode] != 0)
successKeyboard = true;
else
successKeyboard = false;
}
else
{
if (!mKeyBindings[input].active)
{
if (mKeystates[mKeyBindings[input].scancode] != 0)
{
mKeyBindings[input].active = true;
successKeyboard = true;
}
else
{
successKeyboard = false;
}
}
else
{
if (mKeystates[mKeyBindings[input].scancode] == 0)
{
mKeyBindings[input].active = false;
successKeyboard = false;
}
else
{
successKeyboard = false;
}
}
}
}
if (gameControllerFound())
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{
if (repeat)
{
if (SDL_GameControllerGetButton(mConnectedControllers[index], mGameControllerBindings[input].button) != 0)
successGameController = true;
else
successGameController = false;
}
else
{
if (!mGameControllerBindings[input].active)
{
if (SDL_GameControllerGetButton(mConnectedControllers[index], mGameControllerBindings[input].button) != 0)
{
mGameControllerBindings[input].active = true;
successGameController = true;
}
else
{
successGameController = false;
}
}
else
{
if (SDL_GameControllerGetButton(mConnectedControllers[index], mGameControllerBindings[input].button) == 0)
{
mGameControllerBindings[input].active = false;
successGameController = false;
}
else
{
successGameController = false;
}
}
}
}
return (successKeyboard || successGameController);
}
// Comprueba si hay un mando conectado
bool Input::discoverGameController()
{
bool found = false;
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) != 1)
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
if (SDL_GameControllerAddMappingsFromFile(mDBpath.c_str()) < 0)
printf("Error, could not load %s file: %s\n", mDBpath.c_str(), SDL_GetError());
int nJoysticks = SDL_NumJoysticks();
mNumGamepads = 0;
// Cuenta el numero de mandos
for (int i = 0; i < nJoysticks; i++)
if (SDL_IsGameController(i))
mNumGamepads++;
printf("\nChecking for game controllers...\n");
printf("%i joysticks found, %i are gamepads\n", nJoysticks, mNumGamepads);
if (mNumGamepads > 0)
{
found = true;
for (int i = 0; i < mNumGamepads; i++)
{
// Abre el mando y lo añade a la lista
SDL_GameController *pad = SDL_GameControllerOpen(i);
if (SDL_GameControllerGetAttached(pad) == 1)
{
mConnectedControllers.push_back(pad);
std::string separator(" #");
std::string name = SDL_GameControllerNameForIndex(i);
name.resize(25);
name = name + separator + std::to_string(i);
std::cout << name << std::endl;
mControllerNames.push_back(name);
}
else
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
//mGameController = mConnectedControllers[0];
SDL_GameControllerEventState(SDL_ENABLE);
}
return found;
}
// Comprueba si hay algun mando conectado
bool Input::gameControllerFound()
{
if (mNumGamepads > 0)
return true;
else
return false;
}
// Obten el nombre de un mando de juego
std::string Input::getControllerName(int index)
{
if (mNumGamepads > 0)
return mControllerNames[index];
else
return "";
}
// Obten el numero de mandos conectados
int Input::getNumControllers()
{
return mNumGamepads;
}

87
source/input.h Normal file
View File

@@ -0,0 +1,87 @@
#pragma once
#include "ifdefs.h"
#include <string>
#include <vector>
#ifndef INPUT_H
#define INPUT_H
#define INPUT_NULL 0
#define INPUT_UP 1
#define INPUT_DOWN 2
#define INPUT_LEFT 3
#define INPUT_RIGHT 4
#define INPUT_ACCEPT 5
#define INPUT_CANCEL 6
#define INPUT_BUTTON_1 7
#define INPUT_BUTTON_2 8
#define INPUT_BUTTON_3 9
#define INPUT_BUTTON_4 10
#define INPUT_BUTTON_5 11
#define INPUT_BUTTON_6 12
#define INPUT_BUTTON_7 13
#define INPUT_BUTTON_8 14
#define INPUT_BUTTON_PAUSE 15
#define INPUT_BUTTON_ESCAPE 16
#define REPEAT_TRUE true
#define REPEAT_FALSE false
#define INPUT_USE_KEYBOARD 0
#define INPUT_USE_GAMECONTROLLER 1
#define INPUT_USE_ANY 2
// Clase Input
class Input
{
private:
struct keyBindings_t
{
Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo
};
keyBindings_t mKeyBindings[17]; // Vector con las teclas asociadas a los inputs predefinidos
struct GameControllerBindings_t
{
SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo
};
GameControllerBindings_t mGameControllerBindings[17]; // Vector con las teclas asociadas a los inputs predefinidos
//SDL_GameController *mGameController; // Manejador para el mando
std::vector<SDL_GameController*> mConnectedControllers;
std::vector<std::string> mControllerNames;
int mNumGamepads;
std::string mDBpath; // Ruta al archivo gamecontrollerdb.txt
// Comprueba si hay un mando conectado
bool discoverGameController();
public:
// Constructor
Input(std::string file);
// Destructor
~Input();
// Asigna uno de los posibles inputs a una tecla del teclado
void bindKey(Uint8 input, SDL_Scancode code);
// Asigna uno de los posibles inputs a un botón del mando
void bindGameControllerButton(Uint8 input, SDL_GameControllerButton button);
// Comprueba si un input esta activo
bool checkInput(Uint8 input, bool repeat, int device=INPUT_USE_ANY, int index=0);
// Comprueba si hay algun mando conectado
bool gameControllerFound();
// Obten el numero de mandos conectados
int getNumControllers();
// Obten el nombre de un mando de juego
std::string getControllerName(int index);
};
#endif

213
source/jail_audio.cpp Normal file
View File

@@ -0,0 +1,213 @@
#ifndef __MIPSEL__
#include "jail_audio.h"
#include "stb_vorbis.c"
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
struct JA_Sound_t {
Uint32 length {0};
Uint8* buffer {NULL};
};
struct JA_Channel_t {
JA_Sound sound;
int pos {0};
int times {0};
JA_Channel_state state { JA_CHANNEL_FREE };
};
struct JA_Music_t {
int samples {0};
int pos {0};
int times {0};
short* output {NULL};
JA_Music_state state {JA_MUSIC_INVALID};
};
JA_Music current_music{NULL};
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000};
SDL_AudioFormat JA_format {AUDIO_S16};
Uint8 JA_channels {2};
void audioCallback(void * userdata, uint8_t * stream, int len) {
SDL_memset(stream, 0, len);
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) {
const int size = SDL_min(len, current_music->samples*2-current_music->pos);
SDL_memcpy(stream, current_music->output+current_music->pos, size);
current_music->pos += size/2;
if (size < len) {
if (current_music->times != 0) {
SDL_memcpy(stream+size, current_music->output, len-size);
current_music->pos = (len-size)/2;
if (current_music->times > 0) current_music->times--;
} else {
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
}
}
// Mixar els channels mi amol
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) {
const int size = SDL_min(len, channels[i].sound->length - channels[i].pos);
SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, 64);
channels[i].pos += size;
if (size < len) {
if (channels[i].times != 0) {
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, 64);
channels[i].pos = len-size;
if (channels[i].times > 0) channels[i].times--;
} else {
JA_StopChannel(i);
}
}
}
}
}
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
JA_freq = freq;
JA_format = format;
JA_channels = channels;
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL};
SDL_AudioDeviceID sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
SDL_PauseAudioDevice(sdlAudioDevice, 0);
}
JA_Music JA_LoadMusic(const char* filename) {
int chan, samplerate;
JA_Music music = new JA_Music_t();
music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
cvt.len = music->samples * chan * 2;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, music->output, cvt.len);
SDL_ConvertAudio(&cvt);
free(music->output);
music->output = (short*)cvt.buf;
music->pos = 0;
music->state = JA_MUSIC_STOPPED;
return music;
}
void JA_PlayMusic(JA_Music music, const int loop) {
if (current_music != NULL) {
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
current_music = music;
current_music->pos = 0;
current_music->state = JA_MUSIC_PLAYING;
current_music->times = loop;
}
void JA_PauseMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PAUSED;
}
void JA_ResumeMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->state = JA_MUSIC_PLAYING;
}
void JA_StopMusic() {
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED;
}
JA_Music_state JA_GetMusicState() {
if (current_music == NULL) return JA_MUSIC_INVALID;
return current_music->state;
}
void JA_DeleteMusic(JA_Music music) {
if (current_music == music) current_music = NULL;
SDL_free(music->output);
delete music;
}
JA_Sound JA_LoadSound(const char* filename) {
JA_Sound sound = new JA_Sound_t();
SDL_AudioSpec wavSpec;
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer);
sound->buffer = cvt.buf;
sound->length = cvt.len_cvt;
return sound;
}
int JA_PlaySound(JA_Sound sound, const int loop) {
int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
channels[channel].sound = sound;
channels[channel].times = loop;
channels[channel].pos = 0;
channels[channel].state = JA_CHANNEL_PLAYING;
return channel;
}
void JA_DeleteSound(JA_Sound sound) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].sound == sound) JA_StopChannel(i);
}
SDL_free(sound->buffer);
delete sound;
}
void JA_PauseChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED;
}
}
void JA_ResumeChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING;
}
}
void JA_StopChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0;
channels[i].sound = NULL;
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0;
channels[channel].sound = NULL;
}
}
JA_Channel_state JA_GetChannelState(const int channel) {
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state;
}
#endif

26
source/jail_audio.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include "ifdefs.h"
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED };
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED };
typedef struct JA_Sound_t *JA_Sound;
typedef struct JA_Music_t *JA_Music;
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);
JA_Music JA_LoadMusic(const char* filename);
void JA_PlayMusic(JA_Music music, const int loop = -1);
void JA_PauseMusic();
void JA_ResumeMusic();
void JA_StopMusic();
JA_Music_state JA_GetMusicState();
void JA_DeleteMusic(JA_Music music);
JA_Sound JA_LoadSound(const char* filename);
int JA_PlaySound(JA_Sound sound, const int loop = 0);
void JA_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel);
void JA_StopChannel(const int channel);
JA_Channel_state JA_GetChannelState(const int channel);
void JA_DeleteSound(JA_Sound sound);

73
source/lang.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include "lang.h"
#include <iostream>
#include <fstream>
// Constructor
Lang::Lang(std::string *fileList)
{
mFileList = fileList;
}
// Destructor
Lang::~Lang()
{
}
// Inicializa los textos del juego en el idioma seleccionado
bool Lang::setLang(Uint8 lang)
{
std::string file;
switch (lang)
{
case es_ES:
file = mFileList[49];
break;
case en_UK:
file = mFileList[50];
break;
case ba_BA:
file = mFileList[51];
break;
default:
file = mFileList[50];
break;
}
for (int i = 0; i < MAX_TEXT_STRINGS; i++)
mTextStrings[i] = "";
bool success = false;
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good())
{
success = true;
std::string buffer;
// lee el resto de datos del fichero
int index = 0;
int line_read = 0;
while (std::getline(rfile, buffer))
{
// Almacena solo las lineas impares
if (line_read % 2 == 1)
mTextStrings[index++] = buffer;
// Limpia el buffer
buffer.clear();
line_read++;
};
}
return success;
}
// Obtiene la cadena de texto del indice
std::string Lang::getText(int index)
{
return mTextStrings[index];
}

37
source/lang.h Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include "ifdefs.h"
#include <string>
#ifndef LANG_H
#define LANG_H
// Lang codes
#define es_ES 0
#define ba_BA 1
#define en_UK 2
#define MAX_LANGUAGES 3
// Textos
#define MAX_TEXT_STRINGS 100
// Clase Lang
class Lang
{
private:
std::string *mFileList; // Lista de ficheros con los recursos
std::string mTextStrings[MAX_TEXT_STRINGS];
public:
// Constructor
Lang(std::string *fileList);
// Destructor
~Lang();
// Inicializa los textos del juego en el idioma seleccionado
bool setLang(Uint8 lang);
// Obtiene la cadena de texto del indice
std::string getText(int index);
};
#endif

166
source/ltexture.cpp Normal file
View File

@@ -0,0 +1,166 @@
#include "const.h"
#include "ltexture.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
LTexture::LTexture()
{
// Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
LTexture::~LTexture()
{
// Deallocate
unload();
}
bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
{
int req_format = STBI_rgb_alpha;
int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format);
if (data == NULL)
{
SDL_Log("Loading image failed: %s", stbi_failure_reason());
exit(1);
}
int depth, pitch;
Uint32 pixel_format;
if (req_format == STBI_rgb)
{
depth = 24;
pitch = 3 * width; // 3 bytes per pixel * pixels per row
pixel_format = SDL_PIXELFORMAT_RGB24;
}
else
{ // STBI_rgb_alpha (RGBA)
depth = 32;
pitch = 4 * width;
pixel_format = SDL_PIXELFORMAT_RGBA32;
}
// Get rid of preexisting texture
unload();
// The final texture
SDL_Texture *newTexture = NULL;
// Load image at specified path
//SDL_Surface *loadedSurface = IMG_Load(path.c_str());
SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format);
if (loadedSurface == NULL)
{
printf("Unable to load image %s!\n", path.c_str());
}
else
{
// Color key image
//SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, COLOR_KEY_R, COLOR_KEY_G, COLOR_KEY_B));
// Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (newTexture == NULL)
{
printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
else
{
// Get image dimensions
mWidth = loadedSurface->w;
mHeight = loadedSurface->h;
}
// Get rid of old loaded surface
SDL_FreeSurface(loadedSurface);
}
// Return success
mTexture = newTexture;
return mTexture != NULL;
}
bool LTexture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access)
{
// Create uninitialized texture
mTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height);
if (mTexture == NULL)
{
printf("Unable to create blank texture! SDL Error: %s\n", SDL_GetError());
}
else
{
mWidth = width;
mHeight = height;
}
return mTexture != NULL;
}
void LTexture::unload()
{
// Free texture if it exists
if (mTexture != NULL)
{
SDL_DestroyTexture(mTexture);
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
void LTexture::setColor(Uint8 red, Uint8 green, Uint8 blue)
{
// Modulate texture rgb
SDL_SetTextureColorMod(mTexture, red, green, blue);
}
void LTexture::setBlendMode(SDL_BlendMode blending)
{
// Set blending function
SDL_SetTextureBlendMode(mTexture, blending);
}
void LTexture::setAlpha(Uint8 alpha)
{
// Modulate texture alpha
SDL_SetTextureAlphaMod(mTexture, alpha);
}
void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_RendererFlip flip)
{
// Set rendering space and render to screen
SDL_Rect renderQuad = {x, y, mWidth, mHeight};
// Set clip rendering dimensions
if (clip != NULL)
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
renderQuad.w = renderQuad.w * zoomW;
renderQuad.h = renderQuad.h * zoomH;
// Render to screen
SDL_RenderCopyEx(renderer, mTexture, clip, &renderQuad, angle, center, flip);
}
void LTexture::setAsRenderTarget(SDL_Renderer *renderer)
{
// Make self render target
SDL_SetRenderTarget(renderer, mTexture);
}
int LTexture::getWidth()
{
return mWidth;
}
int LTexture::getHeight()
{
return mHeight;
}

66
source/ltexture.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include "ifdefs.h"
#include <stdio.h>
#include <string>
#ifndef LTEXTURE_H
#define LTEXTURE_H
// Texture wrapper class
class LTexture
{
public:
// Initializes variables
LTexture();
// Deallocates memory
~LTexture();
// Loads image at specified path
bool loadFromFile(std::string path, SDL_Renderer *renderer);
// Creates blank texture
bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
// Deallocates texture
void unload();
// Set color modulation
void setColor(Uint8 red, Uint8 green, Uint8 blue);
// Set blending
void setBlendMode(SDL_BlendMode blending);
// Set alpha modulation
void setAlpha(Uint8 alpha);
// Renders texture at given point
void render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip = NULL, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_Point *center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);
// Set self as render target
void setAsRenderTarget(SDL_Renderer *renderer);
// Gets image dimensions
int getWidth();
int getHeight();
// Pixel manipulators
bool lockTexture();
bool unlockTexture();
void *getPixels();
void copyPixels(void *pixels);
int getPitch();
Uint32 getPixel32(unsigned int x, unsigned int y);
private:
// The actual hardware texture
SDL_Texture *mTexture;
void *mPixels;
int mPitch;
// Image dimensions
int mWidth;
int mHeight;
};
#endif

57
source/main.cpp Normal file
View File

@@ -0,0 +1,57 @@
/*
Código fuente creado por JailDesigner (2020)
Empezado en Castalla el 15/07/2020.
Descripción del enfoque utilizado para crear el juego.
El programa contine una serie de clases/objetos básicos: la clase sprite
permite dibujar partes de un fichero png en pantalla. La clase AnimatedSprite
contiene funcionalidad adicional para crear animaciones. La clase text permite
dibujar letras de un png en pantalla a partir de una cadena de texto. La clase
menu permite crear una estructura con diferentes elementos, escribirlos en
pantalla y seleccionar uno de ellos.
A continuación tenemos las clases enfocadas a la lógica del juego, la clase player
contiene la información del jugador, la clase balloon la de los enemigos y la
clase bullet para las balas que dispara el jugador. La clase background es
muy simple y sirve para pintar el fondo de la pantalla. Por ultimo, la clase
mDirector es la que realiza toda la lógica y se encarga de hacer interactuar
al resto de objetos entre si.
El objeto mDirector tiene tres estados: titulo, juego y pausa. Segun su estado
el bucle que recorre es distinto. En el bucle juego, el objeto mDirector
tiene un objeto jugador, un vector con los objetos globo y un vector con los
objetos bala. Se encarga de comprobar las entradas de teclado o gamepad para
cerrar la aplicacion, saltar al estado de pausa y para mover al jugador. Recorre
el vector de globos y de balas y si tienen algun tipo asignado las gestiona.
Comprueba las colisiones entre los globos y el jugador y entre las balas y los
globos. Tiene ademas un nivel de amenaza que calcula en funcion del numero de globos
en pantalla y que se va incrementando conforme aumenta la puntuación del jugador.
Los objetos globo tienen varios contadores para alternar de un estado a otro.
En los vectores que contienen objetos, se considera activos los objetos que tienen
un tipo asociado diferente a NO_KIND
*/
#include "director.h"
#include <stdio.h>
int main(int argc, char *args[])
{
printf("Starting the game...\n\n");
// Crea el objeto Director
Director *mDirector = new Director(args[0]);
// Bucle principal
mDirector->run();
// Destruye el objeto Director
delete mDirector;
mDirector = nullptr;
printf("\nShutting down the game...\n");
return 0;
}

599
source/menu.cpp Normal file
View File

@@ -0,0 +1,599 @@
#include "const.h"
#include "menu.h"
// Constructor
Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList)
{
mRenderer = renderer;
mText = text;
mInput = input;
mFileList = fileList;
}
Menu::~Menu()
{
mRenderer = nullptr;
mText = nullptr;
mInput = nullptr;
mFileList = nullptr;
}
// Inicializador
void Menu::init(std::string name, int x, int y, int backgroundType)
{
loadMedia();
// Inicia variables
mName = name;
mSelector.index = 0;
mTotalItems = 0;
mItemSelected = MENU_NO_OPTION;
mPosX = x;
mPosY = y;
mRectBG.rect.x = 0;
mRectBG.rect.y = 0;
mRectBG.rect.w = 0;
mRectBG.rect.h = 0;
mRectBG.r = 0;
mRectBG.g = 0;
mRectBG.b = 0;
mBackgroundType = backgroundType;
mIsCenteredOnX = false;
mIsCenteredOnY = false;
mAreElementsCenteredOnX = false;
mCenterX = 0;
mCenterY = 0;
mWidestItem = 0;
mColorGreyed = {128, 128, 128};
// Selector
mSelector.originY = 0;
mSelector.targetY = 0;
mSelector.despY = 0;
mSelector.originH = 0;
mSelector.targetH = 0;
mSelector.incH = 0;
mSelector.y = 0.0f;
mSelector.h = 0.0f;
mSelector.numJumps = 8;
mSelector.moving = false;
mSelector.resizing = false;
mSelector.rect = {0, 0, 0, 0};
mSelector.r = 0;
mSelector.g = 0;
mSelector.b = 0;
mSelector.a = 255;
// Elementos del menu
for (int i = 0; i < MENU_MAX_ITEMS; i++)
{
mItem[i].label = "";
mItem[i].rect = {0, 0, 0, 0};
mItem[i].hPaddingDown = 0;
mItem[i].selectable = false;
mItem[i].greyed = false;
mItem[i].linkedDown = false;
mItem[i].linkedUp = false;
}
}
// Carga los recursos necesarios para la sección 'Title'
bool Menu::loadMedia()
{
// Indicador de éxito en la carga
bool success = true;
// Sonidos
mSoundMove = JA_LoadSound(mFileList[17].c_str());
mSoundAccept = JA_LoadSound(mFileList[18].c_str());
mSoundCancel = JA_LoadSound(mFileList[16].c_str());
return success;
}
// Obtiene el nombre del menu
std::string Menu::getName()
{
return mName;
}
// Obtiene el valor de la variable
Uint8 Menu::getItemSelected()
{
// Al llamar a esta funcion, se obtiene el valor y se borra
const int temp = mItemSelected;
mItemSelected = MENU_NO_OPTION;
return temp;
}
// Actualiza la posicion y el estado del selector
void Menu::updateSelector()
{
if (mSelector.moving)
{
// Calcula el desplazamiento en Y
mSelector.y += mSelector.despY;
if (mSelector.despY > 0) // Va hacia abajo
{
if (mSelector.y > mSelector.targetY) // Ha llegado al destino
{
mSelector.originY = mSelector.y = mSelector.targetY;
mSelector.moving = false;
}
}
if (mSelector.despY < 0) // Va hacia arriba
{
if (mSelector.y < mSelector.targetY) // Ha llegado al destino
{
mSelector.originY = mSelector.y = mSelector.targetY;
mSelector.moving = false;
}
}
mSelector.rect.y = int(mSelector.y);
}
else
{
mSelector.rect.y = int(mSelector.y);
}
if (mSelector.resizing)
{
// Calcula el incremento en H
mSelector.h += mSelector.incH;
if (mSelector.incH > 0) // Crece
{
if (mSelector.h > mSelector.targetH) // Ha llegado al destino
{
//mSelector.originH = mSelector.targetH = mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.originH = mSelector.h = mSelector.targetH;
mSelector.resizing = false;
}
}
if (mSelector.incH < 0) // Decrece
{
if (mSelector.h < mSelector.targetH) // Ha llegado al destino
{
//mSelector.originH = mSelector.targetH = mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.originH = mSelector.h = mSelector.targetH;
mSelector.resizing = false;
}
}
mSelector.rect.h = int(mSelector.h);
}
else
{
mSelector.rect.h = getSelectorHeight(mSelector.index);
}
}
// Coloca el selector en una posición específica
void Menu::setSelectorPos(Uint8 index)
{
if (index < mTotalItems)
{
mSelector.index = index;
mSelector.rect.y = mSelector.y = mSelector.originY = mSelector.targetY = mItem[mSelector.index].rect.y;
mSelector.rect.w = mRectBG.rect.w;
mSelector.rect.x = mRectBG.rect.x;
mSelector.originH = mSelector.targetH = mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.moving = false;
mSelector.resizing = false;
}
}
// Obtiene la anchura del elemento más ancho del menu
Uint16 Menu::getWidestItem()
{
Uint16 result = 0;
// Obtenemos la anchura del item mas ancho
for (int i = 0; i < mTotalItems; i++)
if (mItem[i].rect.w > result)
result = mItem[i].rect.w;
return result;
}
// Deja el menu apuntando al primer elemento
void Menu::reset()
{
mItemSelected = MENU_NO_OPTION;
mSelector.index = 0;
mSelector.originY = mSelector.targetY = mSelector.y = mItem[0].rect.y;
mSelector.originH = mSelector.targetH = mItem[0].rect.h;
mSelector.moving = false;
mSelector.resizing = false;
}
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void Menu::reorganize()
{
setRectSize();
if (mIsCenteredOnX)
centerMenuOnX(mCenterX);
if (mIsCenteredOnY)
centerMenuOnY(mCenterY);
if (mAreElementsCenteredOnX)
centerMenuElementsOnX();
}
// Deja el menu apuntando al siguiente elemento
bool Menu::increaseSelectorIndex()
{
bool success = false;
// Obten las coordenadas del elemento actual
mSelector.y = mSelector.originY = mItem[mSelector.index].rect.y;
mSelector.h = mSelector.originH = getSelectorHeight(mSelector.index);
// Calcula cual es el siguiente elemento
//if (mSelector.index < (mTotalItems - 1))
//{
// mSelector.index++;
// while ((!mItem[mSelector.index].selectable) && (mSelector.index < (mTotalItems - 1)))
// mSelector.index++;
// success = true;
//}
// Calcula cual es el siguiente elemento (versión con loop)
//if (mSelector.index < (mTotalItems - 1))
{
++mSelector.index %= mTotalItems;
while (!mItem[mSelector.index].selectable)
//mSelector.index++;
++mSelector.index %= mTotalItems;
success = true;
}
if (success)
{ // Establece las coordenadas y altura de destino
mSelector.targetY = mItem[mSelector.index].rect.y;
mSelector.despY = (mSelector.targetY - mSelector.originY) / mSelector.numJumps;
mSelector.targetH = getSelectorHeight(mSelector.index);
mSelector.incH = (mSelector.targetH - mSelector.originH) / mSelector.numJumps;
mSelector.moving = true;
if (mSelector.incH != 0)
mSelector.resizing = true;
}
return success;
}
// Deja el menu apuntando al elemento anterior
bool Menu::decreaseSelectorIndex()
{
bool success = false;
// Obten las coordenadas del elemento actual
mSelector.y = mSelector.originY = mItem[mSelector.index].rect.y;
mSelector.h = mSelector.originH = getSelectorHeight(mSelector.index);
// Calcula cual es el siguiente elemento
//if (mSelector.index > 0)
//{
// mSelector.index--;
// while ((!mItem[mSelector.index].selectable) && (mSelector.index > 0))
// mSelector.index--;
// success = true;
//}
// Calcula cual es el siguiente elemento (versión con loop)
//if (mSelector.index > 0)
{
if (mSelector.index == 0)
mSelector.index = mTotalItems;
else
mSelector.index--;
while (!mItem[mSelector.index].selectable)
{
if (mSelector.index == 0)
mSelector.index = mTotalItems;
else
mSelector.index--;
}
success = true;
}
if (success)
{ // Establece las coordenadas y altura de destino
mSelector.targetY = mItem[mSelector.index].rect.y;
mSelector.despY = (mSelector.targetY - mSelector.originY) / mSelector.numJumps;
mSelector.targetH = getSelectorHeight(mSelector.index);
mSelector.incH = (mSelector.targetH - mSelector.originH) / mSelector.numJumps;
mSelector.moving = true;
if (mSelector.incH != 0)
mSelector.resizing = true;
}
return success;
}
// Actualiza la logica del menu
void Menu::update()
{
updateSelector();
}
// Pinta el menu en pantalla
void Menu::render()
{
// Rendereritza el fondo del menu
if (mBackgroundType == MENU_BACKGROUND_SOLID)
{
SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, mRectBG.a);
SDL_RenderFillRect(mRenderer, &mRectBG.rect);
}
// Renderiza el rectangulo del selector
SDL_Rect temp = mSelector.rect;
temp.y--;
temp.h++;
SDL_SetRenderDrawColor(mRenderer, mSelector.r, mSelector.g, mSelector.b, mSelector.a);
SDL_RenderFillRect(mRenderer, &temp);
// Renderiza el borde del fondo
if (mBackgroundType == MENU_BACKGROUND_SOLID)
{
SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, 255);
SDL_RenderDrawRect(mRenderer, &mRectBG.rect);
}
// Renderitza el texto
for (int i = 0; i < mTotalItems; i++)
{
if (i == mSelector.index)
{
const color_t color = {mSelector.itemR, mSelector.itemG, mSelector.itemB};
mText->writeColored(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label, color);
}
else if (mItem[i].selectable)
{
mText->write(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label);
}
else if (mItem[i].greyed)
{
mText->writeColored(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label, mColorGreyed);
}
else // No seleccionable
{
if ((mItem[i].linkedUp) && (i == mSelector.index + 1))
{
const color_t color = {mSelector.itemR, mSelector.itemG, mSelector.itemB};
mText->writeColored(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label, color);
}
else // No enlazado con el de arriba
{
mText->write(mItem[i].rect.x, mItem[i].rect.y, mItem[i].label);
}
}
//borrar
//mText->write(0, 0, std::to_string(mSelector.h) + " " + std::to_string(mSelector.incH) + " " + std::to_string(mSelector.resizing));
//mText->write(0, 8, std::to_string(mSelector.y) + " " + std::to_string(mSelector.despY) + " " + std::to_string(mSelector.moving));
}
}
// Establece el rectangulo de fondo del menu y el selector
void Menu::setRectSize()
{
mRectBG.rect.w = findWidth() + mText->getCharacterWidth();
mRectBG.rect.h = findHeight() + mText->getCharacterWidth();
// La posición X es la del menú menos medio caracter
mRectBG.rect.x = mPosX - (mText->getCharacterWidth() / 2);
// La posición Y es la del menu menos la altura de medio caracter
mRectBG.rect.y = mPosY - (mText->getCharacterWidth() / 2);
// Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo
setSelectorPos(mSelector.index);
}
// Establece el valor de la variable
void Menu::setTotalItems(int num)
{
mTotalItems = num;
if (mTotalItems > MENU_MAX_ITEMS)
mTotalItems = MENU_MAX_ITEMS;
}
// Establece el color del rectangulo de fondo
void Menu::setBackgroundColor(int r, int g, int b, int alpha)
{
mRectBG.r = r;
mRectBG.g = g;
mRectBG.b = b;
mRectBG.a = alpha;
}
// Establece el color del rectangulo del selector
void Menu::setSelectorColor(int r, int g, int b, int alpha)
{
mSelector.r = r;
mSelector.g = g;
mSelector.b = b;
mSelector.a = alpha;
}
// Establece el color del texto del selector
void Menu::setSelectorTextColor(int r, int g, int b)
{
mSelector.itemR = r;
mSelector.itemG = g;
mSelector.itemB = b;
}
// Centra el menu respecto un punto en el eje X
void Menu::centerMenuOnX(int value)
{
mIsCenteredOnX = true;
mCenterX = value;
// Actualiza el rectangulo de fondo para recalcular las dimensiones
//setRectSize();
// Establece la nueva posición centrada en funcion del elemento más ancho
mPosX = (value) - (findWidth() / 2);
// Reposiciona los elementos del menu
for (int i = 0; i < MENU_MAX_ITEMS; i++)
mItem[i].rect.x = mPosX;
// Recalcula el rectangulo de fondo
setRectSize();
}
// Centra el menu respecto un punto en el eje Y
void Menu::centerMenuOnY(int value)
{
mIsCenteredOnY = true;
mCenterY = value;
// Actualiza el rectangulo de fondo para recalcular las dimensiones
//setRectSize();
// Establece la nueva posición centrada en funcion del elemento más ancho
mPosY = (value) - (findHeight() / 2);
// Reposiciona los elementos del menu
replaceElementsOnY();
// Recalcula el rectangulo de fondo
setRectSize();
}
// Centra los elementos del menu en el eje X
void Menu::centerMenuElementsOnX()
{
mAreElementsCenteredOnX = true;
for (int i = 0; i < mTotalItems; i++)
mItem[i].rect.x = (mCenterX - (mItem[i].rect.w / 2));
}
// Añade un item al menu
void Menu::addItem(std::string text, Uint8 hPaddingDown, bool selectable, bool greyed, bool linkedDown)
{
// Si es el primer item coge la posición en el eje Y del propio menu
if (mTotalItems == 0)
mItem[mTotalItems].rect.y = mPosY;
else
// En caso contrario, coge la posición en el eje Y a partir del elemento anterior
mItem[mTotalItems].rect.y = mItem[mTotalItems - 1].rect.y + mItem[mTotalItems - 1].rect.h + mItem[mTotalItems - 1].hPaddingDown;
setItemCaption(mTotalItems, text);
mItem[mTotalItems].rect.x = mPosX;
mItem[mTotalItems].hPaddingDown = hPaddingDown;
mItem[mTotalItems].selectable = selectable;
mItem[mTotalItems].greyed = greyed;
mItem[mTotalItems].linkedDown = linkedDown;
if (mTotalItems > 0)
if (mItem[mTotalItems - 1].linkedDown)
mItem[mTotalItems].linkedUp = true;
setTotalItems(mTotalItems + 1);
mCenterX = mPosX + (findWidth() / 2);
//setSelectorPos(0);
reorganize();
}
// Cambia el texto de un item
void Menu::setItemCaption(Uint8 index, std::string text)
{
mItem[index].label = text;
mItem[index].rect.w = mText->lenght(mItem[index].label);
mItem[index].rect.h = mText->getCharacterWidth();
reorganize();
}
// Establece el indice del itemm que se usará por defecto al cancelar el menu
void Menu::setDefaultActionWhenCancel(Uint8 item)
{
mDefaultActionWhenCancel = item;
}
// Gestiona la entrada de teclado y mando durante el menu
void Menu::checkInput()
{
if (mInput->checkInput(INPUT_UP, REPEAT_FALSE))
{
if (decreaseSelectorIndex())
JA_PlaySound(mSoundMove);
}
if (mInput->checkInput(INPUT_DOWN, REPEAT_FALSE))
{
if (increaseSelectorIndex())
JA_PlaySound(mSoundMove);
}
if (mInput->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
{
mItemSelected = mSelector.index;
JA_PlaySound(mSoundAccept);
}
if (mInput->checkInput(INPUT_CANCEL, REPEAT_FALSE))
{
mItemSelected = mDefaultActionWhenCancel;
JA_PlaySound(mSoundCancel);
}
}
// Calcula el ancho del menu
Uint16 Menu::findWidth()
{
return getWidestItem();
}
// Calcula el alto del menu
Uint16 Menu::findHeight()
{
Uint16 height = 0;
// Obtenemos la altura de la suma de alturas de los items
for (int i = 0; i < mTotalItems; i++)
height += mItem[i].rect.h + mItem[i].hPaddingDown;
return height - mItem[mTotalItems - 1].hPaddingDown;
}
// Recoloca los elementos del menu en el eje Y
void Menu::replaceElementsOnY()
{
mItem[0].rect.y = mPosY;
for (int i = 1; i < mTotalItems; i++)
mItem[i].rect.y = mItem[i - 1].rect.y + mItem[i - 1].rect.h + mItem[i - 1].hPaddingDown;
}
// Establece el estado seleccionable de un item
void Menu::setSelectable(Uint8 index, bool value)
{
mItem[index].selectable = value;
}
// Establece el estado agrisado de un item
void Menu::setGreyed(Uint8 index, bool value)
{
mItem[index].greyed = value;
}
// Establece el estado de enlace de un item
void Menu::setLinkedDown(Uint8 index, bool value)
{
mItem[index].linkedDown = value;
}
// Calcula la altura del selector
int Menu::getSelectorHeight(int value)
{
if (mItem[value].linkedDown)
return mItem[value].rect.h + mItem[value].hPaddingDown + mItem[value + 1].rect.h;
else
return mItem[value].rect.h;
}

195
source/menu.h Normal file
View File

@@ -0,0 +1,195 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#include "text.h"
#include "input.h"
#include "jail_audio.h"
#ifndef MENU_H
#define MENU_H
#define MENU_MAX_ITEMS 50
// Clase menu
class Menu
{
private:
std::string mName; // Nombre del menu
int mPosX; // Posición en el eje X de la primera letra del primer elemento
int mPosY; // Posición en el eje Y de la primera letra del primer elemento
Uint16 mHeight; // Altura del menu
Uint16 mWidth; // Anchura del menu
Uint8 mTotalItems; // Numero total de items del menu
int mItemSelected; // Índice del item del menu que ha sido seleccionado
Uint8 mDefaultActionWhenCancel; // Indice del item del menu que se selecciona cuando se cancela el menu
Uint8 mBackgroundType; // Tipo de fondo para el menu
bool mIsCenteredOnX; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje X
bool mIsCenteredOnY; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje Y
int mCenterX; // Centro del menu en el eje X
int mCenterY; // Centro del menu en el eje Y
bool mAreElementsCenteredOnX; // Variable para saber si los elementos van centrados en el eje X
Uint16 mWidestItem; // Anchura del elemento más ancho
JA_Sound mSoundAccept; // Sonido al aceptar o elegir una opción del menu
JA_Sound mSoundCancel; // Sonido al cancelar el menu
JA_Sound mSoundMove; // Sonido al mover el selector
SDL_Renderer *mRenderer; // Puntero al renderizador de la ventana
std::string *mFileList; // Lista de ficheros
Text *mText; // Texto para poder escribir los items del menu
Input *mInput; // Gestor de eventos de entrada de teclado o gamepad
color_t mColorGreyed; // Color para los elementos agrisados
struct rectangle
{
SDL_Rect rect; // Rectangulo
Uint8 r; // Rojo
Uint8 g; // Verde
Uint8 b; // Azul
Uint8 a; // Transparencia
};
rectangle mRectBG; // Rectangulo de fondo del menu
struct item
{
std::string label; // Texto
SDL_Rect rect; // Rectangulo que delimita el elemento
Uint8 hPaddingDown; // Espaciado bajo el elemento
bool selectable; // Indica si se puede seleccionar
bool greyed; // Indica si ha de aparecer con otro color mas oscuro
bool linkedDown; // Indica si el elemento actual y el siguiente se tratan como uno solo. Afecta al selector
bool linkedUp; // Indica si el elemento actual y el anterior se tratan como uno solo. Afecta al selector
};
item mItem[MENU_MAX_ITEMS]; // Estructura para cada elemento del menu
struct selector
{
float originY; // Coordenada de origen
float targetY; // Coordenada de destino
float despY; // Cantidad de pixeles que se desplaza el selector en cada salto: (target - origin) / numJumps
bool moving; // Indica si el selector está avanzando hacia el destino
float originH; // Altura de origen
float targetH; // Altura de destino
float incH; // Cantidad de pixels que debe incrementar o decrementar el selector en cada salto
bool resizing; // Indica si el selector está cambiando de tamaño
float y; // Coordenada actual, usado para el desplazamiento
float h; // Altura actual, usado para el cambio de tamaño
Uint8 numJumps; // Numero de pasos preestablecido para llegar al destino
Uint8 index; // Elemento del menu que tiene el foco
SDL_Rect rect; // Rectangulo del selector
Uint8 r; // Cantidad de color rojo para el rectangulo del selector
Uint8 g; // Cantidad de color verde para el rectangulo del selector
Uint8 b; // Cantidad de color azul para el rectangulo del selector
Uint8 a; // Cantidad de transparencia para el rectangulo del selector
Uint8 itemR; // Cantidad de color rojo para el texto del elemento seleccionado
Uint8 itemG; // Cantidad de color verde para el texto del elemento seleccionado
Uint8 itemB; // Cantidad de color azul para el texto del elemento seleccionado
};
selector mSelector; // Variables para pintar el selector del menu
// Carga los recursos necesarios para la sección 'Title'
bool loadMedia();
// Establece el valor de la variable
void setTotalItems(int num);
// Establece el rectangulo de fondo del menu
void setRectSize();
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void reorganize();
// Deja el menu apuntando al siguiente elemento
bool increaseSelectorIndex();
// Deja el menu apuntando al elemento anterior
bool decreaseSelectorIndex();
// Actualiza la posicion y el estado del selector
void updateSelector();
// Obtiene la anchura del elemento más ancho del menu
Uint16 getWidestItem();
// Gestiona la entrada de teclado y mando durante el menu
void checkMenuInput(Menu *menu);
// Calcula el ancho del menu
Uint16 findWidth();
// Calcula el alto del menu
Uint16 findHeight();
// Recoloca los elementos del menu en el eje Y
void replaceElementsOnY();
// Calcula la altura del selector
int getSelectorHeight(int value);
public:
// Constructor
Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList);
// Destructor
~Menu();
// Inicializador
void init(std::string name, int x, int y, int backgroundType);
// Obtiene el nombre del menu
std::string getName();
// Obtiene el valor de la variable
Uint8 getItemSelected();
// Deja el menu apuntando al primer elemento
void reset();
// Gestiona la entrada de teclado y mando durante el menu
void checkInput();
// Actualiza la logica del menu
void update();
// Pinta el menu en pantalla
void render();
// Establece el color del rectangulo de fondo
void setBackgroundColor(int r, int g, int b, int alpha);
// Establece el color del rectangulo del selector
void setSelectorColor(int r, int g, int b, int alpha);
// Establece el color del texto del selector
void setSelectorTextColor(int r, int g, int b);
// Centra el menu respecto a un punto en el eje X
void centerMenuOnX(int value);
// Centra el menu respecto a un punto en el eje Y
void centerMenuOnY(int value);
// Centra los elementos del menu en el eje X
void centerMenuElementsOnX();
// Añade un item al menu
void addItem(std::string text, Uint8 hPaddingDown = 1, bool selectable = true, bool greyed = false, bool linkedDown = false);
// Cambia el texto de un item
void setItemCaption(Uint8 index, std::string text);
// Establece el indice del item que se usará por defecto al cancelar el menu
void setDefaultActionWhenCancel(Uint8 item);
// Coloca el selector en una posición específica
void setSelectorPos(Uint8 index);
// Establece el estado seleccionable de un item
void setSelectable(Uint8 index, bool value);
// Establece el estado agrisado de un item
void setGreyed(Uint8 index, bool value);
// Establece el estado de enlace de un item
void setLinkedDown(Uint8 index, bool value);
};
#endif

286
source/movingsprite.cpp Normal file
View File

@@ -0,0 +1,286 @@
#include "const.h"
#include "movingsprite.h"
// Constructor
MovingSprite::MovingSprite()
{
clear();
}
// Destructor
MovingSprite::~MovingSprite()
{
clear();
}
// Reinicia todas las variables
void MovingSprite::clear()
{
mPosX = 0.0f; // Posición en el eje X
mPosY = 0.0f; // Posición en el eje Y
mVelX = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
mVelY = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
mAccelX = 0.0f; // Aceleración en el eje X. Variación de la velocidad
mAccelY = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
mZoomW = 1.0f; // Zoom aplicado a la anchura
mZoomH = 1.0f; // Zoom aplicado a la altura
mAngle = 0.0; // Angulo para dibujarlo
mRotate = false; // Indica si ha de rotar
mRotateSpeed = 0; // Velocidad de giro
mRotateAmount = 0.0; // Cantidad de grados a girar en cada iteración
mCounter = 0; // Contador interno
}
// Iniciador
void MovingSprite::init(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, LTexture *texture, SDL_Renderer *renderer)
{
// Establece el alto y el ancho del sprite
setWidth(w);
setHeight(h);
// Establece la posición X,Y del sprite
setPosX(x);
setPosY(y);
// Establece la velocidad X,Y del sprite
setVelX(velx);
setVelY(vely);
// Establece la aceleración X,Y del sprite
setAccelX(accelx);
setAccelY(accely);
// Establece el zoom W,H del sprite
setZoomW(1);
setZoomH(1);
// Establece el angulo con el que se dibujará
setAngle(0.0);
// Establece los valores de rotacion
setRotate(false);
setRotateSpeed(0);
setRotateAmount(0.0);
// Contador interno
mCounter = 0;
// Establece la textura donde están los gráficos para el sprite
setTexture(texture);
// Establece el renderizador
setRenderer(renderer);
// Establece el rectangulo de donde coger la imagen
setSpriteClip(0, 0, w, h);
}
// Mueve el sprite
void MovingSprite::move()
{
if (mEnabled)
{
mPosX += mVelX;
mPosY += mVelY;
mVelX += mAccelX;
mVelY += mAccelY;
}
}
// Muestra el sprite por pantalla
void MovingSprite::render()
{
if (mEnabled)
mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip, mZoomW, mZoomH, mAngle);
}
// Obtiene el valor de la variable
float MovingSprite::getPosX()
{
return mPosX;
}
// Obtiene el valor de la variable
float MovingSprite::getPosY()
{
return mPosY;
}
// Obtiene el valor de la variable
float MovingSprite::getVelX()
{
return mVelX;
}
// Obtiene el valor de la variable
float MovingSprite::getVelY()
{
return mVelY;
}
// Obtiene el valor de la variable
float MovingSprite::getAccelX()
{
return mAccelX;
}
// Obtiene el valor de la variable
float MovingSprite::getAccelY()
{
return mAccelY;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomW()
{
return mZoomW;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomH()
{
return mZoomH;
}
// Obtiene el valor de la variable
double MovingSprite::getAngle()
{
return mAngle;
}
// Establece el valor de la variable
void MovingSprite::setPosX(float x)
{
mPosX = x;
}
// Establece el valor de la variable
void MovingSprite::setPosY(float y)
{
mPosY = y;
}
// Establece el valor de la variable
void MovingSprite::setVelX(float x)
{
mVelX = x;
}
// Establece el valor de la variable
void MovingSprite::setVelY(float y)
{
mVelY = y;
}
// Establece el valor de la variable
void MovingSprite::setAccelX(float x)
{
mAccelX = x;
}
// Establece el valor de la variable
void MovingSprite::setAccelY(float y)
{
mAccelY = y;
}
// Establece el valor de la variable
void MovingSprite::setZoomW(float w)
{
mZoomW = w;
}
// Establece el valor de la variable
void MovingSprite::setZoomH(float h)
{
mZoomH = h;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double a)
{
mAngle = a;
}
// Incrementa el valor de la variable
void MovingSprite::incAngle(double inc)
{
mAngle += inc;
}
// Decrementa el valor de la variable
void MovingSprite::decAngle(double dec)
{
mAngle -= dec;
}
// Obtiene el valor de la variable
bool MovingSprite::getRotate()
{
return mRotate;
}
// Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed()
{
return mRotateSpeed;
}
// Establece la rotacion
void MovingSprite::rotate()
{
if (mEnabled)
if (mRotate)
{
if (mCounter % mRotateSpeed == 0)
{
incAngle(mRotateAmount);
}
}
}
// Establece el valor de la variable
void MovingSprite::setRotate(bool value)
{
mRotate = value;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(Uint16 value)
{
mRotateSpeed = value;
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
mRotateAmount = value;
}
// Establece el valor de la variable
void MovingSprite::disableRotate()
{
mRotate = false;
mAngle = 0;
}
// Actualiza las variables internas del objeto
void MovingSprite::update()
{
move();
rotate();
if (mEnabled)
++mCounter %= 60000;
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
mRotateAmount *= -1;
}

137
source/movingsprite.h Normal file
View File

@@ -0,0 +1,137 @@
#pragma once
#include "ifdefs.h"
#include "sprite.h"
#ifndef MOVINGSPRITE_H
#define MOVINGSPRITE_H
// Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite
{
protected:
float mPosX; // Posición en el eje X
float mPosY; // Posición en el eje Y
float mVelX; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float mVelY; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float mAccelX; // Aceleración en el eje X. Variación de la velocidad
float mAccelY; // Aceleración en el eje Y. Variación de la velocidad
float mZoomW; // Zoom aplicado a la anchura
float mZoomH; // Zoom aplicado a la altura
double mAngle; // Angulo para dibujarlo
bool mRotate; // Indica si ha de rotar
Uint16 mRotateSpeed; // Velocidad de giro
double mRotateAmount; // Cantidad de grados a girar en cada iteración
Uint16 mCounter; // Contador interno
public:
// Constructor
MovingSprite();
// Destructor
~MovingSprite();
// Iniciador
void init(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, LTexture *texture, SDL_Renderer *renderer);
// Mueve el sprite
void move();
// Rota el sprite
void rotate();
// Actualiza las variables internas del objeto
void update();
// Reinicia todas las variables
void clear();
// Muestra el sprite por pantalla
void render();
// Obten el valor de la variable
float getPosX();
// Obten el valor de la variable
float getPosY();
// Obten el valor de la variable
float getVelX();
// Obten el valor de la variable
float getVelY();
// Obten el valor de la variable
float getAccelX();
// Obten el valor de la variable
float getAccelY();
// Obten el valor de la variable
float getZoomW();
// Obten el valor de la variable
float getZoomH();
// Obten el valor de la variable
double getAngle();
// Obtiene el valor de la variable
bool getRotate();
// Obtiene el valor de la variable
Uint16 getRotateSpeed();
// Establece el valor de la variable
void setPosX(float x);
// Establece el valor de la variable
void setPosY(float y);
// Establece el valor de la variable
void setVelX(float x);
// Establece el valor de la variable
void setVelY(float y);
// Establece el valor de la variable
void setAccelX(float x);
// Establece el valor de la variable
void setAccelY(float y);
// Establece el valor de la variable
void setZoomW(float w);
// Establece el valor de la variable
void setZoomH(float h);
// Establece el valor de la variable
void setAngle(double a);
// Incrementa el valor de la variable
void incAngle(double inc);
// Decrementa el valor de la variable
void decAngle(double dec);
// Establece el valor de la variable
void setRotate(bool value);
// Establece el valor de la variable
void setRotateSpeed(Uint16 value);
// Establece el valor de la variable
void setRotateAmount(double value);
// Quita el efecto de rotación y deja el sprite en su angulo inicial.
void disableRotate();
// Cambia el sentido de la rotación
void switchRotate();
};
#endif

233
source/smartsprite.cpp Normal file
View File

@@ -0,0 +1,233 @@
#include "const.h"
#include "smartsprite.h"
// Constructor
SmartSprite::SmartSprite()
{
//init(nullptr, nullptr);
}
// Destructor
SmartSprite::~SmartSprite()
{
//init(nullptr, nullptr);
}
// Inicializador
void SmartSprite::init(LTexture *texture, SDL_Renderer *renderer)
{
setTexture(texture);
setRenderer(renderer);
setPosX(0);
setPosY(0);
setWidth(0);
setHeight(0);
setVelX(0);
setVelY(0);
setAccelX(0);
setAccelY(0);
setSpriteClip(0, 0, 0, 0);
setEnabled(false);
setEnabledTimer(0);
mIsOnDestination = false;
mDestX = 0;
mDestY = 0;
setRotate(false);
setRotateSpeed(0);
setRotateAmount(0.0);
mCounter = 0;
// El Id siempre es >=0, por lo tanto si no se le asigna Id se queda en negativo
mId = -1;
mIntroEvents = nullptr;
}
// Pone a cero los elementos del objeto
void SmartSprite::erase()
{
init(nullptr, nullptr);
}
// Obtiene el valor de la variable
bool SmartSprite::isEnabled()
{
return mEnabled;
}
// Establece el valor de la variable
void SmartSprite::setEnabled(bool state)
{
mEnabled = state;
}
// Obtiene el valor de la variable
Uint16 SmartSprite::getEnabledTimer()
{
return mEnabledCounter;
}
// Establece el valor de la variable
void SmartSprite::setEnabledTimer(Uint16 time)
{
mEnabledCounter = time;
}
// Establece el valor de la variable
void SmartSprite::setDestX(int value)
{
mDestX = value;
}
// Establece el valor de la variable
void SmartSprite::setDestY(int value)
{
mDestY = value;
}
// Obtiene el valor de la variable
int SmartSprite::getDestX()
{
return mDestX;
}
// Obtiene el valor de la variable
int SmartSprite::getDestY()
{
return mDestY;
}
// Actualiza la posición y comprueba si ha llegado a su destino
bool SmartSprite::update()
{
if (mEnabled)
{
MovingSprite::update();
// Comprueba si se desplaza en el eje X hacia la derecha
if ((getAccelX() > 0) || ((getAccelX() == 0) && (getVelX() > 0)))
{
// Comprueba si hemos llegado al destino
if (getPosX() > mDestX)
{
// Lo coloca en posición
setPosX(mDestX);
// Lo detiene
setVelX(0.0f);
setAccelX(0.0f);
}
}
// Comprueba si se desplaza en el eje X hacia la izquierda
else if ((getAccelX() < 0) || ((getAccelX() == 0) && (getVelX() < 0)))
{
// Comprueba si hemos llegado al destino
if (getPosX() < mDestX)
{
// Lo coloca en posición
setPosX(mDestX);
// Lo detiene
setVelX(0.0f);
setAccelX(0.0f);
}
}
// Comprueba si se desplaza en el eje Y hacia abajo
if ((getAccelY() > 0) || ((getAccelY() == 0) && (getVelY() > 0)))
{
// Comprueba si hemos llegado al destino
if (getPosY() > mDestY)
{
// Lo coloca en posición
setPosY(mDestY);
// Lo detiene
setVelY(0.0f);
setAccelY(0.0f);
}
}
// Comprueba si se desplaza en el eje Y hacia arriba
else if ((getAccelY() < 0) || ((getAccelY() == 0) && (getVelY() < 0)))
{
// Comprueba si hemos llegado al destino
if (getPosY() < mDestY)
{
// Lo coloca en posición
setPosY(mDestY);
// Lo detiene
setVelY(0.0f);
setAccelY(0.0f);
}
}
// Comprueba si ha llegado a su destino
if ((getPosX() == mDestX) && (getPosY() == mDestY))
{
mIsOnDestination = true;
}
else
{
mIsOnDestination = false;
}
// Si esta en el destino comprueba su contador
if (mIsOnDestination)
{
// Si el contador es mayor que cero, lo decrementa
if (mEnabledCounter > 0)
{
--mEnabledCounter;
}
// Si ha llegado a cero, deshabilita el objeto o manda el aviso en función de si tiene Id
else if (mEnabledCounter == 0)
{
if (mId < 0)
{
mEnabled = false;
}
else
{
mIntroEvents[mId] = EVENT_COMPLETED;
}
}
}
}
return mIsOnDestination;
}
// Obtiene el valor de la variable
bool SmartSprite::isOnDestination()
{
return mIsOnDestination;
}
// Pinta el objeto en pantalla
void SmartSprite::render()
{
if (mEnabled)
{
MovingSprite::render();
}
}
// Establece el valor de la variable
void SmartSprite::setId(int id)
{
mId = id;
}
// Establece el valor de la variable
void SmartSprite::setIntroEvents(Uint8 *value)
{
mIntroEvents = value;
}

73
source/smartsprite.h Normal file
View File

@@ -0,0 +1,73 @@
#pragma once
#include "utils.h"
#include "animatedsprite.h"
#ifndef SMARTSPRITE_H
#define SMARTSPRITE_H
// Clase SmartSprite
class SmartSprite : public AnimatedSprite
{
private:
bool mEnabled; // Indica si esta habilitado
bool mIsOnDestination; // Indica si está en el destino
int mDestX; // Posicion de destino en el eje X
int mDestY; // Posicion de destino en el eje Y
int mId; // Identificador
Uint16 mEnabledCounter; // Contador para deshabilitarlo
Uint8 *mIntroEvents; // Dirección del array de eventos donde notificar el estado
public:
// Constructor
SmartSprite();
// Destructor
~SmartSprite();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer);
// Pone a cero los elementos del objeto
void erase();
// Obtiene el valor de la variable
bool isEnabled();
// Establece el valor de la variable
void setEnabled(bool state);
// Obtiene el valor de la variable
Uint16 getEnabledTimer();
// Establece el valor de la variable
void setEnabledTimer(Uint16 time);
// Establece el valor de la variable
void setDestX(int value);
// Establece el valor de la variable
void setDestY(int value);
// Obtiene el valor de la variable
int getDestX();
// Obtiene el valor de la variable
int getDestY();
// Actualiza la posición y comprueba si ha llegado a su destino
bool update();
// Obtiene el valor de la variable
bool isOnDestination();
// Pinta el objeto en pantalla
void render();
// Establece el valor de la variable
void setId(int id);
// Establece el valor de la variable
void setIntroEvents(Uint8 *value);
};
#endif

165
source/sprite.cpp Normal file
View File

@@ -0,0 +1,165 @@
#include "sprite.h"
// Constructor
Sprite::Sprite()
{
init(0, 0, 0, 0, nullptr, nullptr);
}
// Destructor
Sprite::~Sprite()
{
mTexture = nullptr;
mRenderer = nullptr;
}
// Inicializador
void Sprite::init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer)
{
// Establece la posición X,Y del sprite
setPosX(x);
setPosY(y);
// Establece el alto y el ancho del sprite
setWidth(w);
setHeight(h);
// Establece el puntero al renderizador de la ventana
setRenderer(renderer);
// Establece la textura donde están los gráficos para el sprite
setTexture(texture);
// Establece el rectangulo de donde coger la imagen
setSpriteClip(0, 0, w, h);
// Habilita el objeto
setEnabled(true);
}
// Inicializador
void Sprite::init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer)
{
// Establece el alto y el ancho del sprite
mWidth = rect.w;
mHeight = rect.h;
// Establece la posición X,Y del sprite
mPosX = rect.x;
mPosY = rect.y;
// Establece el puntero al renderizador de la ventana
setRenderer(renderer);
// Establece la textura donde están los gráficos para el sprite
setTexture(texture);
// Establece el rectangulo de donde coger la imagen
setSpriteClip(rect);
}
// Muestra el sprite por pantalla
void Sprite::render()
{
if (mEnabled)
mTexture->render(mRenderer, mPosX, mPosY, &mSpriteClip);
}
// Obten el valor de la variable
int Sprite::getPosX()
{
return mPosX;
}
// Obten el valor de la variable
int Sprite::getPosY()
{
return mPosY;
}
// Obten el valor de la variable
int Sprite::getWidth()
{
return mWidth;
}
// Obten el valor de la variable
int Sprite::getHeight()
{
return mHeight;
}
// Establece el valor de la variable
void Sprite::setPosX(int x)
{
mPosX = x;
}
// Establece el valor de la variable
void Sprite::setPosY(int y)
{
mPosY = y;
}
// Establece el valor de la variable
void Sprite::setWidth(int w)
{
mWidth = w;
}
// Establece el valor de la variable
void Sprite::setHeight(int h)
{
mHeight = h;
}
// Obten el valor de la variable
SDL_Rect Sprite::getSpriteClip()
{
return mSpriteClip;
}
// Establece el valor de la variable
void Sprite::setSpriteClip(SDL_Rect rect)
{
mSpriteClip = rect;
}
// Establece el valor de la variable
void Sprite::setSpriteClip(int x, int y, int w, int h)
{
mSpriteClip.x = x;
mSpriteClip.y = y;
mSpriteClip.w = w;
mSpriteClip.h = h;
}
// Obten el valor de la variable
LTexture *Sprite::getTexture()
{
return mTexture;
}
// Establece el valor de la variable
void Sprite::setTexture(LTexture *texture)
{
mTexture = texture;
}
// Establece el valor de la variable
void Sprite::setRenderer(SDL_Renderer *renderer)
{
mRenderer = renderer;
}
// Establece el valor de la variable
void Sprite::setEnabled(bool value)
{
mEnabled = value;
}
// Comprueba si el objeto está habilitado
bool Sprite::isEnabled()
{
return mEnabled;
}

86
source/sprite.h Normal file
View File

@@ -0,0 +1,86 @@
#pragma once
#include "ifdefs.h"
#include "ltexture.h"
#ifndef SPRITE_H
#define SPRITE_H
// Clase sprite
class Sprite
{
protected:
int mPosX; // Posición en el eje X donde dibujar el sprite
int mPosY; // Posición en el eje Y donde dibujar el sprite
Uint16 mWidth; // Ancho del sprite
Uint16 mHeight; // Alto del sprite
SDL_Renderer *mRenderer; // Puntero al renderizador de la ventana
LTexture *mTexture; // Textura donde estan todos los dibujos del sprite
SDL_Rect mSpriteClip; // Rectangulo de origen de la textura que se dibujará en pantalla
bool mEnabled; // Indica si el sprite esta habilitado
public:
// Constructor
Sprite();
// Destructor
~Sprite();
// Inicializador
void init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer);
void init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer);
// Muestra el sprite por pantalla
void render();
// Obten el valor de la variable
int getPosX();
// Obten el valor de la variable
int getPosY();
// Obten el valor de la variable
int getWidth();
// Obten el valor de la variable
int getHeight();
// Establece el valor de la variable
void setPosX(int x);
// Establece el valor de la variable
void setPosY(int y);
// Establece el valor de la variable
void setWidth(int w);
// Establece el valor de la variable
void setHeight(int h);
// Obten el valor de la variable
SDL_Rect getSpriteClip();
// Establece el valor de la variable
void setSpriteClip(SDL_Rect rect);
// Establece el valor de la variable
void setSpriteClip(int x, int y, int w, int h);
// Obten el valor de la variable
LTexture *getTexture();
// Establece el valor de la variable
void setTexture(LTexture *texture);
// Establece el valor de la variable
void setRenderer(SDL_Renderer *renderer);
// Establece el valor de la variable
void setEnabled(bool value);
// Comprueba si el objeto está habilitado
bool isEnabled();
};
#endif

7897
source/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

5565
source/stb_vorbis.c Normal file

File diff suppressed because it is too large Load Diff

177
source/text.cpp Normal file
View File

@@ -0,0 +1,177 @@
#include "const.h"
#include "text.h"
#include <iostream>
#include <fstream>
// Constructor
Text::Text(std::string file, LTexture *texture, SDL_Renderer *renderer)
{
mSprite = new Sprite();
mSprite->setTexture(texture);
mSprite->setRenderer(renderer);
mFile = file;
init();
}
// Destructor
Text::~Text()
{
delete mSprite;
mSprite = nullptr;
}
// Inicializador
void Text::init()
{
// Inicializa a cero el vector con las coordenadas
for (int i = 0; i < 128; i++)
{
mOffset[i].x = 0;
mOffset[i].y = 0;
mOffset[i].w = 0;
}
// Carga los offsets desde el fichero
initOffsetFromFile();
// Inicia los valores del sprite que dibuja las letras
mSprite->setWidth(mBoxWidth);
mSprite->setHeight(mBoxHeight);
mSprite->setPosX(0);
mSprite->setPosY(0);
mSprite->setSpriteClip(0, 0, mSprite->getWidth(), mSprite->getHeight());
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; i++)
{
mOffset[i].x = ((i - 32) % 15) * mBoxWidth;
mOffset[i].y = ((i - 32) / 15) * mBoxHeight;
}
}
// Escribe texto en pantalla
void Text::write(int x, int y, std::string text, int kerning, int lenght)
{
Uint16 shift = 0;
if (lenght == -1)
lenght = text.length();
for (int i = 0; i < lenght; ++i)
{
mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight());
mSprite->setPosX(x + shift);
mSprite->setPosY(y);
mSprite->render();
shift += (mOffset[int(text[i])].w + kerning);
}
}
// Escribe el texto con colores
void Text::writeColored(int x, int y, std::string text, color_t color, int kerning, int lenght)
{
mSprite->getTexture()->setColor(color.r, color.g, color.b);
write(x, y, text, kerning, lenght);
mSprite->getTexture()->setColor(255, 255, 255);
}
// Escribe el texto con sombra
void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, int kerning, int lenght)
{
mSprite->getTexture()->setColor(color.r, color.g, color.b);
write(x + shadowDistance, y + shadowDistance, text, kerning, lenght);
mSprite->getTexture()->setColor(255, 255, 255);
write(x, y, text, kerning, lenght);
}
// Escribe el texto centrado en un punto x
void Text::writeCentered(int x, int y, std::string text, int kerning, int lenght)
{
x -= (Text::lenght(text, kerning) / 2);
write(x, y, text, kerning, lenght);
}
// Escribe texto con extras
void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, color_t textColor, Uint8 shadowDistance, color_t shadowColor, int lenght)
{
const bool centered = ((flags & TXT_CENTER) == TXT_CENTER);
const bool shadowed = ((flags & TXT_SHADOW) == TXT_SHADOW);
const bool colored = ((flags & TXT_COLOR) == TXT_COLOR);
const bool stroked = ((flags & TXT_STROKE) == TXT_STROKE);
if (centered)
x -= (Text::lenght(text, kerning) / 2);
if (shadowed)
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
if (stroked)
{
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x + shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x, y + shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x, y - shadowDistance, text, shadowColor, kerning, lenght);
writeColored(x + shadowDistance, y, text, shadowColor, kerning, lenght);
writeColored(x - shadowDistance, y, text, shadowColor, kerning, lenght);
}
if (colored)
writeColored(x, y, text, textColor, kerning, lenght);
else
write(x, y, text, kerning, lenght);
}
// Obtiene la longitud en pixels de una cadena
Uint16 Text::lenght(std::string text, int kerning)
{
Uint16 shift = 0;
for (int i = 0; i < (int)text.length(); ++i)
shift += (mOffset[int(text[i])].w + kerning);
return shift;
}
// Inicializa el vector de offsets desde un fichero
void Text::initOffsetFromFile()
{
std::ifstream rfile(mFile);
if (rfile.is_open() && rfile.good())
{
std::string buffer;
//printf("Reading %s file\n", mFile.c_str());
// Lee los dos primeros valores del fichero
std::getline(rfile, buffer);
std::getline(rfile, buffer);
mBoxWidth = std::stoi(buffer);
std::getline(rfile, buffer);
std::getline(rfile, buffer);
mBoxHeight = std::stoi(buffer);
// lee el resto de datos del fichero
int index = 32;
int line_read = 0;
while (std::getline(rfile, buffer))
{
// Almacena solo las lineas impares
if (line_read % 2 == 1)
mOffset[index++].w = std::stoi(buffer);
// Limpia el buffer
buffer.clear();
line_read++;
};
}
}
// Devuelve el valor de la variable
Uint8 Text::getCharacterWidth()
{
return mBoxWidth;
}

66
source/text.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include "sprite.h"
#include "utils.h"
#ifndef TEXT_H
#define TEXT_H
#define TXT_COLOR 1
#define TXT_SHADOW 2
#define TXT_CENTER 4
#define TXT_STROKE 8
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text
{
private:
Sprite *mSprite; // Objeto con los graficos para el texto
struct Offset
{
int x;
int y;
Uint8 w;
};
Offset mOffset[128]; // Vector con las posiciones y ancho de cada letra
Uint8 mBoxWidth; // Anchura de la caja de cada caracter en el png
Uint8 mBoxHeight; // Altura de la caja de cada caracter en el png
std::string mFile; // Fichero con los descriptores de la fuente
// Inicializa el vector de offsets desde un fichero
void initOffsetFromFile();
public:
// Constructor
Text(std::string file, LTexture *texture, SDL_Renderer *renderer);
// Destructor
~Text();
// Inicializador
void init();
// Escribe el texto en pantalla
void write(int x, int y, std::string text, int kerning = 1, int lenght = -1);
// Escribe el texto con colores
void writeColored(int x, int y, std::string text, color_t color, int kerning = 1, int lenght = -1);
// Escribe el texto con sombra
void writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance = 1, int kerning = 1, int lenght = -1);
// Escribe el texto centrado en un punto x y con kerning
void writeCentered(int x, int y, std::string text, int kerning = 1, int lenght = -1);
// Escribe texto con extras
void writeDX(Uint8 flags, int x, int y, std::string text, int kerning = 1, color_t textColor = {255, 255, 255}, Uint8 shadowDistance = 1, color_t shadowColor = {0, 0, 0}, int lenght = -1);
// Obtiene la longitud en pixels de una cadena
Uint16 lenght(std::string text, int kerning = 1);
// Devuelve el valor de la variable
Uint8 getCharacterWidth();
};
#endif

124
source/utils.cpp Normal file
View File

@@ -0,0 +1,124 @@
#include "utils.h"
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2)
{
int deltaX = x2 - x1;
int deltaY = y2 - y1;
return deltaX * deltaX + deltaY * deltaY;
}
// Detector de colisiones entre dos circulos
bool checkCollision(circle_t &a, circle_t &b)
{
// Calcula el radio total al cuadrado
int totalRadiusSquared = a.r + b.r;
totalRadiusSquared = totalRadiusSquared * totalRadiusSquared;
// Si la distancia entre el centro de los circulos es inferior a la suma de sus radios
if (distanceSquared(a.x, a.y, b.x, b.y) < (totalRadiusSquared))
{
// Los circulos han colisionado
return true;
}
// En caso contrario
return false;
}
// Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(circle_t &a, SDL_Rect &b)
{
//Closest point on collision box
int cX, cY;
//Find closest x offset
if (a.x < b.x)
{
cX = b.x;
}
else if (a.x > b.x + b.w)
{
cX = b.x + b.w;
}
else
{
cX = a.x;
}
//Find closest y offset
if (a.y < b.y)
{
cY = b.y;
}
else if (a.y > b.y + b.h)
{
cY = b.y + b.h;
}
else
{
cY = a.y;
}
//If the closest point is inside the circle_t
if (distanceSquared(a.x, a.y, cX, cY) < a.r * a.r)
{
//This box and the circle_t have collided
return true;
}
//If the shapes have not collided
return false;
}
// Detector de colisiones entre un dos rectangulos
bool checkCollision(SDL_Rect &a, SDL_Rect &b)
{
//Calculate the sides of rect A
int leftA = a.x;
int rightA = a.x + a.w;
int topA = a.y;
int bottomA = a.y + a.h;
//Calculate the sides of rect B
int leftB = b.x;
int rightB = b.x + b.w;
int topB = b.y;
int bottomB = b.y + b.h;
//If any of the sides from A are outside of B
if (bottomA <= topB)
{
return false;
}
if (topA >= bottomB)
{
return false;
}
if (rightA <= leftB)
{
return false;
}
if (leftA >= rightB)
{
return false;
}
//If none of the sides from A are outside B
return true;
}
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer)
{
bool success = true;
if (!texture->loadFromFile(path, renderer))
{
printf("Failed to load %s texture!\n", path.c_str());
success = false;
}
return success;
}

78
source/utils.h Normal file
View File

@@ -0,0 +1,78 @@
#pragma once
#include "ifdefs.h"
#include "ltexture.h"
#include <string>
#ifndef UTILS_H
#define UTILS_H
// Estructura para definir un circulo
struct circle_t
{
int x;
int y;
int r;
};
// Estructura para definir un color
struct color_t
{
Uint8 r;
Uint8 g;
Uint8 b;
};
// Estructura para saber la seccion y subseccion del programa
struct section_t
{
Uint8 name;
Uint8 subsection;
};
// Estructura para mapear el teclado usado en la demo
struct demoKeys_t
{
Uint8 left;
Uint8 right;
Uint8 noInput;
Uint8 fire;
Uint8 fireLeft;
Uint8 fireRight;
};
// Estructura para albergar métodos de control
struct input_t
{
int id; // Identificador en el vector de mandos
std::string name; // Nombre del dispositivo
Uint8 deviceType; // Tipo de dispositivo (teclado o mando)
};
// Estructura con todas las opciones de configuración del programa
struct options_t
{
Uint8 difficulty; // Dificultad del juego
input_t input[2]; // Modo de control (teclado o mando)
Uint8 language; // Idioma usado en el juego
Uint32 fullScreenMode; // Contiene el valor del modo de pantalla completa
Uint8 windowSize; // Contiene el valor del tamaño de la ventana
Uint32 filter; // Filtro usado para el escalado de la imagen
bool vSync; // Indica si se quiere usar vsync o no
};
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2);
// Detector de colisiones entre dos circulos
bool checkCollision(circle_t &a, circle_t &b);
// Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(circle_t &a, SDL_Rect &b);
// Detector de colisiones entre un dos rectangulos
bool checkCollision(SDL_Rect a, SDL_Rect b);
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer);
#endif

158
source/writer.cpp Normal file
View File

@@ -0,0 +1,158 @@
#include "const.h"
#include "writer.h"
// Constructor
Writer::Writer(Text *text)
{
mText = text;
init();
}
// Destructor
Writer::~Writer()
{
mText = nullptr;
}
// Inicializador
void Writer::init()
{
mPosX = 0;
mPosY = 0;
mKerning = 0;
mCaption = "";
mSpeed = 0;
mTimer = 0;
mIndex = 0;
mLenght = 0;
mCompleted = false;
mEnabled = false;
mEnabledTimer = 0;
mId = -1;
mIntroEvents = nullptr;
}
// Establece el valor de la variable
void Writer::setPosX(int value)
{
mPosX = value;
}
// Establece el valor de la variable
void Writer::setPosY(int value)
{
mPosY = value;
}
// Establece el valor de la variable
void Writer::setKerning(int value)
{
mKerning = value;
}
// Establece el valor de la variable
void Writer::setCaption(std::string text)
{
mCaption = text;
mLenght = text.length();
}
// Establece el valor de la variable
void Writer::setSpeed(Uint16 value)
{
mSpeed = value;
mTimer = value;
}
// Establece el valor de la variable
void Writer::setEnabled(bool value)
{
mEnabled = value;
}
// Obtiene el valor de la variable
bool Writer::IsEnabled()
{
return mEnabled;
}
// Establece el valor de la variable
void Writer::setEnabledTimer(Uint16 value)
{
mEnabledTimer = value;
}
// Obtiene el valor de la variable
Uint16 Writer::getEnabledTimer()
{
return mEnabledTimer;
}
// Actualiza el objeto
void Writer::update()
{
if (mEnabled)
{
if (mCompleted == false)
{
if (mTimer > 0)
{
mTimer--;
}
if (mTimer == 0)
{
mIndex++;
mTimer = mSpeed;
}
if (mIndex == mLenght)
{
mCompleted = true;
}
}
if (mCompleted)
{
if (mEnabledTimer > 0)
{
mEnabledTimer--;
}
else if (mEnabledTimer == 0)
{
if (mId < 0)
{
mEnabled = false;
}
else
{
mIntroEvents[mId] = EVENT_COMPLETED;
}
}
}
}
}
// Dibuja el objeto en pantalla
void Writer::render()
{
if (mEnabled)
{
mText->write(mPosX, mPosY, mCaption, mKerning, mIndex);
}
}
// Centra la cadena de texto a un punto X
void Writer::center(int x)
{
setPosX(x - (mText->lenght(mCaption, mKerning) / 2));
}
// Establece el valor de la variable
void Writer::setId(int id)
{
mId = id;
}
// Establece el valor de la variable
void Writer::setIntroEvents(Uint8 *value)
{
mIntroEvents = value;
}

80
source/writer.h Normal file
View File

@@ -0,0 +1,80 @@
#pragma once
#include "sprite.h"
#include "text.h"
#ifndef WRITER_H
#define WRITER_H
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Writer
{
private:
int mPosX; // Posicion en el eje X donde empezar a escribir el texto
int mPosY; // Posicion en el eje Y donde empezar a escribir el texto
int mKerning; // Kerning del texto, es decir, espaciado entre caracteres
std::string mCaption; // El texto para escribir
Uint16 mSpeed; // Velocidad de escritura
Uint16 mTimer; // Temporizador de escritura para cada caracter
Uint16 mIndex; // Posición del texto que se está escribiendo
Uint16 mLenght; // Longitud de la cadena a escribir
bool mCompleted; // Indica si se ha escrito todo el texto
bool mEnabled; // Indica si el objeto está habilitado
Uint16 mEnabledTimer; // Temporizador para deshabilitar el objeto
int mId; // Temporizador para deshabilitar el objeto
Uint8 *mIntroEvents; // Dirección del array de eventos donde notificar el estado
Text *mText; // Objeto encargado de escribir el texto
public:
// Constructor
Writer(Text *text);
// Destructor
~Writer();
// Inicializador
void init();
// Establece el valor de la variable
void setPosX(int value);
// Establece el valor de la variable
void setPosY(int value);
// Establece el valor de la variable
void setKerning(int value);
// Establece el valor de la variable
void setCaption(std::string text);
// Establece el valor de la variable
void setSpeed(Uint16 value);
// Establece el valor de la variable
void setEnabled(bool value);
// Obtiene el valor de la variable
bool IsEnabled();
// Establece el valor de la variable
void setEnabledTimer(Uint16 value);
// Obtiene el valor de la variable
Uint16 getEnabledTimer();
// Actualiza el objeto
void update();
// Dibuja el objeto en pantalla
void render();
// Centra la cadena de texto a un punto X
void center(int x);
// Establece el valor de la variable
void setId(int id);
// Establece el valor de la variable
void setIntroEvents(Uint8 *value);
};
#endif