114 Commits

Author SHA1 Message Date
d3f17bc93a Release 2.0 2021-09-03 19:21:26 +02:00
b7490ed1c1 Preparing release 2.0 2021-09-03 12:58:54 +02:00
836deb720d new logo.png 2021-09-03 12:47:16 +02:00
7e9a1cb049 bug fixes 2021-09-02 10:07:54 +02:00
f928195a05 bug fixes 2021-09-01 22:58:50 +02:00
84b09a4987 Bug fixes 2021-09-01 19:26:34 +02:00
f0b9a1d134 Fixed offset from render messages with nokia font 2021-09-01 19:10:00 +02:00
64369921ec bug fixes 2021-09-01 17:23:12 +02:00
70ae7f67a9 Merge branch 'master' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis 2021-09-01 16:54:41 +02:00
2ea86ef39f added font nokia2 2021-09-01 16:54:19 +02:00
658bb71441 bug fixes 2021-09-01 14:04:34 +02:00
0b996ea321 Working on support for various controllers 2021-08-31 21:36:09 +02:00
cf072424c6 Working on support for various controllers 2021-08-31 21:30:55 +02:00
42c0f19c68 Working on support for various controllers 2021-08-31 21:05:04 +02:00
8d1cabb288 updated some pngs 2021-08-31 18:00:55 +02:00
87aeaab6b8 bug fixes 2021-08-31 17:09:30 +02:00
ad5fb0fc22 Working on support for various controllers 2021-08-31 13:56:03 +02:00
8e6d546b97 Start to work on support for various controllers 2021-08-31 10:18:13 +02:00
f916381a9b added gamecontrollersDB.txt 2021-08-31 07:23:27 +02:00
fd94aea99b added gamecontrollerdb.txt 2021-08-30 22:24:39 +02:00
cda4d3a566 added gamecontrollerdb.txt 2021-08-30 22:24:16 +02:00
22ca349171 Improved menu class 2021-08-30 20:58:57 +02:00
74c08884ae Improving menu class. Selector flickers when selecting 2021-08-30 17:16:53 +02:00
005eab5694 Reduced checkFileList function 2021-08-30 14:06:33 +02:00
56dd646dde Centered new/translated GetReady text 2021-08-30 13:37:28 +02:00
eb7f534b3b menu selector now resizes smooth 2021-08-30 12:39:11 +02:00
384cfa7156 Solved 1P death music. Some tweaks to bg.png 2021-08-29 22:55:19 +02:00
224b176108 Dual input for P1 done 2021-08-29 22:03:48 +02:00
02b528ea8c Start to work on dual input for P1 2021-08-29 19:54:18 +02:00
4de3d69bb8 Powerup face blinking 2021-08-29 16:22:19 +02:00
c373d10720 added nokia_big font 2021-08-29 13:42:26 +02:00
88e5303d28 options menu completed 2021-08-29 13:35:19 +02:00
697e5d796f menu class improved 2021-08-29 00:54:05 +02:00
0baf73b9ae working on options menu, almost done 2021-08-28 23:45:29 +02:00
0341a0fe9d working on options menu, almost done 2021-08-28 23:17:00 +02:00
e9fcacd7c6 working on options menu 2021-08-28 21:43:47 +02:00
502835453a added difficulty (speed and points) 2021-08-28 19:51:32 +02:00
914b9e4123 fixing bugs 2021-08-28 18:26:45 +02:00
946ab62c30 writer class completed 2021-08-28 13:21:10 +02:00
13be9df131 text2 class converted to writer class 2021-08-28 12:57:13 +02:00
a54d71c990 lang class 2021-08-28 12:23:04 +02:00
cc8ef6e927 working on text notifications 2021-08-28 00:55:27 +02:00
3f53ba333b working on text notifications 2021-08-27 22:40:48 +02:00
aac11d05aa updated title.png 2021-08-27 16:49:15 +02:00
acbdcf2fc1 Working on title cosmetics 2021-08-27 16:48:10 +02:00
c12a7dc885 updated title.png 2021-08-27 16:25:10 +02:00
ff0102256c enhancing title screen 2021-08-27 13:54:57 +02:00
75031038c8 working on CM collider 2021-08-27 12:44:02 +02:00
70324570c8 bug hunting coffee machine on windows 2021-08-27 12:32:34 +02:00
5d6047b642 bug hunting coffee machine on windows 2021-08-27 08:58:54 +02:00
97d5140ef9 bug hunting coffee machine on windows 2021-08-27 08:33:21 +02:00
dafba0648f bug fix 2021-08-26 22:44:19 +02:00
d240f8123c fixing some bugs 2021-08-26 20:49:49 +02:00
3cb822ee6c working on new text engine 2021-08-26 18:14:56 +02:00
6d2fd16ec2 working on new font engine 2021-08-26 13:59:46 +02:00
e93aba2522 working on new font engine 2021-08-26 13:59:25 +02:00
5768c1f7a2 renamed fonts.png 2021-08-26 07:39:27 +02:00
30c8a31a48 moved fonts.png to new folder 2021-08-26 07:31:31 +02:00
a2a6262ffe working on new font engine 2021-08-25 22:35:54 +02:00
dbd22fa719 new font added 2021-08-25 20:00:59 +02:00
5bb5022ebf fix bullet owner bug 2021-08-25 17:59:40 +02:00
3440dea0a5 working on game controller 2021-08-25 13:34:40 +02:00
36eaf1de4f working on game controller 2021-08-25 12:02:18 +02:00
c3d560a9b6 working on game controller input 2021-08-24 20:52:32 +02:00
09cee79122 working on game controller input 2021-08-24 20:28:27 +02:00
03cbc67cfb working on game controller input 2021-08-24 20:20:08 +02:00
23d9bb0e3d working on game controller input 2021-08-24 20:15:20 +02:00
f9d6917770 working on game controller input 2021-08-24 20:12:28 +02:00
bf45482c10 working on game controller input 2021-08-24 20:06:34 +02:00
39a59336e4 working on game controller input 2021-08-24 19:56:25 +02:00
7c0201f913 working on game controller input 2021-08-24 17:57:21 +02:00
b61fd84e22 working on 2p 2021-08-24 13:01:33 +02:00
52ea512eab working on 2p 2021-08-23 21:53:54 +02:00
Sergio Valor
26ac51b1be working on 2players 2021-08-23 13:44:05 +02:00
fb1ff3c97a working on 2players 2021-08-23 08:11:24 +02:00
943fb7bf27 working on 2players 2021-08-22 19:50:55 +02:00
2fd4334259 added poerup and helper 2021-08-22 16:15:10 +02:00
eb8f84a4b8 added player2 gfx 2021-08-22 09:41:38 +02:00
e793e08e85 added player2 gfx 2021-08-22 09:41:17 +02:00
837306f16e added power up on the player 2021-08-21 20:39:48 +02:00
182631b2b7 repository cleanup 2021-08-21 14:46:00 +02:00
5cc9b16d59 repository cleanup 2021-08-21 14:45:14 +02:00
6224ed2779 repository cleanup 2021-08-21 14:42:38 +02:00
fc3a4efc5f repositoty cleanup 2021-08-21 14:41:01 +02:00
2be1e566b2 repository cleanup 2021-08-21 14:40:37 +02:00
017f691841 update readme.md 2021-08-21 12:54:41 +02:00
43c5ddcd1e Update readme.md 2021-08-21 12:53:47 +02:00
ef9f855785 repository cleanup 2021-08-21 12:50:57 +02:00
a70402ab5e repository cleanup 2021-08-21 11:12:21 +02:00
91bed82fd2 repository cleanup 2021-08-21 11:11:48 +02:00
90812f2140 Game end completed 2021-05-21 21:08:43 +02:00
0c0b677474 working on endgame 2021-05-21 10:34:34 +02:00
63bae5c504 update 2021-05-18 20:34:27 +02:00
5847c79ffb added support for text with ñ and ç 2021-04-28 21:04:01 +02:00
176d0d4f90 multi lang support 2021-04-27 22:28:00 +02:00
a0e94035db bugfixed initEnemyFormations 2021-04-22 12:10:47 +02:00
9b5eaf36e1 bughunting 2021-04-22 09:58:24 +02:00
f97291110f debuging memory leaks 2021-04-21 21:20:20 +02:00
e9ff516b1d working on class sections 2021-04-17 23:46:14 +02:00
2330820a15 "How to play" added 2021-04-05 19:07:33 +02:00
36bb6b8fe8 working on "How to play" 2021-04-05 17:56:15 +02:00
d84137daa7 Throw coffe with rotation and time stop with clock sound 2021-04-04 12:31:48 +02:00
4980c0f712 Throw coffee with rotate and clock sound on time stopped 2021-04-04 12:31:08 +02:00
b8cc628dd7 Merge pull request 'Soport per a OpenDingux' (#11) from JailDoctor/coffee_crisis_opendingux_dev:master into master
Reviewed-on: https://sustancia.synology.me:3000/JailDesigner/coffee_crisis/pulls/11
2021-04-01 11:44:42 +00:00
b663916a59 Cagades arregleited; generation script cleanup 2021-04-01 13:39:47 +02:00
6c1c6cbc42 minor type corrected 2021-04-01 13:26:16 +02:00
bcb012fc65 Basic opendingux support 2021-04-01 13:15:34 +02:00
67acc46222 updated sync.sh 2021-03-17 16:50:10 +01:00
8099e6dab6 v1.4 2021-03-17 13:51:01 +01:00
965ed711f7 v1.4 2021-03-17 12:34:11 +01:00
a3e608b01e before change player animation 2021-02-26 22:48:52 +01:00
765b64c29c code reorganized 2021-02-26 17:51:46 +01:00
190f1e9a47 bugfix: player could fire and get items after death 2021-02-20 19:04:13 +01:00
a8eff04d6a added .gitignore 2021-02-19 09:37:58 +01:00
103 changed files with 13144 additions and 6465 deletions

12
.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
.vscode
bin
data/config.bin
data/score.bin
dll
docs
icon
releases
resources
scripts
*.opk
*.DS_Store

View File

@@ -1,6 +1,6 @@
# Coffee Crisis # Coffee Crisis
Coffe Crisis es un juego arcade que pondrá a prueba tus reflejos. Realizado entre el verano de 2020 y el invierno de 2021. Intenta conseguir todos los puntos que puedas con una sola vida y ayuda a Bal1 a defender la UPV ante la invasión de la cafeína. Coffe Crisis es un juego arcade que pondrá a prueba tus reflejos. Empezado el verano de 2020 y terminado el verano de 2021. Intenta conseguir todos los puntos que puedas con una sola vida y ayuda a Bal1 a defender la UPV ante la invasión de la cafeína durante 10 estresantes oleadas.
## Compilar ## Compilar
@@ -8,10 +8,10 @@ Para compilar el código se necesitan tener las librerías SDL instaladas en el
En Linux: En Linux:
```bash ```bash
sudo apt install lib-SDL2 g++ sudo apt install libsdl2-dev g++
``` ```
En macos es más facil instalarlas con [brew](https://brew.sh): En macOS se pueden instalar fácilmente con [brew](https://brew.sh):
```bash ```bash
brew install sdl2 g++ brew install sdl2 g++
``` ```
@@ -23,21 +23,31 @@ En Linux:
make linux make linux
``` ```
En macos: En macOS:
```bash ```bash
make macos make macos
``` ```
## Como ejecutar ## Como ejecutar
Para ejecutar el juego hay que escribir en la terminal la orden que se muestra a continuación.
En Linux:
```bash ```bash
./bin/coffee_crisis bin/coffee_crisis_linux
``` ```
En macOS:
```bash
bin/coffee_crisis_macos
```
En macOS tambien puedes hacer doble click sobre el archivo coffee_crisis_macos que hay en la carpeta bin
## Agradecimientos ## Agradecimientos
A los jailers y a la jail. Y entre ellos, a JailDoctor por estar siempre ahí apoyándonos/obligándonos a sacar un Jailgame más. A los jailers y a la jail. Y entre ellos, a JailDoctor por estar siempre ahí apoyándonos/obligándonos a sacar un Jailgame más.
Y por supuesto a ti por estar aquí. Y por supuesto a ti por estar aquí.
## License ## Licencia
Buscar una licencia para que quiera haga con el código lo que le de la gana, menos sacar beneficio económico... que si lo hacen me expliquen como. Usa el código para lo que quieras: aprender, reirte, curiosear... excepto para sacar beneficio económico. Si lo consigues, por favor avísame y vamos a medias.

1144
data/gamecontrollerdb.txt Normal file

File diff suppressed because it is too large Load Diff

BIN
media/.DS_Store vendored

Binary file not shown.

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/nokia_big2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

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

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

BIN
media/font/smb2_big.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

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

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

BIN
media/gfx/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

BIN
media/gfx/player1_body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
media/gfx/player1_death.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
media/gfx/player1_head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 785 B

After

Width:  |  Height:  |  Size: 785 B

BIN
media/gfx/player2_body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
media/gfx/player2_death.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
media/gfx/player2_head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
media/gfx/player2_legs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 71 KiB

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:

BIN
media/music/.DS_Store vendored

Binary file not shown.

View File

@@ -1,10 +0,0 @@
playing.ogg
ARCADE GOBLINS
https://soundimage.org/chiptunes-3/
title.ogg
ARCADE STORIES
https://soundimage.org/chiptunes-3/
intro.ogg
JailDoctor

BIN
media/sound/clock.wav Normal file

Binary file not shown.

View File

@@ -1,60 +0,0 @@
bullet.wav
Gun11.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
balloon.wav
Impact3.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
player_collision.wav
Impact5.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
title.wav
Explosion2.wav
http://www.themotionmonkey.co.uk/free-resources/retro-arcade-sounds/
menu_select.wav
kenney_digitalaudio/powerUp2.ogg
www.kenney.nl
menu_move.wav
kenney_uiaudio/switch11.ogg
www.kenney.nl
hiscore.wav
kenney_digitalaudio/powerUp1.ogg
www.kenney.nl
itemdrop.wav
kenney_digitalaudio/PowerUp10.ogg
www.kenney.nl
itempickup.wav
kenney_digitalaudio/PowerUp7.ogg
www.kenney.nl
coffeeout.wav
kenney_digitalaudio/lowDown.ogg
www.kenney.nl
stage_change.wav
kenney_digitalaudio/phaserUp2.ogg
www.kenney.nl
menu_cancel.wav
kenney_digitalaudio/lowRandom.ogg
kenney_digitalaudio/pepSound1.ogg <-
www.kenney.nl
bubble1.wav
JailDoctor
bubble2.wav
JailDoctor
bubble3.wav
JailDoctor
bubble4.wav
JailDoctor

BIN
media/sound/powerball.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
source/.DS_Store vendored

Binary file not shown.

View File

@@ -1,17 +1,16 @@
#include "const.h" #include "const.h"
#include "animatedsprite.h" #include "animatedsprite.h"
#include <iostream>
// Constructor // Constructor
AnimatedSprite::AnimatedSprite() AnimatedSprite::AnimatedSprite()
{ {
init(nullptr, nullptr); //init(nullptr, nullptr);
} }
// Destructor // Destructor
AnimatedSprite::~AnimatedSprite() AnimatedSprite::~AnimatedSprite()
{ {
init(nullptr, nullptr); //init(nullptr, nullptr);
} }
// Iniciador // Iniciador
@@ -19,12 +18,13 @@ void AnimatedSprite::init(LTexture *texture, SDL_Renderer *renderer)
{ {
mRenderer = renderer; mRenderer = renderer;
mTexture = texture; mTexture = texture;
for (Uint8 i = 0; i < 20; i++) for (int i = 0; i < 20; i++)
{ {
mAnimation[i].numFrames = 0; mAnimation[i].numFrames = 0;
mAnimation[i].speed = 0; mAnimation[i].speed = 0;
mAnimation[i].loop = true; mAnimation[i].loop = true;
for (Uint8 j = 0; i < 20; i++) mAnimation[i].completed = false;
for (int j = 0; i < 20; i++)
{ {
mAnimation[i].frames[j].x = 0; mAnimation[i].frames[j].x = 0;
mAnimation[i].frames[j].y = 0; mAnimation[i].frames[j].y = 0;
@@ -39,30 +39,29 @@ void AnimatedSprite::init(LTexture *texture, SDL_Renderer *renderer)
// Calcula el frame correspondiente a la animación // Calcula el frame correspondiente a la animación
void AnimatedSprite::animate(int index) void AnimatedSprite::animate(int index)
{ {
// Calculamos el frame actual a partir del contador if (mEnabled)
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) // 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)
{ {
mAnimationCounter = 0; if (mAnimation[index].loop)
mAnimationCounter = 0;
else
mCurrentFrame = mAnimation[index].numFrames;
} }
// En caso contrario
else else
{ {
mCurrentFrame = mAnimation[index].numFrames; // Escogemos el frame correspondiente de la animación
} setSpriteClip(mAnimation[index].frames[mCurrentFrame]);
}
// En caso contrario
else
{
// Escogemos el frame correspondiente de la animación
setSpriteClip(mAnimation[index].frames[mCurrentFrame]);
// Incrementamos el contador de la animacion // Incrementamos el contador de la animacion
++mAnimationCounter; mAnimationCounter++;
}
} }
} }
@@ -105,6 +104,18 @@ void AnimatedSprite::setAnimationLoop(Uint8 index, bool loop)
mAnimation[index].loop = 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 // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(Uint8 index_animation, Uint8 index_frame) SDL_Rect AnimatedSprite::getAnimationClip(Uint8 index_animation, Uint8 index_frame)
{ {

View File

@@ -5,9 +5,26 @@
#ifndef ANIMATEDSPRITE_H #ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H #define ANIMATEDSPRITE_H
#define MAX_FRAMES 30
#define MAX_ANIMATIONS 20
// Clase AnimatedSprite // Clase AnimatedSprite
class AnimatedSprite : public MovingSprite 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: public:
// Constructor // Constructor
AnimatedSprite(); AnimatedSprite();
@@ -39,26 +56,14 @@ public:
// Establece si la animación se reproduce en bucle // Establece si la animación se reproduce en bucle
void setAnimationLoop(Uint8 index, bool loop); 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 // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(Uint8 index_animation, Uint8 index_frame); SDL_Rect getAnimationClip(Uint8 index_animation, Uint8 index_frame);
private:
struct sAnimation
{
SDL_Rect frames[20]; // Hasta 20 frames
Uint8 numFrames;
Uint8 speed;
bool loop;
};
// Vector con las diferentes animaciones y los diferentes frames de cada animación
sAnimation mAnimation[20]; // Hasta 20 animaciones
// Frame actual
Uint8 mCurrentFrame;
// Contador para las animaciones
Uint16 mAnimationCounter;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,73 @@
#pragma once #pragma once
#include "struct.h" #include "utils.h"
#include "animatedsprite.h" #include "animatedsprite.h"
#ifndef BALLOON_H #ifndef BALLOON_H
#define BALLOON_H #define BALLOON_H
#define MAX_BOUNCE 10
// Clase globo // Clase globo
class Balloon class Balloon
{ {
private:
float mPosX; // Posición en el eje X
float mPosY; // Posición en el eje Y
Uint8 mWidth; // Ancho
Uint8 mHeight; // Alto
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 mGravity; // Aceleración en el eje Y. Modifica la velocidad
float mDefaultVelY; // Velocidad inicial que tienen al rebotar contra el suelo
float mMaxVelY; // Máxima velocidad que puede alcanzar el objeto en el eje Y
AnimatedSprite *mSprite; // Sprite del objeto globo
bool mBeingCreated; // Indica si el globo se está creando
bool mBlinking; // Indica si el globo está intermitente
bool mEnabled; // Indica si el globo esta activo
bool mInvulnerable; // Indica si el globo es invulnerable
bool mPopping; // Indica si el globo está explotando
bool mStopped; // Indica si el globo está parado
bool mVisible; // Indica si el globo es visible
circle_t mCollider; // Circulo de colisión del objeto
Uint16 mCreationCounter; // Temporizador para controlar el estado "creandose"
Uint16 mCreationCounterIni; // Valor inicial para el temporizador para controlar el estado "creandose"
Uint16 mScore; // Puntos que da el globo al ser destruido
Uint16 mStoppedCounter; // Contador para controlar el estado "parado"
Uint16 mTimeToLive; // Indica el tiempo de vida que le queda al globo
Uint8 mKind; // Tipo de globo
Uint8 mMenace; // Cantidad de amenaza que genera el globo
Uint32 mCounter; // Contador interno
float mTravelY; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad
float mSpeed; // Velocidad a la que se mueven los globos
Uint8 mSize; // Tamaño del globo
Uint8 mPower; // Cantidad de poder que alberga el globo
struct bouncing // Estructura para las variables para el efecto de los rebotes
{
bool enabled; // Si el efecto está activo
Uint8 counter; // Countador para el efecto
Uint8 speed; // Velocidad a la que transcurre el efecto
float zoomW; // Zoom aplicado a la anchura
float zoomH; // Zoom aplicado a la altura
float despX; // Desplazamiento de pixeles en el eje X antes de pintar el objeto con zoom
float despY; // Desplazamiento de pixeles en el eje Y antes de pintar el objeto con zoom
// Vector con los valores de zoom para el ancho y alto del globo
float w[MAX_BOUNCE] = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f};
float h[MAX_BOUNCE] = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f};
};
bouncing mBouncing;
void updateColliders(); // Alinea el circulo de colisión con la posición del objeto globo
void bounceStart(); // Activa el efecto
void bounceStop(); // Detiene el efecto
void updateBounce(); // Aplica el efecto
void updateState(); // Actualiza los estados del globo
void updateAnimation(); // Establece la animación correspondiente
void setBeingCreated(bool state); // Establece el valor de la variable
void setTimeToLive(Uint16 time); // Establece el valor de la variable
Uint16 getTimeToLive(); // Obtiene del valor de la variable
public: public:
// Constructor // Constructor
Balloon(); Balloon();
@@ -16,7 +76,7 @@ public:
~Balloon(); ~Balloon();
// Inicializador // Inicializador
void init(float x, int y, Uint8 kind, float velx, Uint16 creationtimer, LTexture* texture, SDL_Renderer *renderer); void init(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, LTexture *texture, SDL_Renderer *renderer);
// Centra el globo en la posición X // Centra el globo en la posición X
void allignTo(int x); void allignTo(int x);
@@ -27,8 +87,8 @@ public:
// Actualiza la posición y estados del globo // Actualiza la posición y estados del globo
void move(); void move();
// Pone a cero todos los valores del globo // Deshabilita el globo y pone a cero todos los valores
void erase(); void disable();
// Explosiona el globo // Explosiona el globo
void pop(); void pop();
@@ -36,17 +96,14 @@ public:
// Actualiza al globo a su posicion, animación y controla los contadores // Actualiza al globo a su posicion, animación y controla los contadores
void update(); void update();
// Establece la animación correspondiente // Comprueba si el globo está habilitado
void setAnimation(); bool isEnabled();
// Comprueba si el globo tiene algun tipo asignado
bool isActive();
// Obtiene del valor de la variable // Obtiene del valor de la variable
int getPosX(); float getPosX();
// Obtiene del valor de la variable // Obtiene del valor de la variable
int getPosY(); float getPosY();
// Obtiene del valor de la variable // Obtiene del valor de la variable
float getVelY(); float getVelY();
@@ -60,9 +117,18 @@ public:
// Establece el valor de la variable // Establece el valor de la variable
void setVelY(float velY); void setVelY(float velY);
// Establece el valor de la variable
void setSpeed(float speed);
// Obtiene del valor de la variable // Obtiene del valor de la variable
int getKind(); int getKind();
// Obtiene del valor de la variable
Uint8 getSize();
// Obtiene la clase a la que pertenece el globo
Uint8 getClass();
// Establece el valor de la variable // Establece el valor de la variable
void setStop(bool state); void setStop(bool state);
@@ -87,9 +153,6 @@ public:
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isInvulnerable(); bool isInvulnerable();
// Establece el valor de la variable
void setBeingCreated(bool state);
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isBeingCreated(); bool isBeingCreated();
@@ -99,12 +162,6 @@ public:
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isPopping(); bool isPopping();
// Establece el valor de la variable
void setTimeToLive(Uint16 time);
// Obtiene del valor de la variable
Uint16 getTimeToLive();
// Establece el valor de la variable // Establece el valor de la variable
void setStoppedTimer(Uint16 time); void setStoppedTimer(Uint16 time);
@@ -115,71 +172,13 @@ public:
Uint16 getScore(); Uint16 getScore();
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &getCollider(); circle_t &getCollider();
// Obtiene le valor de la variable // Obtiene le valor de la variable
Uint8 getMenace(); Uint8 getMenace();
private: // Obtiene le valor de la variable
// Posición X,Y del objeto globo Uint8 getPower();
float mPosX;
int mPosY;
// Alto y ancho del objeto globo
Uint8 mWidth;
Uint8 mHeight;
// Variables para controlar la velocidad del globo
float mVelX;
float mVelY;
float mGravity;
float mDefaultVelY;
int mMaxVelY;
// Puntos que da el globo al ser destruido
Uint16 mScore;
// Nivel de amenaza del globo
Uint8 mMenace;
// Indica si el globo está parado
bool mStopped;
// Temporizador para controlar el estado "parado"
Uint16 mStoppedTimer;
// Indica si el globo está intermitente
bool mBlinking;
// Indica si el globo es visible
bool mVisible;
// Indica si el globo es invulnerable
bool mInvulnerable;
// Indica si el globo se está creando
bool mBeingCreated;
// Indica si el globo está explotando
bool mPopping;
// Indica el tiempo de vida que le queda al globo
Uint16 mTimeToLive;
// Temporizador para controlar el estado "creandose"
Uint16 mCreationTimer;
// Tipo de globo
Uint8 mKind;
// Sprite del objeto globo
AnimatedSprite *mSprite;
// Circulo de colisión del objeto
Circle mCollider;
// Alinea el circulo de colisión con la posición del objeto globo
void shiftColliders();
}; };
#endif #endif

View File

@@ -5,18 +5,19 @@
Bullet::Bullet() Bullet::Bullet()
{ {
mSprite = new Sprite(); mSprite = new Sprite();
init(0, 0, NO_KIND, nullptr, nullptr); mKind = NO_KIND;
} }
// Destructor // Destructor
Bullet::~Bullet() Bullet::~Bullet()
{ {
init(0, 0, NO_KIND, nullptr, nullptr); //init(0, 0, NO_KIND, nullptr, nullptr);
delete mSprite; delete mSprite;
mSprite = nullptr;
} }
// Iniciador // Iniciador
void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *renderer) void Bullet::init(int x, int y, int kind, bool poweredUp, int owner, LTexture *texture, SDL_Renderer *renderer)
{ {
// Posición inicial del objeto // Posición inicial del objeto
mPosX = x; mPosX = x;
@@ -32,6 +33,9 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
// Tipo de bala // Tipo de bala
mKind = kind; mKind = kind;
// Identificador del dueño del objeto
mOwner = owner;
// Textura con los gráficos del objeto // Textura con los gráficos del objeto
mSprite->setTexture(texture); mSprite->setTexture(texture);
@@ -54,7 +58,10 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
mVelX = 0; mVelX = 0;
// Rectangulo con los gráficos del objeto // Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(0 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight()); if (!poweredUp)
mSprite->setSpriteClip(0 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
else
mSprite->setSpriteClip((0 + 3) * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break; break;
case BULLET_LEFT: case BULLET_LEFT:
@@ -62,7 +69,10 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
mVelX = -2; mVelX = -2;
// Rectangulo con los gráficos del objeto // Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(1 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight()); if (!poweredUp)
mSprite->setSpriteClip(1 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
else
mSprite->setSpriteClip((1 + 3) * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break; break;
case BULLET_RIGHT: case BULLET_RIGHT:
@@ -70,7 +80,10 @@ void Bullet::init(int x, int y, int kind, LTexture *texture, SDL_Renderer *rende
mVelX = 2; mVelX = 2;
// Rectangulo con los gráficos del objeto // Rectangulo con los gráficos del objeto
mSprite->setSpriteClip(2 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight()); if (!poweredUp)
mSprite->setSpriteClip(2 * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
else
mSprite->setSpriteClip((2 + 3) * mWidth, 0, mSprite->getWidth(), mSprite->getHeight());
break; break;
default: default:
@@ -147,7 +160,7 @@ void Bullet::testMove()
// Deshabilita el objeto // Deshabilita el objeto
void Bullet::erase() void Bullet::erase()
{ {
init(0, 0, 0, nullptr, nullptr); init(0, 0, 0, false, -1, nullptr, nullptr);
} }
// Comprueba si el objeto está activo // Comprueba si el objeto está activo
@@ -199,8 +212,14 @@ int Bullet::getKind()
return mKind; return mKind;
} }
// Obtiene el valor de la variable
int Bullet::getOwner()
{
return mOwner;
}
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &Bullet::getCollider() circle_t &Bullet::getCollider()
{ {
return mCollider; return mCollider;
} }

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "struct.h" #include "utils.h"
#include "sprite.h" #include "sprite.h"
#ifndef BULLET_H #ifndef BULLET_H
@@ -8,6 +8,21 @@
// Clase bala // Clase bala
class Bullet class Bullet
{ {
private:
int mPosX; // Posición en el eje X
int mPosY; // Posición en el eje Y
Uint8 mWidth; // Ancho del objeto
Uint8 mHeight; // Alto del objeto
int mVelX; // Velocidad en el eje X
int mVelY; // Velocidad en el eje Y
int mKind; // Tipo de objeto
int mOwner; // Identificador del dueño del objeto
Sprite *mSprite; // Sprite con los graficos y métodos de pintado
circle_t mCollider; // Circulo de colisión del objeto
// Alinea el circulo de colisión con el objeto
void shiftColliders();
public: public:
// Constructor // Constructor
Bullet(); Bullet();
@@ -16,11 +31,11 @@ public:
~Bullet(); ~Bullet();
// Iniciador // Iniciador
void init(int x, int y, int kind, LTexture* texture, SDL_Renderer *renderer); void init(int x, int y, int kind, bool poweredUp, int owner, LTexture *texture, SDL_Renderer *renderer);
// Pinta el objeto en pantalla // Pinta el objeto en pantalla
void render(); void render();
// Actualiza la posición y estado del objeto // Actualiza la posición y estado del objeto
Uint8 move(); Uint8 move();
@@ -48,33 +63,11 @@ public:
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getKind(); int getKind();
// Obtiene el valor de la variable
int getOwner();
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &getCollider(); circle_t &getCollider();
private:
// Posición X/Y del objeto
int mPosX;
int mPosY;
// Alto y ancho el objeto
Uint8 mWidth;
Uint8 mHeight;
// Velocidad del objeto
int mVelX;
int mVelY;
// Tipo de objeto
int mKind;
// Sprite con los graficos y métodos de pintado
Sprite *mSprite;
// Balloon's collision circle
Circle mCollider;
// Alinea el circulo de colisión con el objeto
void shiftColliders();
}; };
#endif #endif

89
source/coffeedrop.cpp Normal file
View File

@@ -0,0 +1,89 @@
#include "const.h"
#include "coffeedrop.h"
#ifndef UNUSED
// Constructor
CoffeeDrop::CoffeeDrop()
{
mPosX = 0;
mPosY = 0;
mWidth = 8;
mHeight = 8;
mVelX = 0;
mVelY = 0;
mGravity = 0.1f;
mFloor = 0;
mEnabled = false;
mSprite = new Sprite();
mAlpha = 128;
}
// Destructor
CoffeeDrop::~CoffeeDrop()
{
delete mSprite;
}
// Inicializador
void CoffeeDrop::init(LTexture *texture, SDL_Renderer *renderer, float x, float y, float velX, float velY, int floor)
{
mEnabled = true;
mPosX = x;
mPosY = y;
mVelX = velX;
mVelY = velY;
mFloor = floor;
mSprite->setRenderer(renderer);
mSprite->setTexture(texture);
mSprite->setSpriteClip(256, 97, mWidth, mHeight);
mSprite->setPosX(x);
mSprite->setPosY(y);
}
// Actualiza las variables del objeto
void CoffeeDrop::update()
{
if (mEnabled)
{
mVelY += mGravity;
mPosX += mVelX;
mPosY += mVelY;
mSprite->setPosX((int)mPosX);
mSprite->setPosY((int)mPosY);
if ((mPosY > mFloor) || (mPosX > PLAY_AREA_RIGHT) || ((mPosX - mWidth) < PLAY_AREA_LEFT))
mEnabled = false;
mAlpha -= 2;
if (mAlpha == 0)
mEnabled = false;
}
}
// Pinta el objeto
void CoffeeDrop::render()
{
if (mEnabled)
{
mSprite->getTexture()->setAlpha(mAlpha);
mSprite->render();
mSprite->getTexture()->setAlpha(255);
}
}
// Deshabilita el objeto
void CoffeeDrop::disable()
{
mEnabled = false;
}
// Comprueba si està habilitado
bool CoffeeDrop::isEnabled()
{
return mEnabled;
}
#endif

50
source/coffeedrop.h Normal file
View File

@@ -0,0 +1,50 @@
#pragma once
#include "sprite.h"
#ifndef COFFEEDROP_H
#define COFFEEDROP_H
#ifndef UNUSED
// Clase CoffeeDrop. Gotas de café que aparecen al explotar un globo
class CoffeeDrop
{
private:
float mPosX; // Posicion en el eje X del objeto
float mPosY; // Posicion en el eje Y del objeto
Uint8 mWidth; // Ancho del sprite
Uint8 mHeight; // Alto del sprite
float mVelX; // Velocidad en el eje X
float mVelY; // Velocidad en el eje Y
float mGravity; // Aceleración en el eje Y
int mFloor; // Punto donde se encuentra el suelo y desaparecen
bool mEnabled; // Si esta habilitado. Sirve para saber si se pinta, se actualiza o se puede usar
Sprite *mSprite; // Puntero al sprite con los graficos
Uint8 mAlpha;
public:
// Constructor
CoffeeDrop();
// Destructor
~CoffeeDrop();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer, float x, float y, float velX, float velY, int floor);
// Actualiza las variables del objeto
void update();
// Pinta el objeto
void render();
// Deshabilita el objeto
void disable();
// Comprueba si està habilitado
bool isEnabled();
};
#endif
#endif

View File

@@ -1,5 +1,7 @@
#pragma once #pragma once
#include "ifdefs.h" #include "ifdefs.h"
#include "utils.h"
#include "lang.h"
#include <string> #include <string>
#ifndef CONST_H #ifndef CONST_H
@@ -7,73 +9,77 @@
// Textos // Textos
#define WINDOW_CAPTION "Coffee Crisis" #define WINDOW_CAPTION "Coffee Crisis"
#define TEXT_COPYRIGHT "@2020,2021 JAILDESIGNER (V1.3*)" #define TEXT_COPYRIGHT "@2020,2021 JailDesigner (v2.0)"
// Recursos // Recursos
const Uint8 BINFILE_SCORE = 0; #define BINFILE_SCORE 0
const Uint8 BINFILE_DEMO = 1; #define BINFILE_DEMO 1
const Uint8 BINFILE_CONFIG = 2; #define BINFILE_CONFIG 2
const Uint8 TOTAL_BINFILE = 3; #define TOTAL_BINFILE 3
const Uint8 MUSIC_INTRO = 0; #define MUSIC_INTRO 0
const Uint8 MUSIC_PLAYING = 1; #define MUSIC_PLAYING 1
const Uint8 MUSIC_TITLE = 2; #define MUSIC_TITLE 2
const Uint8 TOTAL_MUSIC = 3; #define TOTAL_MUSIC 3
const Uint8 SOUND_BALLON = 0; #define SOUND_BALLOON 0
const Uint8 SOUND_BULLET = 1; #define SOUND_BUBBLE1 1
const Uint8 SOUND_MENU_SELECT = 2; #define SOUND_BUBBLE2 2
const Uint8 SOUND_MENU_CANCEL = 3; #define SOUND_BUBBLE3 3
const Uint8 SOUND_MENU_MOVE = 4; #define SOUND_BUBBLE4 4
const Uint8 SOUND_TITLE = 5; #define SOUND_BULLET 5
const Uint8 SOUND_PLAYER_COLLISION = 6; #define SOUND_COFFEE_OUT 6
const Uint8 SOUND_HISCORE = 7; #define SOUND_HISCORE 7
const Uint8 SOUND_ITEM_DROP = 8; #define SOUND_ITEM_DROP 8
const Uint8 SOUND_ITEM_PICKUP = 9; #define SOUND_ITEM_PICKUP 9
const Uint8 SOUND_COFFEE_OUT = 10; #define SOUND_MENU_CANCEL 10
const Uint8 SOUND_STAGE_CHANGE = 11; #define SOUND_MENU_MOVE 11
const Uint8 SOUND_BUBBLE1 = 12; #define SOUND_MENU_SELECT 12
const Uint8 SOUND_BUBBLE2 = 13; #define SOUND_PLAYER_COLLISION 13
const Uint8 SOUND_BUBBLE3 = 14; #define SOUND_STAGE_CHANGE 14
const Uint8 SOUND_BUBBLE4 = 15; #define SOUND_TITLE 15
#define SOUND_CLOCK 16
#define SOUND_POWERBALL 17
const Uint8 TOTAL_SOUND = 16; #define TOTAL_SOUND 18
const Uint8 TEXTURE_BALLOON = 0; #define TEXTURE_BALLOON 0
const Uint8 TEXTURE_BULLET = 1; #define TEXTURE_BULLET 1
const Uint8 TEXTURE_FONT_BLACK = 2; #define TEXTURE_FONT_BLACK 2
const Uint8 TEXTURE_FONT_NOKIA = 3; #define TEXTURE_FONT_BLACK_X2 3
const Uint8 TEXTURE_FONT_WHITE = 4; #define TEXTURE_FONT_NOKIA 4
const Uint8 TEXTURE_GAME_BG = 5; #define TEXTURE_FONT_WHITE 5
const Uint8 TEXTURE_GAME_TEXT = 6; #define TEXTURE_FONT_WHITE_X2 6
const Uint8 TEXTURE_INTRO = 7; #define TEXTURE_GAME_BG 7
const Uint8 TEXTURE_ITEMS = 8; #define TEXTURE_GAME_TEXT 8
const Uint8 TEXTURE_LOGO = 9; #define TEXTURE_INTRO 9
const Uint8 TEXTURE_MENU = 10; #define TEXTURE_ITEMS 10
const Uint8 TEXTURE_PLAYER_BODY = 11; #define TEXTURE_LOGO 11
const Uint8 TEXTURE_PLAYER_LEGS = 12; #define TEXTURE_MENU 12
const Uint8 TEXTURE_PLAYER_DEATH = 13; #define TEXTURE_PLAYER_BODY 13
const Uint8 TEXTURE_TITLE = 14; #define TEXTURE_PLAYER_DEATH 14
#define TEXTURE_PLAYER_LEGS 15
#define TEXTURE_TITLE 16
const Uint8 TOTAL_TEXTURE = 15; #define TOTAL_TEXTURE 17
// Tamaño de bloque // Tamaño de bloque
const Uint8 BLOCK = 8; #define BLOCK 8
const Uint8 HALF_BLOCK = BLOCK / 2; #define HALF_BLOCK BLOCK / 2
// Tamaño de la pantalla real // Tamaño de la pantalla real
const int SCREEN_WIDTH = 256; #define SCREEN_WIDTH 256
const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4; // 192 const int SCREEN_HEIGHT = SCREEN_WIDTH * 3 / 4;
// Tamaño de la pantalla que se muestra // Tamaño de la pantalla que se muestra
const int VIEW_WIDTH = SCREEN_WIDTH * 3; // 768 const int VIEW_WIDTH = SCREEN_WIDTH * 3;
const int VIEW_HEIGHT = SCREEN_HEIGHT * 3; // 576 const int VIEW_HEIGHT = SCREEN_HEIGHT * 3;
// Cantidad de enteros a escribir en los ficheros de datos // Cantidad de enteros a escribir en los ficheros de datos
const Uint8 TOTAL_SCORE_DATA = 3; #define TOTAL_SCORE_DATA 3
const Uint16 TOTAL_DEMO_DATA = 2000; #define TOTAL_DEMO_DATA 2000
// Zona de juego // Zona de juego
const int PLAY_AREA_TOP = (0 * BLOCK); const int PLAY_AREA_TOP = (0 * BLOCK);
@@ -82,7 +88,9 @@ const int PLAY_AREA_LEFT = (0 * BLOCK);
const int PLAY_AREA_RIGHT = SCREEN_WIDTH - (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_WIDTH = PLAY_AREA_RIGHT - PLAY_AREA_LEFT;
const int PLAY_AREA_HEIGHT = PLAY_AREA_BOTTOM - PLAY_AREA_TOP; 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_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_CENTER_Y = PLAY_AREA_TOP + (PLAY_AREA_HEIGHT / 2);
const int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4; const int PLAY_AREA_FIRST_QUARTER_Y = PLAY_AREA_HEIGHT / 4;
const int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3; const int PLAY_AREA_THIRD_QUARTER_Y = (PLAY_AREA_HEIGHT / 4) * 3;
@@ -95,95 +103,98 @@ const int SCREEN_CENTER_Y = SCREEN_HEIGHT / 2;
const int SCREEN_FIRST_QUARTER_Y = SCREEN_HEIGHT / 4; const int SCREEN_FIRST_QUARTER_Y = SCREEN_HEIGHT / 4;
const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3; const int SCREEN_THIRD_QUARTER_Y = (SCREEN_HEIGHT / 4) * 3;
// Color transparente para los sprites
const Uint8 COLOR_KEY_R = 0xff;
const Uint8 COLOR_KEY_G = 0x00;
const Uint8 COLOR_KEY_B = 0xff;
// Opciones de menu // Opciones de menu
const int MENU_NO_OPTION = -1; #define MENU_NO_OPTION -1
const int MENU_OPTION_START = 0; #define MENU_OPTION_START 0
const int MENU_OPTION_QUIT = 1; #define MENU_OPTION_QUIT 1
const int MENU_OPTION_TOTAL = 2; #define MENU_OPTION_TOTAL 2
// Selector de menu
const int MENU_SELECTOR_BLACK = (BLOCK * 0);
const int MENU_SELECTOR_WHITE = (BLOCK * 1);
// Tipos de fondos para el menu // Tipos de fondos para el menu
const int MENU_BACKGROUND_TRANSPARENT = 0; #define MENU_BACKGROUND_TRANSPARENT 0
const int MENU_BACKGROUND_SOLID = 1; #define MENU_BACKGROUND_SOLID 1
// Estados del jugador // Estados del jugador
const Uint8 PLAYER_STATUS_WALKING_LEFT = 0; #define PLAYER_STATUS_WALKING_LEFT 0
const Uint8 PLAYER_STATUS_WALKING_RIGHT = 1; #define PLAYER_STATUS_WALKING_RIGHT 1
const Uint8 PLAYER_STATUS_WALKING_STOP = 2; #define PLAYER_STATUS_WALKING_STOP 2
const Uint8 PLAYER_STATUS_FIRING_UP = 0; #define PLAYER_STATUS_FIRING_UP 0
const Uint8 PLAYER_STATUS_FIRING_LEFT = 1; #define PLAYER_STATUS_FIRING_LEFT 1
const Uint8 PLAYER_STATUS_FIRING_RIGHT = 2; #define PLAYER_STATUS_FIRING_RIGHT 2
const Uint8 PLAYER_STATUS_FIRING_NO = 3; #define PLAYER_STATUS_FIRING_NO 3
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_LEFT = 0; #define PLAYER_ANIMATION_LEGS_WALKING_LEFT 0
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_RIGHT = 1; #define PLAYER_ANIMATION_LEGS_WALKING_RIGHT 1
const Uint8 PLAYER_ANIMATION_LEGS_WALKING_STOP = 2; #define PLAYER_ANIMATION_LEGS_WALKING_STOP 2
const Uint8 PLAYER_ANIMATION_BODY_WALKING_LEFT = 0; #define PLAYER_ANIMATION_BODY_WALKING_LEFT 0
const Uint8 PLAYER_ANIMATION_BODY_FIRING_LEFT = 1; #define PLAYER_ANIMATION_BODY_FIRING_LEFT 1
const Uint8 PLAYER_ANIMATION_BODY_WALKING_RIGHT = 2; #define PLAYER_ANIMATION_BODY_WALKING_RIGHT 2
const Uint8 PLAYER_ANIMATION_BODY_FIRING_RIGHT = 3; #define PLAYER_ANIMATION_BODY_FIRING_RIGHT 3
const Uint8 PLAYER_ANIMATION_BODY_WALKING_STOP = 4; #define PLAYER_ANIMATION_BODY_WALKING_STOP 4
const Uint8 PLAYER_ANIMATION_BODY_FIRING_UP = 5; #define PLAYER_ANIMATION_BODY_FIRING_UP 5
const Uint8 PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT = 6;
const Uint8 PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT = 7; #define PLAYER_ANIMATION_HEAD_WALKING_LEFT 0
const Uint8 PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT = 8; #define PLAYER_ANIMATION_HEAD_FIRING_LEFT 1
const Uint8 PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT = 9; #define PLAYER_ANIMATION_HEAD_WALKING_RIGHT 2
const Uint8 PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT = 10; #define PLAYER_ANIMATION_HEAD_FIRING_RIGHT 3
const Uint8 PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT = 11; #define PLAYER_ANIMATION_HEAD_WALKING_STOP 4
#define PLAYER_ANIMATION_HEAD_FIRING_UP 5
// Variables del jugador // Variables del jugador
const Uint16 PLAYER_INVULNERABLE_TIMER = 200; #define PLAYER_INVULNERABLE_COUNTER 200
#define PLAYER_POWERUP_COUNTER 1500
// Estados del juego // Secciones del programa
const Uint8 GAME_STATE_TITLE = 0; #define PROG_SECTION_LOGO 0
const Uint8 GAME_STATE_PLAYING = 1; #define PROG_SECTION_INTRO 1
const Uint8 GAME_STATE_QUIT = 2; #define PROG_SECTION_TITLE 2
const Uint8 GAME_STATE_GAME_OVER_SCREEN = 3; #define PROG_SECTION_GAME 3
const Uint8 GAME_STATE_INTRO = 4; #define PROG_SECTION_QUIT 4
const Uint8 GAME_STATE_DEMO = 5;
const Uint8 GAME_STATE_INSTRUCTIONS = 6; // Subsecciones
const Uint8 GAME_STATE_LOGO = 7; #define GAME_SECTION_PLAY_1P 0
const Uint8 GAME_STATE_INIT = 8; #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 // Estados de cada elemento que pertenece a un evento
const Uint8 EVENT_WAITING = 1; #define EVENT_WAITING 1
const Uint8 EVENT_RUNNING = 2; #define EVENT_RUNNING 2
const Uint8 EVENT_COMPLETED = 3; #define EVENT_COMPLETED 3
// Cantidad de eventos de la intro // Cantidad de eventos de la intro
const Uint8 INTRO_TOTAL_BITMAPS = 6; #define INTRO_TOTAL_BITMAPS 6
const Uint8 INTRO_TOTAL_TEXTS = 9; #define INTRO_TOTAL_TEXTS 9
const Uint8 INTRO_TOTAL_EVENTS = INTRO_TOTAL_BITMAPS + INTRO_TOTAL_TEXTS; const int INTRO_TOTAL_EVENTS = INTRO_TOTAL_BITMAPS + INTRO_TOTAL_TEXTS;
// Cantidad de eventos de la pantalla de titulo // Cantidad de eventos de la pantalla de titulo
const Uint8 TITLE_TOTAL_EVENTS = 2; #define TITLE_TOTAL_EVENTS 2
// Relaciones de Id con nomnbres // Relaciones de Id con nomnbres
const Uint8 BITMAP0 = 0; #define BITMAP0 0
const Uint8 BITMAP1 = 1; #define BITMAP1 1
const Uint8 BITMAP2 = 2; #define BITMAP2 2
const Uint8 BITMAP3 = 3; #define BITMAP3 3
const Uint8 BITMAP4 = 4; #define BITMAP4 4
const Uint8 BITMAP5 = 5; #define BITMAP5 5
const Uint8 TEXT0 = 6; #define TEXT0 6
const Uint8 TEXT1 = 7; #define TEXT1 7
const Uint8 TEXT2 = 8; #define TEXT2 8
const Uint8 TEXT3 = 9; #define TEXT3 9
const Uint8 TEXT4 = 10; #define TEXT4 10
const Uint8 TEXT5 = 11; #define TEXT5 11
const Uint8 TEXT6 = 12; #define TEXT6 12
const Uint8 TEXT7 = 13; #define TEXT7 13
const Uint8 TEXT8 = 14; #define TEXT8 14
// Anclajes para el marcador de puntos // Anclajes para el marcador de puntos
const int SCORE_WORD_X = (SCREEN_WIDTH / 4) - ((5 * BLOCK) / 2); const int SCORE_WORD_X = (SCREEN_WIDTH / 4) - ((5 * BLOCK) / 2);
@@ -198,85 +209,150 @@ 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_X = (SCREEN_WIDTH / 2) - ((4 * BLOCK) / 2);
const int MULTIPLIER_WORD_Y = SCREEN_HEIGHT - (3 * 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_X = (SCREEN_WIDTH / 2) - ((3 * BLOCK) / 2);
const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2; const int MULTIPLIER_NUMBER_Y = SCREEN_HEIGHT - (2 * BLOCK) + 2;
// Ningun tipo // Ningun tipo
const Uint8 NO_KIND = 0; #define NO_KIND 0
// Tipos de globo // Tipos de globo
const Uint8 BALLOON_1 = 1; #define BALLOON_1 1
const Uint8 BALLOON_2 = 2; #define BALLOON_2 2
const Uint8 BALLOON_3 = 3; #define BALLOON_3 3
const Uint8 BALLOON_4 = 4; #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 // Velocidad del globo
const float BALLON_VELX_POSITIVE = 0.7f; #define BALLOON_VELX_POSITIVE 0.7f
const float BALLON_VELX_NEGATIVE = -0.7f; #define BALLOON_VELX_NEGATIVE -0.7f
// Indice para las animaciones de los globos // Indice para las animaciones de los globos
const Uint8 BALLOON_MOVING_ANIMATION = 0; #define BALLOON_MOVING_ANIMATION 0
const Uint8 BALLOON_POP_ANIMATION = 1; #define BALLOON_POP_ANIMATION 1
const Uint8 BALLOON_BORN_ANIMATION = 2; #define BALLOON_BORN_ANIMATION 2
// Cantidad posible de globos // Cantidad posible de globos
const Uint8 MAX_BALLOONS = 75; #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 // Tipos de bala
const Uint8 BULLET_UP = 1; #define BULLET_UP 1
const Uint8 BULLET_LEFT = 2; #define BULLET_LEFT 2
const Uint8 BULLET_RIGHT = 3; #define BULLET_RIGHT 3
// Cantidad posible de globos // Cantidad posible de globos
const Uint8 MAX_BULLETS = 50; #define MAX_BULLETS 50
// Tipos de objetos // Tipos de objetos
const Uint8 ITEM_POINTS_1_DISK = 1; #define ITEM_POINTS_1_DISK 1
const Uint8 ITEM_POINTS_2_GAVINA = 2; #define ITEM_POINTS_2_GAVINA 2
const Uint8 ITEM_POINTS_3_PACMAR = 3; #define ITEM_POINTS_3_PACMAR 3
const Uint8 ITEM_CLOCK = 4; #define ITEM_CLOCK 4
const Uint8 ITEM_TNT = 5; #define ITEM_COFFEE 5
const Uint8 ITEM_COFFEE = 6; #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 // Cantidad de objetos simultaneos
const Uint8 MAX_ITEMS = 5; #define MAX_ITEMS 10
// Valores para las variables asociadas a los objetos // Valores para las variables asociadas a los objetos
const Uint8 REMAINING_EXPLOSIONS = 3; #define REMAINING_EXPLOSIONS 3
const Uint8 REMAINING_EXPLOSIONS_TIMER = 50; #define REMAINING_EXPLOSIONS_COUNTER 50
const Uint16 TIME_STOPPED_TIMER = 300; #define TIME_STOPPED_COUNTER 300
// Estados de entrada // Estados de entrada
const Uint8 NO_INPUT = 0; #define NO_INPUT 0
const Uint8 INPUT_UP = 1; #define INPUT_FIRE_LEFT 7
const Uint8 INPUT_DOWN = 2; #define INPUT_FIRE_UP 8
const Uint8 INPUT_LEFT = 3; #define INPUT_FIRE_RIGHT 9
const Uint8 INPUT_RIGHT = 4; #define INPUT_PAUSE 10
const Uint8 INPUT_ACCEPT = 5;
const Uint8 INPUT_CANCEL = 6;
const Uint8 INPUT_FIRE_UP = 7;
const Uint8 INPUT_FIRE_LEFT = 8;
const Uint8 INPUT_FIRE_RIGHT = 9;
const Uint8 INPUT_PAUSE = 10;
// Zona muerta del mando analógico // Zona muerta del mando analógico
const int JOYSTICK_DEAD_ZONE = 8000; #define JOYSTICK_DEAD_ZONE 8000
// Tipos de mensajes para el retorno de las funciones // Tipos de mensajes para el retorno de las funciones
const Uint8 MSG_OK = 0; #define MSG_OK 0
const Uint8 MSG_BULLET_OUT = 1; #define MSG_BULLET_OUT 1
// Tipos de texto // Tipos de texto
const Uint8 TEXT_FIXED = 0; #define TEXT_FIXED 0
const Uint8 TEXT_VARIABLE = 1; #define TEXT_VARIABLE 1
// Cantidad de elementos del vector de SmartSprites // Cantidad de elementos del vector de SmartSprites
const Uint8 MAX_SMART_SPRITES = 10; #define MAX_SMART_SPRITES 10
// Cantidad máxima de gotas de café
#define MAX_COFFEE_DROPS 100
// Contadores // Contadores
const Uint16 TITLE_TIMER = 800; #define TITLE_COUNTER 800
const Uint8 STAGE_COUNTER = 200; #define STAGE_COUNTER 200
const Uint16 INSTRUCTIONS_COUNTER = 600; #define INSTRUCTIONS_COUNTER 600
const Uint16 DEATH_COUNTER = 350; #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 #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

3539
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

File diff suppressed because it is too large Load Diff

View File

@@ -1,549 +0,0 @@
#pragma once
#include "ifdefs.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 "text2.h"
#include "menu.h"
#include "const.h"
#include "jail_audio.h"
#include <math.h>
#ifndef GAMEDIRECTOR_H
#define GAMEDIRECTOR_H
// GameDirector
class GameDirector
{
public:
// Constructor
GameDirector();
// Destructor
~GameDirector();
// Iniciador
void init(bool reset);
// Arranca SDL y crea la ventana
bool initSDL();
// Crea el indice de ficheros
void setFileList();
// Comprueba que todos los ficheros existen
bool checkFileList();
// Carga un archivo de imagen en una textura
bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer);
// Carga los recursos necesarios
bool loadMedia(Uint8 section);
// Descrga los recursos necesarios
bool unLoadMedia(Uint8 section);
// Establece el valor de la variable
void setExecutablePath(std::string path);
// Establece el valor de la variable
void setScore(Uint32 score);
// 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 el valor de la variable mStage
void updateStage();
// Actualiza el estado de muerte
void updateDeath();
// Renderiza el fade final cuando se acaba la partida
void renderDeathFade();
// Mueve todos los globos activos
void moveBalloons();
// Pinta en pantalla todos los globos activos
void renderBalloons();
// Devuelve el primer indice no activo del vector de globos
Uint8 getBallonFreeIndex();
// Crea un globo nuevo en el vector de globos
Uint8 createNewBalloon(float x, int y, Uint8 kind, float velx, Uint16 stoppedtimer, LTexture *texture);
// Establece a cero todos los valores del vector de objetos globo
void resetBalloons();
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(Uint8 index);
// Explosiona todos los globos
void popAllBallons();
// 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 checkPlayerBallonCollision();
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision();
// Comprueba la colisión entre las balas y los globos
void checkBulletBallonCollision();
// 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);
// 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);
// 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);
// 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();
// Calcula y establece el valor de amenaza en funcion de los globos activos
void calculateMenaceLevel();
// Obtiene el valor de la variable
Uint8 getMenaceLevel();
// Obtiene el valor de la variable
bool isPlayFieldDrawOnly();
// Establece el valor de la variable
void setPlayFieldDrawOnly(bool state);
// 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 setTimeStoppedTimer(Uint16 value);
// Actualiza y comprueba el valor de la variable
void updateTimeStoppedTimer();
// 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 updateRemainingExplosionsTimer();
// Gestiona el nivel de amenaza
void checkMenaceLevel();
// 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();
// Gestiona la entrada de teclado y mando durante el menu
void checkMenuInput(Menu *menu);
// Obtiene el valor de la variable
Uint8 getGameStatus();
// Establece el valor de la variable
void setGameStatus(Uint8 status);
// Pinta una transición en pantalla
void renderFade(Uint8 index);
// 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();
// Cambia el valor de la variable de modo de pantalla completa
void changeFullScreenMode();
// Actualiza los elementos del menu de opciones
void updateOptionsMenu();
// Agita la pantalla
void shakeScreen();
// Bucle para el logo del juego
void runLogo();
// Bucle para la intro del juego
void runIntro();
// Bucle para el titulo del juego
void runTitle();
// Bucle para el juego
void runGame();
// Bucle para el menu de pausa del juego
void runPausedGame();
// Bucle para la pantalla de instrucciones
void runInstructions();
// Bucle para la pantalla de game over
void runGameOverScreen();
// Dibuja la informacion de debug en pantalla
void renderDebugInfo();
// Activa el modo Demo
void enableDemoMode();
// Desactiva el modo Demo
void disableDemoMode();
// Intercambia el proximo estado del juego despues del titulo
void toogleTitleNextGS();
private:
// La ventana donde dibujamos
SDL_Window *mWindow;
// El renderizador de la ventana
SDL_Renderer *mRenderer;
// Texturas donde dibujar
SDL_Texture *mBackbuffer;
SDL_Texture *mTitleSurface;
SDL_Texture *mInstructionsSurface;
// Manejador para el mando 1
SDL_Joystick *mGameController;
bool mGameControllerFound;
SDL_Haptic *mControllerHaptic;
// Datos del fichero
Uint32 mScoreDataFile[TOTAL_SCORE_DATA];
DemoKeys mDemoDataFile[TOTAL_DEMO_DATA];
// Manejador de eventos
SDL_Event *mEventHandler;
// El jugador
Player *mPlayer;
// Vector con los objetos globo
Balloon *mBalloon[MAX_BALLOONS];
// Vector con los objetos bala
Bullet *mBullet[MAX_BULLETS];
// Vector con los objetos item
Item *mItem[MAX_ITEMS];
// Fondo del juego
Sprite *mGameBackgroundFront;
Sprite *mGameBackgroundSky;
MovingSprite *mGBClouds1;
MovingSprite *mGBClouds1b;
MovingSprite *mGBClouds2;
MovingSprite *mGBClouds2b;
Sprite *mGrass;
// Instrucciones
Sprite *mInstructions;
// Fondo de la pantalla de titulo
Sprite *mTitleTile;
// Ventana visible de la textura de fondo del titulo
SDL_Rect mBackgroundWindow;
// Vector con los valores del seno para 360 grados
double mSen[360];
// Texto
struct text
{
Text *white;
Text *black;
Text *nokia;
};
text mText;
// Variable con lkos menus del juego
struct menu
{
Menu *title; // Menu de la pantalla de título
Menu *pause; // Menú de la pantalla de pausa
Menu *gameOver; // Menú de la pantalla de game over
Menu *options; // Menú de la pantalla de opciones
Menu *active; // Menu activo (de momento para la pantalla del titulo)
};
menu mMenu;
// Notificación GetReady!
SmartSprite *mGetReadyBitmap;
// Dibujos de la intro
SmartSprite *mIntroBitmap[INTRO_TOTAL_BITMAPS];
// Sprites con el titulo del juego para la pantalla de titulo
SmartSprite *mCoffeeBitmap;
SmartSprite *mCrisisBitmap;
AnimatedSprite *mDustSpriteLeft;
AnimatedSprite *mDustSpriteRight;
// Sprites con los puntos de algunos objetos
SmartSprite *m1000Bitmap;
SmartSprite *m2500Bitmap;
SmartSprite *m5000Bitmap;
// Vector para almacenar y gestionar SmartSprites
SmartSprite *mSmartSprite[MAX_SMART_SPRITES];
// Textos de la intro
Text2 *mIntroText[INTRO_TOTAL_TEXTS];
// Vector para coordinar los eventos de la intro
Uint8 mIntroEvents[INTRO_TOTAL_EVENTS];
// Vector para coordinar los eventos de la pantalla de titulo
Uint8 mTitleEvents[TITLE_TOTAL_EVENTS];
// Indicador para el bucle del titulo
Uint8 mTitleStatus;
struct game
{
Uint32 score; // Puntuación actual
Uint32 hiScore; // Puntuación máxima
Uint8 status; // Indicador para el bucle principal
bool paused; // Idica si el juego está en pausa
bool hiScoreAchieved; // Indica si se ha superado la puntuación máxima
Uint8 stage; // Pantalla actual
Uint8 stageCounter; // Contador para el tiempo visible del texto de Stage
double stagePath[STAGE_COUNTER]; // Vector con los puntos Y por donde pasará la etiqueta
Uint16 deathCounter; // Contador para la animación de muerte del jugador
Uint8 deathIndex; // Indice del vector de smartsprites que contiene el sprite del jugador
};
game mGame;
// Contador de ticks para ajustar la velocidad del juego
Uint32 mTicks;
// Velocidad a la que se repite el bucle de juego
Uint8 mTicksSpeed;
// Nivel de amenaza actual
Uint8 mMenaceLevel;
// 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
Uint8 mMenaceLevelThreshold;
// Indica si el bucle de juego avanza o solo pinta
bool mPlayFieldDrawOnly;
// Indica si se va a mostrar la información de debug
bool mDebug;
// Almacena los códigos de teclado correspondientes
Input mKeyboard;
// Buffer para teclas pulsadas
Input mKeyboardBuffer;
// Indica si el tiempo está detenido
bool mTimeStopped;
// Temporizador para llevar la cuenta del tiempo detenido
Uint16 mTimeStoppedTimer;
// Cantidad de explosiones restantes
Uint8 mRemainingExplosions;
// Temporizador para la cantidad de explosiones restantes
Uint16 mRemainingExplosionsTimer;
// Indica si las explosiones estan en marcha
bool mExplosionTime;
// Contador para las instrucciones
Uint16 mInstructionsCounter;
// Temporizador para la pantalla de titulo
Uint16 mTitleTimer;
// Temporizador para el fondo de tiles de la pantalla de titulo
Uint16 mTitleBackgroundTimer;
// Variable para almacenar el tipo de efecto que hará el foindo del titulo
Uint8 mTitleBackgroundMode;
// Indicador para saber si se muestra el menu del titulo o la frase intermitente
bool mTitleMenuVisible;
// Indica si está activo el modo demo
bool mDemo;
// Indica si está activado el modo para grabar la demo
bool mDemoRecording;
// Contador para el modo demo
Uint16 mDemoCounter;
DemoKeys mDemoKeys;
// Indica a que estado pasara el juego cuando acabe el temporizador del titulo
Uint8 mTiteNextGS;
// Contador para el juego
Uint32 mGameCounter;
// Variable para evitar la repetición de teclas en los menus
bool mMenuKeyPressed;
// Variables para el tamaño y modo de la ventana y variables para almacenar el valor si cancelamos en el menu de opciones
Uint32 mFullScreenMode;
Uint32 mFullScreenModePrevious;
Uint8 mWindowSize;
Uint8 mWindowSizePrevious;
// Variables para el logo
struct logo
{
Uint16 counter;
Sprite *sprite;
};
logo mLogo;
// Path del ejecutable
std::string mExecutablePath;
// Recursos
struct resourceBinFile
{
std::string file;
bool loaded;
};
resourceBinFile mBinFile[TOTAL_BINFILE];
struct resourceSound
{
std::string file;
bool loaded;
JA_Sound sound;
};
resourceSound mSound[TOTAL_SOUND];
struct resourceMusic
{
std::string file;
bool loaded;
JA_Music music;
};
resourceMusic mMusic[TOTAL_MUSIC];
struct resourceTexture
{
std::string file;
bool loaded;
LTexture *texture;
};
resourceTexture mTexture[TOTAL_TEXTURE];
};
#endif

View File

@@ -1,9 +1,9 @@
#ifdef _WIN64 #ifdef _WIN64
#include "C:\mingw_dev_lib\include\SDL2\SDL.h" #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 #endif
#ifdef _WIN32 #ifdef _WIN32
#include "C:\mingw_dev_lib\include\SDL2\SDL.h" #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 #endif
#ifdef __APPLE__ #ifdef __APPLE__
@@ -11,5 +11,11 @@
#endif #endif
#ifdef __linux__ #ifdef __linux__
#include "/usr/include/SDL2/SDL.h" #ifdef __MIPSEL__
#endif #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

228
source/instructions.cpp Normal file
View File

@@ -0,0 +1,228 @@
#include "instructions.h"
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
const Uint8 SELF = 0;
// Constructor
Instructions::Instructions(SDL_Renderer *renderer, std::string *fileList, Lang *lang)
{
// Copia los punteros
mRenderer = renderer;
mFileList = fileList;
mLang = lang;
// Reserva memoria para los punteros
mEventHandler = new SDL_Event();
mItemTexture = new LTexture();
mTextTexture = new LTexture();
mSprite = new Sprite();
mText = new Text(mFileList[48], mTextTexture, mRenderer);
// Crea un backbuffer para el renderizador
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
Instructions::~Instructions()
{
mItemTexture->unload();
delete mItemTexture;
mItemTexture = nullptr;
mTextTexture->unload();
delete mTextTexture;
mTextTexture = nullptr;
delete mSprite;
mSprite = nullptr;
delete mEventHandler;
mEventHandler = nullptr;
delete mText;
mText = nullptr;
SDL_DestroyTexture(mBackbuffer);
mBackbuffer = nullptr;
}
// Carga los recursos necesarios para la sección 'Instructions'
bool Instructions::loadMedia()
{
bool success = true;
success &= loadTextureFromFile(mItemTexture, mFileList[34], mRenderer);
success &= loadTextureFromFile(mTextTexture, mFileList[30], mRenderer);
return success;
}
// Inicializa las variables necesarias para la sección 'Instructions'
void Instructions::init()
{
// Carga los recursos
loadMedia();
// Inicializa variables
mSection.name = SELF;
mSprite->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mItemTexture, mRenderer);
mTicks = 0;
mTicksSpeed = 15;
mManualQuit = false;
mCounter = 0;
}
// Bucle para la pantalla de instrucciones
void Instructions::run(Uint8 mode)
{
init();
while (mSection.name == SELF)
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
{
if (mode == INSTRUCTIONS_MODE_AUTO)
{
JA_StopMusic();
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_1;
}
else
mManualQuit = true;
}
}
// Actualiza las variables
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
// Modo automático
if (mode == INSTRUCTIONS_MODE_AUTO)
{
mCounter++;
if (mCounter == INSTRUCTIONS_COUNTER)
{
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_1;
}
}
// Modo manual
else
{
++mCounter %= 60000;
if (mManualQuit)
{
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_3;
}
}
}
// Pinta en pantalla
SDL_Rect window = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
SDL_Rect srcRect = {0, 0, 16, 16};
const color_t orangeColor = {0xFF, 0x7A, 0x00};
const SDL_Rect destRect1 = {60, 88 + (16 * 0), 16, 16}; // Disquito
const SDL_Rect destRect2 = {60, 88 + (16 * 1), 16, 16}; // Gavineixon
const SDL_Rect destRect3 = {60, 88 + (16 * 2), 16, 16}; // Pacmar
const SDL_Rect destRect4 = {60, 88 + (16 * 3), 16, 16}; // Time Stopper
const SDL_Rect destRect5 = {60, 88 + (16 * 4), 16, 16}; // Coffee
// Pinta en el backbuffer el texto y los sprites
SDL_SetRenderTarget(mRenderer, mBackbuffer);
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Escribe el texto
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 8, mLang->getText(11), 1, orangeColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 24, mLang->getText(12), 1, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 34, mLang->getText(13), 1, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 48, mLang->getText(14), 1, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 58, mLang->getText(15), 1, noColor, 1, shdwTxtColor);
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 75, mLang->getText(16), 1, orangeColor, 1, shdwTxtColor);
mText->writeShadowed(84, 92, mLang->getText(17), shdwTxtColor);
mText->writeShadowed(84, 108, mLang->getText(18), shdwTxtColor);
mText->writeShadowed(84, 124, mLang->getText(19), shdwTxtColor);
mText->writeShadowed(84, 140, mLang->getText(20), shdwTxtColor);
mText->writeShadowed(84, 156, mLang->getText(21), shdwTxtColor);
if ((mode == INSTRUCTIONS_MODE_MANUAL) && (mCounter % 50 > 14))
mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, SCREEN_HEIGHT - 12, mLang->getText(22), 1, orangeColor, 1, shdwTxtColor);
// Disquito
mSprite->init(destRect1, mItemTexture, mRenderer);
srcRect.x = 0;
srcRect.y = 16 * (((mCounter + 12) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Gavineixon
mSprite->init(destRect2, mItemTexture, mRenderer);
srcRect.x += srcRect.w;
srcRect.y = 16 * (((mCounter + 9) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Pacmar
mSprite->init(destRect3, mItemTexture, mRenderer);
srcRect.x += srcRect.w;
srcRect.y = 16 * (((mCounter + 6) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Time Stopper
mSprite->init(destRect4, mItemTexture, mRenderer);
srcRect.x += srcRect.w;
srcRect.y = 16 * (((mCounter + 3) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Coffee
mSprite->init(destRect5, mItemTexture, mRenderer);
srcRect.x += (srcRect.w * 2); // Se salta el icono del TNT
srcRect.y = 16 * (((mCounter + 0) / 36) % 2);
mSprite->setSpriteClip(srcRect);
mSprite->render();
// Cambia el destino de renderizado
SDL_SetRenderTarget(mRenderer, nullptr);
// Limpia el renderizador
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Establece la ventana del backbuffer
if (mode == INSTRUCTIONS_MODE_AUTO)
window.y = std::max(8, SCREEN_HEIGHT - mCounter + 100);
else
window.y = 0;
// Copia el backbuffer al renderizador
SDL_RenderCopy(mRenderer, mBackbuffer, NULL, &window);
// Dibuja el renderizador en pantalla
SDL_RenderPresent(mRenderer);
}
}

55
source/instructions.h Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include "ifdefs.h"
#include "utils.h"
#include "const.h"
#include "sprite.h"
#include "text.h"
#include "jail_audio.h"
#ifndef INSTRUCTIONS_H
#define INSTRUCTIONS_H
// Instructions
class Instructions
{
private:
LTexture *mItemTexture; // Textura con los graficos
LTexture *mTextTexture; // Textura con los graficos
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
Sprite *mSprite; // Sprite con la textura de las instrucciones
std::string *mFileList; // Lista de ficheros
Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas
Text *mText; // Objeto para escribir texto
Uint16 mCounter; // Contador
section_t mSection; // Estado del bucle principal para saber si continua o se sale
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
bool mManualQuit; // Indica si se quiere salir del modo manual
// Carga los recursos
bool loadMedia();
// Actualiza las variables
void update();
// Pinta en pantalla
void render();
// Inicializa las variables
void init();
public:
// Constructor
Instructions(SDL_Renderer *renderer, std::string *fileList, Lang *lang);
// Destructor
~Instructions();
// Bucle principal
void run(Uint8 mode);
};
#endif

374
source/intro.cpp Normal file
View File

@@ -0,0 +1,374 @@
#include "intro.h"
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
// Constructor
Intro::Intro(SDL_Renderer *renderer, std::string *fileList, Lang *lang)
{
// Copia los punteros
mRenderer = renderer;
mFileList = fileList;
mLang = lang;
// Reserva memoria para los punteros
mEventHandler = new SDL_Event();
mBitmapTexture = new LTexture();
mTextTexture = new LTexture();
mText = new Text(mFileList[52], mTextTexture, mRenderer);
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
mBitmap[i] = new SmartSprite();
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
mWriter[i] = new Writer(mText);
}
// Destructor
Intro::~Intro()
{
delete mEventHandler;
mEventHandler = nullptr;
mBitmapTexture->unload();
delete mBitmapTexture;
mBitmapTexture = nullptr;
mTextTexture->unload();
delete mTextTexture;
mTextTexture = nullptr;
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
{
delete mBitmap[i];
mBitmap[i] = nullptr;
}
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
{
delete mWriter[i];
mWriter[i] = nullptr;
}
JA_DeleteMusic(mMusic);
}
// Inicializa las variables
void Intro::init()
{
// Carga los recursos
loadMedia();
mSection = {PROG_SECTION_INTRO, 0};
mTicks = 0;
mTicksSpeed = 15;
// Inicializa el vector de eventos de la intro
for (int i = 0; i < INTRO_TOTAL_EVENTS; i++)
mEvents[i] = EVENT_WAITING;
// Inicializa los bitmaps de la intro
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
{
mBitmap[i]->init(mBitmapTexture, mRenderer);
mBitmap[i]->setId(i);
mBitmap[i]->setIntroEvents(&mEvents[0]);
mBitmap[i]->setWidth(128);
mBitmap[i]->setHeight(96);
mBitmap[i]->setEnabled(false);
mBitmap[i]->setEnabledTimer(20);
mBitmap[i]->setDestX(SCREEN_CENTER_X - 64);
mBitmap[i]->setDestY(SCREEN_FIRST_QUARTER_Y - 24);
}
mBitmap[0]->setPosX(-128);
mBitmap[0]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
mBitmap[0]->setVelX(0.0f);
mBitmap[0]->setVelY(0.0f);
mBitmap[0]->setAccelX(0.6f);
mBitmap[0]->setAccelY(0.0f);
mBitmap[0]->setSpriteClip(0, 0, 128, 96);
mBitmap[1]->setPosX(SCREEN_WIDTH);
mBitmap[1]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
mBitmap[1]->setVelX(-1.0f);
mBitmap[1]->setVelY(0.0f);
mBitmap[1]->setAccelX(-0.3f);
mBitmap[1]->setAccelY(0.0f);
mBitmap[1]->setSpriteClip(128, 0, 128, 96);
mBitmap[2]->setPosX(SCREEN_CENTER_X - 64);
mBitmap[2]->setPosY(-96);
mBitmap[2]->setVelX(0.0f);
mBitmap[2]->setVelY(3.0f);
mBitmap[2]->setAccelX(0.1f);
mBitmap[2]->setAccelY(0.3f);
mBitmap[2]->setSpriteClip(0, 96, 128, 96);
mBitmap[2]->setEnabledTimer(250);
mBitmap[3]->setPosX(SCREEN_CENTER_X - 64);
mBitmap[3]->setPosY(SCREEN_HEIGHT);
mBitmap[3]->setVelX(0.0f);
mBitmap[3]->setVelY(-0.7f);
mBitmap[3]->setAccelX(0.0f);
mBitmap[3]->setAccelY(0.0f);
mBitmap[3]->setSpriteClip(128, 96, 128, 96);
mBitmap[4]->setPosX(SCREEN_CENTER_X - 64);
mBitmap[4]->setPosY(-96);
mBitmap[4]->setVelX(0.0f);
mBitmap[4]->setVelY(3.0f);
mBitmap[4]->setAccelX(0.1f);
mBitmap[4]->setAccelY(0.3f);
mBitmap[4]->setSpriteClip(0, 192, 128, 96);
mBitmap[5]->setPosX(SCREEN_WIDTH);
mBitmap[5]->setPosY(SCREEN_FIRST_QUARTER_Y - 24);
mBitmap[5]->setVelX(-0.7f);
mBitmap[5]->setVelY(0.0f);
mBitmap[5]->setAccelX(0.0f);
mBitmap[5]->setAccelY(0.0f);
mBitmap[5]->setSpriteClip(128, 192, 128, 96);
// Inicializa los textos de la intro
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
{
mWriter[i]->init();
mWriter[i]->setId(6 + i);
mWriter[i]->setIntroEvents(&mEvents[0]);
mWriter[i]->setPosX(BLOCK * 0);
mWriter[i]->setPosY(SCREEN_HEIGHT - (BLOCK * 6));
mWriter[i]->setKerning(-1);
mWriter[i]->setEnabled(false);
mWriter[i]->setEnabledTimer(180);
}
// Un dia qualsevol de l'any 2000
mWriter[0]->setCaption(mLang->getText(27));
mWriter[0]->setSpeed(10);
// Tot esta tranquil a la UPV
mWriter[1]->setCaption(mLang->getText(28));
mWriter[1]->setSpeed(10);
// Fins que un desaprensiu...
mWriter[2]->setCaption(mLang->getText(29));
mWriter[2]->setSpeed(15);
// HEY! ME ANE A FERME UN CORTAET...
mWriter[3]->setCaption(mLang->getText(30));
mWriter[3]->setSpeed(10);
// UAAAAAAAAAAAAA!!!
mWriter[4]->setCaption(mLang->getText(31));
mWriter[4]->setSpeed(1);
// Espera un moment...
mWriter[5]->setCaption(mLang->getText(32));
mWriter[5]->setSpeed(20);
// Si resulta que no tinc solt!
mWriter[6]->setCaption(mLang->getText(33));
mWriter[6]->setSpeed(2);
// MERDA DE MAQUINA!
mWriter[7]->setCaption(mLang->getText(34));
mWriter[7]->setSpeed(3);
// Blop... blop... blop...
mWriter[8]->setCaption(mLang->getText(35));
mWriter[8]->setSpeed(20);
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
{
mWriter[i]->center(SCREEN_CENTER_X);
}
}
// Carga los recursos
bool Intro::loadMedia()
{
bool success = true;
// Texturas
success &= loadTextureFromFile(mBitmapTexture, mFileList[33], mRenderer);
success &= loadTextureFromFile(mTextTexture, mFileList[28], mRenderer);
// Musicas
mMusic = JA_LoadMusic(mFileList[3].c_str());
return success;
}
// Bucle principal
section_t Intro::run()
{
init();
// Si la música no está sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
// Reproduce la música
JA_PlayMusic(mMusic, 0);
}
while (mSection.name == PROG_SECTION_INTRO)
{
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
{
JA_StopMusic();
mSection = {PROG_SECTION_TITLE, TITLE_SECTION_1};
}
}
// Actualiza los objetos
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
mBitmap[i]->update();
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
mWriter[i]->update();
// Guión de eventos
// Primera imagen - UPV
if (mEvents[BITMAP0] == EVENT_WAITING)
{
mBitmap[0]->setEnabled(true);
mEvents[BITMAP0] = EVENT_RUNNING;
}
// Primer texto de la primera imagen
if ((mEvents[BITMAP0] == EVENT_COMPLETED) && (mEvents[TEXT0] == EVENT_WAITING))
{
mWriter[0]->setEnabled(true);
mEvents[TEXT0] = EVENT_RUNNING;
}
// Segundo texto de la primera imagen
if ((mEvents[TEXT0] == EVENT_COMPLETED) && (mEvents[TEXT1] == EVENT_WAITING))
{
mWriter[0]->setEnabled(false);
mWriter[1]->setEnabled(true);
mEvents[TEXT1] = EVENT_RUNNING;
}
// Tercer texto de la primera imagen
if ((mEvents[TEXT1] == EVENT_COMPLETED) && (mEvents[TEXT2] == EVENT_WAITING))
{
mWriter[1]->setEnabled(false);
mWriter[2]->setEnabled(true);
mEvents[TEXT2] = EVENT_RUNNING;
}
// Segunda imagen - Máquina
if ((mEvents[TEXT2] == EVENT_COMPLETED) && (mEvents[BITMAP1] == EVENT_WAITING))
{
mBitmap[0]->setEnabled(false);
mWriter[2]->setEnabled(false);
mBitmap[1]->setEnabled(true);
mEvents[BITMAP1] = EVENT_RUNNING;
}
// Primer texto de la segunda imagen
if ((mEvents[BITMAP1] == EVENT_COMPLETED) && (mEvents[TEXT3] == EVENT_WAITING))
{
mWriter[3]->setEnabled(true);
mEvents[TEXT3] = EVENT_RUNNING;
}
// Tercera imagen junto con primer texto - GRITO
if ((mEvents[TEXT3] == EVENT_COMPLETED) && (mEvents[BITMAP2] == EVENT_WAITING) && (mEvents[TEXT4] == EVENT_WAITING))
{
mBitmap[1]->setEnabled(false);
mWriter[3]->setEnabled(false);
mBitmap[2]->setEnabled(true);
mWriter[4]->setEnabled(true);
mEvents[BITMAP2] = EVENT_RUNNING;
mEvents[TEXT4] = EVENT_RUNNING;
}
// Cuarta imagen junto con primer texto - Reflexión
if ((mEvents[TEXT4] == EVENT_COMPLETED) && (mEvents[BITMAP3] == EVENT_WAITING) && (mEvents[TEXT5] == EVENT_WAITING))
{
mBitmap[2]->setEnabled(false);
mWriter[4]->setEnabled(false);
mBitmap[3]->setEnabled(true);
mWriter[5]->setEnabled(true);
mEvents[BITMAP3] = EVENT_RUNNING;
mEvents[TEXT5] = EVENT_RUNNING;
}
// Segundo texto de la cuarta imagen
if ((mEvents[TEXT5] == EVENT_COMPLETED) && (mEvents[TEXT6] == EVENT_WAITING))
{
mWriter[5]->setEnabled(false);
mWriter[6]->setEnabled(true);
mEvents[TEXT6] = EVENT_RUNNING;
}
// Quinta imagen - Patada
if ((mEvents[TEXT6] == EVENT_COMPLETED) && (mEvents[BITMAP4] == EVENT_WAITING))
{
mBitmap[3]->setEnabled(false);
mWriter[6]->setEnabled(false);
mBitmap[4]->setEnabled(true);
mEvents[BITMAP4] = EVENT_RUNNING;
}
// Primer texto de la quinta imagen
if ((mEvents[BITMAP4] == EVENT_COMPLETED) && (mEvents[TEXT7] == EVENT_WAITING))
{
mWriter[7]->setEnabled(true);
mEvents[TEXT7] = EVENT_RUNNING;
}
// Sexta imagen junto con texto - Globos de café
if ((mEvents[TEXT7] == EVENT_COMPLETED) && (mEvents[BITMAP5] == EVENT_WAITING) && (mEvents[TEXT8] == EVENT_WAITING))
{
mBitmap[4]->setEnabled(false);
mWriter[7]->setEnabled(false);
mBitmap[5]->setEnabled(true);
mWriter[8]->setEnabled(true);
mEvents[BITMAP5] = EVENT_RUNNING;
mEvents[TEXT8] = EVENT_RUNNING;
}
// Acaba el último texto
if (mEvents[TEXT8] == EVENT_COMPLETED)
{
mWriter[8]->setEnabled(false);
JA_StopMusic();
mSection = {PROG_SECTION_TITLE, TITLE_SECTION_1};
}
}
// Limpia la pantalla
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 0xFF);
SDL_RenderClear(mRenderer);
// Dibuja los objetos
for (int i = 0; i < INTRO_TOTAL_BITMAPS; i++)
mBitmap[i]->render();
for (int i = 0; i < INTRO_TOTAL_TEXTS; i++)
mWriter[i]->render();
// Actualiza la pantalla
SDL_RenderPresent(mRenderer);
}
return mSection;
}

49
source/intro.h Normal file
View File

@@ -0,0 +1,49 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "smartsprite.h"
#include "writer.h"
#include "jail_audio.h"
#ifndef INTRO_H
#define INTRO_H
// Intro
class Intro
{
private:
LTexture *mBitmapTexture; // Textura con los graficos
LTexture *mTextTexture; // Textura con los caracteres de texto
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Renderer *mRenderer; // El renderizador de la ventana
std::string *mFileList; // Lista de ficheros
Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas
section_t mSection; // Estado del bucle principal para saber si continua o se sale
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
SmartSprite *mBitmap[INTRO_TOTAL_BITMAPS]; // Vector con los sprites inteligentes para los dibujos de la intro
Writer *mWriter[INTRO_TOTAL_TEXTS]; // Textos de la intro
Text *mText; // Textos de la intro
Uint8 mEvents[INTRO_TOTAL_EVENTS]; // Vector para coordinar los eventos de la intro
JA_Music mMusic; // Musica para la intro
public:
// Constructor
Intro(SDL_Renderer *renderer, std::string *fileList, Lang *lang);
// Destructor
~Intro();
// Inicializa las variables
void init();
// Carga los recursos
bool loadMedia();
// Bucle principal
section_t run();
};
#endif

View File

@@ -1,18 +1,19 @@
#include "const.h" #include "const.h"
#include "item.h" #include "item.h"
#include <stdio.h>
// Constructor // Constructor
Item::Item() Item::Item()
{ {
mSprite = new AnimatedSprite(); mSprite = new AnimatedSprite();
init(NO_KIND, 0, 0, nullptr, nullptr); mClass = NO_KIND;
} }
// Destructor // Destructor
Item::~Item() Item::~Item()
{ {
init(NO_KIND, 0, 0, nullptr, nullptr);
delete mSprite; delete mSprite;
mSprite = nullptr;
} }
// Iniciador // Iniciador
@@ -29,6 +30,7 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *
mVelY = -4.0f; mVelY = -4.0f;
mAccelX = 0.0f; mAccelX = 0.0f;
mAccelY = 0.2f; mAccelY = 0.2f;
mFloorCollision = false;
mCollider.r = mWidth / 2; mCollider.r = mWidth / 2;
shiftColliders(); shiftColliders();
@@ -41,6 +43,8 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *
mSprite->setAnimationSpeed(0, 10); mSprite->setAnimationSpeed(0, 10);
mSprite->setAnimationLoop(0, true); mSprite->setAnimationLoop(0, true);
mSprite->setSpriteClip(mSprite->getAnimationClip(0, 0)); mSprite->setSpriteClip(mSprite->getAnimationClip(0, 0));
mSprite->setPosX(mPosX);
mSprite->setPosY(mPosY);
switch (value) switch (value)
{ {
@@ -54,36 +58,57 @@ void Item::init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *
mVelX = 0; mVelX = 0;
mVelY = 0; mVelY = 0;
break; break;
case ITEM_POINTS_1_DISK: case ITEM_POINTS_1_DISK:
mSprite->setAnimationFrames(0, 0, 16 * 0, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 0, 16 * 0, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 0, 16 * 1, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 0, 16 * 1, mWidth, mHeight);
break; break;
case ITEM_POINTS_2_GAVINA: case ITEM_POINTS_2_GAVINA:
mSprite->setAnimationFrames(0, 0, 16 * 1, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 0, 16 * 1, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 1, 16 * 1, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 1, 16 * 1, mWidth, mHeight);
break; break;
case ITEM_POINTS_3_PACMAR: case ITEM_POINTS_3_PACMAR:
mSprite->setAnimationFrames(0, 0, 16 * 2, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 0, 16 * 2, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 2, 16 * 1, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 2, 16 * 1, mWidth, mHeight);
break; break;
case ITEM_CLOCK: case ITEM_CLOCK:
mSprite->setAnimationFrames(0, 0, 16 * 3, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 0, 16 * 3, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 3, 16 * 1, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 3, 16 * 1, mWidth, mHeight);
break; break;
case ITEM_TNT:
mSprite->setAnimationFrames(0, 0, 16 * 4, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 4, 16 * 1, mWidth, mHeight);
break;
case ITEM_COFFEE: case ITEM_COFFEE:
mSprite->setAnimationFrames(0, 0, 16 * 5, 16 * 0, mWidth, mHeight); mSprite->setAnimationFrames(0, 0, 16 * 5, 16 * 0, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 16 * 5, 16 * 1, mWidth, mHeight); mSprite->setAnimationFrames(0, 1, 16 * 5, 16 * 1, mWidth, mHeight);
break; break;
case ITEM_COFFEE_MACHINE:
mWidth = 32;
mHeight = 32;
mPosX = (((int)x + (PLAY_AREA_WIDTH / 2)) % (PLAY_AREA_WIDTH - mWidth - 5)) + 2;
mPosY = PLAY_AREA_TOP - mHeight;
mVelX = 0.0f;
mVelY = -0.1f;
mAccelY = 0.1f;
mSprite->setAnimationNumFrames(0, 4);
mSprite->setAnimationFrames(0, 0, 32 * 0, 16 * 2, mWidth, mHeight);
mSprite->setAnimationFrames(0, 1, 32 * 1, 16 * 2, mWidth, mHeight);
mSprite->setAnimationFrames(0, 2, 32 * 2, 16 * 2, mWidth, mHeight);
mSprite->setAnimationFrames(0, 3, 32 * 3, 16 * 2, mWidth, mHeight);
mSprite->setPosX(mPosX);
mSprite->setPosY(mPosY);
mCollider.r = 10;
shiftColliders();
break;
default: default:
break; break;
} }
} }
// Centra el globo en la posición X // Centra el objeto en la posición X
void Item::allignTo(int x) void Item::allignTo(int x)
{ {
mPosX = float(x - (mWidth / 2)); mPosX = float(x - (mWidth / 2));
@@ -105,7 +130,7 @@ void Item::allignTo(int x)
shiftColliders(); shiftColliders();
} }
// Pinta el globo en la pantalla // Pinta el objeto en la pantalla
void Item::render() void Item::render()
{ {
if (mEnabled) if (mEnabled)
@@ -121,9 +146,11 @@ void Item::render()
} }
} }
// Actualiza la posición y estados del globo // Actualiza la posición y estados del objeto
void Item::move() void Item::move()
{ {
mFloorCollision = false;
// Calcula la nueva posición // Calcula la nueva posición
mPosX += mVelX; mPosX += mVelX;
mPosY += mVelY; mPosY += mVelY;
@@ -142,8 +169,8 @@ void Item::move()
mVelX = -mVelX; mVelX = -mVelX;
} }
// Si se sale por arriba // Si se sale por arriba rebota (excepto la maquina de café)
if (mPosY < PLAY_AREA_TOP) if ((mPosY < PLAY_AREA_TOP) && !(mClass == ITEM_COFFEE_MACHINE))
{ {
// Corrige // Corrige
mPosY = PLAY_AREA_TOP; mPosY = PLAY_AREA_TOP;
@@ -164,6 +191,8 @@ void Item::move()
mAccelX = 0; mAccelX = 0;
mAccelY = 0; mAccelY = 0;
mPosY = PLAY_AREA_BOTTOM - mHeight; mPosY = PLAY_AREA_BOTTOM - mHeight;
if (mClass == ITEM_COFFEE_MACHINE)
mFloorCollision = true;
} }
// Actualiza la posición del sprite // Actualiza la posición del sprite
@@ -195,7 +224,7 @@ void Item::updateTimeToLive()
{ {
if (mTimeToLive > 0) if (mTimeToLive > 0)
{ {
--mTimeToLive; mTimeToLive--;
} }
} }
@@ -203,9 +232,7 @@ void Item::updateTimeToLive()
void Item::checkTimeToLive() void Item::checkTimeToLive()
{ {
if (mTimeToLive == 0) if (mTimeToLive == 0)
{
erase(); erase();
}
} }
// Obtiene del valor de la variable // Obtiene del valor de la variable
@@ -251,7 +278,7 @@ void Item::setEnabled(bool value)
} }
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &Item::getCollider() circle_t &Item::getCollider()
{ {
return mCollider; return mCollider;
} }
@@ -259,6 +286,14 @@ Circle &Item::getCollider()
// Alinea el circulo de colisión con la posición del objeto // Alinea el circulo de colisión con la posición del objeto
void Item::shiftColliders() void Item::shiftColliders()
{ {
mCollider.x = Uint16(mPosX + mCollider.r); //mCollider.x = int(mPosX + mCollider.r);
mCollider.y = Uint16(mPosY + mCollider.r); //mCollider.y = int(mPosY + mCollider.r);
mCollider.x = int(mPosX + (mWidth / 2));
mCollider.y = int(mPosY + (mHeight / 2));
}
// Informa si el objeto ha colisionado con el suelo
bool Item::floorCollision()
{
return mFloorCollision;
} }

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "ifdefs.h" #include "ifdefs.h"
#include "animatedsprite.h" #include "animatedsprite.h"
#include "struct.h" #include "utils.h"
#ifndef ITEM_H #ifndef ITEM_H
#define ITEM_H #define ITEM_H
@@ -9,6 +9,26 @@
// Clase AnimatedSprite // Clase AnimatedSprite
class Item class Item
{ {
private:
float mPosX; // Posición X del objeto
float mPosY; // Posición Y del objeto
Uint8 mWidth; // Ancho del objeto
Uint8 mHeight; // Alto del objeto
float mVelX; // Velocidad en el eje X
float mVelY; // Velocidad en el eje Y
float mAccelX; // Aceleración en el eje X
float mAccelY; // Aceleración en el eje Y
bool mFloorCollision; // Indica si el objeto colisiona con el suelo
AnimatedSprite *mSprite; // Sprite con los graficos del objeto
Uint8 mClass; // Especifica el tipo de objeto que es
bool mEnabled; // Especifica si el objeto está habilitado
circle_t mCollider; // Circulo de colisión del objeto
// Alinea el circulo de colisión con la posición del objeto
void shiftColliders();
public: public:
// Constructor // Constructor
Item(); Item();
@@ -17,7 +37,7 @@ public:
~Item(); ~Item();
// Iniciador // Iniciador
void init(Uint8 value, float x, float y, LTexture* texture, SDL_Renderer *renderer); void init(Uint8 value, float x, float y, LTexture *texture, SDL_Renderer *renderer);
// Centra el objeto en la posición X // Centra el objeto en la posición X
void allignTo(int x); void allignTo(int x);
@@ -62,44 +82,13 @@ public:
void setEnabled(bool value); void setEnabled(bool value);
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &getCollider(); circle_t &getCollider();
// Temporizador con el tiempo que el objeto está presente // Temporizador con el tiempo que el objeto está presente
Uint16 mTimeToLive; Uint16 mTimeToLive;
private: // Informa si el objeto ha colisionado con el suelo
// Posición X,Y del objeto bool floorCollision();
float mPosX;
float mPosY;
// Alto y ancho del objeto
Uint8 mWidth;
Uint8 mHeight;
// Variables para controlar la velocidad del objeto
float mVelX;
float mVelY;
// Aceleración
float mAccelX;
float mAccelY;
// Sprite con los graficos del objeto
AnimatedSprite *mSprite;
// Especifica el tipo de objeto que es
Uint8 mClass;
// Especifica si está habilitado el objeto
bool mEnabled;
// Circulo de colisión del objeto
Circle mCollider;
// Alinea el circulo de colisión con la posición del objeto
void shiftColliders();
}; };
#endif #endif

View File

@@ -1,6 +1,6 @@
#ifndef __MIPSEL__
#include "jail_audio.h" #include "jail_audio.h"
#include "stb_vorbis.c" #include "stb_vorbis.c"
//#include <SDL2/SDL.h>
#define JA_MAX_SIMULTANEOUS_CHANNELS 5 #define JA_MAX_SIMULTANEOUS_CHANNELS 5
@@ -210,4 +210,4 @@ JA_Channel_state JA_GetChannelState(const int channel) {
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID; if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
return channels[channel].state; return channels[channel].state;
} }
#endif

View File

@@ -0,0 +1,106 @@
#ifdef __MIPSEL__
#include "jail_audio.h"
#include "SDL_mixer.h"
struct JA_Sound_t {
Mix_Chunk *mix_chunk;
};
struct JA_Music_t {
Mix_Music* mix_music;
};
JA_Music current_music{NULL};
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
Mix_AllocateChannels(8);
}
JA_Music JA_LoadMusic(const char* filename) {
int chan, samplerate;
JA_Music music = new JA_Music_t();
music->mix_music = Mix_LoadMUS(filename);
return music;
}
void JA_PlayMusic(JA_Music music, const int loop) {
if (current_music == music) return;
if (current_music != NULL) {
Mix_HaltMusic();
}
current_music = music;
Mix_PlayMusic(music->mix_music, loop);
}
void JA_PauseMusic() {
Mix_PauseMusic();
}
void JA_ResumeMusic() {
Mix_ResumeMusic();
}
void JA_StopMusic() {
Mix_HaltMusic();
}
JA_Music_state JA_GetMusicState() {
if (current_music == NULL) return JA_MUSIC_INVALID;
if (Mix_PausedMusic()) {
return JA_MUSIC_PAUSED;
} else if (Mix_PlayingMusic()) {
return JA_MUSIC_PLAYING;
} else {
return JA_MUSIC_STOPPED;
}
}
void JA_DeleteMusic(JA_Music music) {
if (current_music == music) {
Mix_HaltMusic();
current_music = NULL;
}
Mix_FreeMusic(music->mix_music);
delete music;
}
JA_Sound JA_LoadSound(const char* filename) {
JA_Sound sound = new JA_Sound_t();
sound->mix_chunk = Mix_LoadWAV(filename);
return sound;
}
int JA_PlaySound(JA_Sound sound, const int loop) {
int channel = Mix_PlayChannel(-1, sound->mix_chunk, loop);
return channel;
}
void JA_DeleteSound(JA_Sound sound) {
Mix_FreeChunk(sound->mix_chunk);
delete sound;
}
void JA_PauseChannel(const int channel) {
Mix_Pause(channel);
}
void JA_ResumeChannel(const int channel) {
Mix_Resume(channel);
}
void JA_StopChannel(const int channel) {
Mix_HaltChannel(channel);
}
JA_Channel_state JA_GetChannelState(const int channel) {
if (Mix_Paused(channel)) {
return JA_CHANNEL_PAUSED;
} else if (Mix_Playing(channel)) {
return JA_CHANNEL_PLAYING;
} else {
return JA_CHANNEL_FREE;
}
}
#endif

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

146
source/logo.cpp Normal file
View File

@@ -0,0 +1,146 @@
#include "logo.h"
#ifdef __MIPSEL__
#include <sys/stat.h>
#include <dirent.h>
#endif
# define INIT_FADE 100
# define END_LOGO 200
// Constructor
Logo::Logo(SDL_Renderer *renderer, std::string *fileList)
{
// Copia la dirección del renderizador
mRenderer = renderer;
// Copia la dirección del la lista de ficheros
mFileList = fileList;
// Reserva memoria para los punteros
mEventHandler = new SDL_Event();
mTexture = new LTexture();
mSprite = new Sprite();
// Crea un backbuffer para el renderizador
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
Logo::~Logo()
{
mTexture->unload();
delete mTexture;
mTexture = nullptr;
delete mSprite;
mSprite = nullptr;
delete mEventHandler;
mEventHandler = nullptr;
SDL_DestroyTexture(mBackbuffer);
mBackbuffer = nullptr;
}
// Inicializa las variables necesarias para la sección 'Logo'
void Logo::init()
{
// Carga los recursos
loadMedia();
// Inicializa variables
mCounter = 0;
mSection.name = PROG_SECTION_LOGO;
mSection.subsection = 0;
mSprite->init(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mTexture, mRenderer);
mTicks = 0;
mTicksSpeed = 15;
}
// Carga los recursos necesarios para la sección 'Logo'
bool Logo::loadMedia()
{
bool success = true;
success &= loadTextureFromFile(mTexture, mFileList[35], mRenderer);
return success;
}
// Bucle para el logo del juego
section_t Logo::run()
{
init();
const SDL_Rect rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
const int fadeLenght = END_LOGO - INIT_FADE;
while (mSection.name == PROG_SECTION_LOGO)
{
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(mEventHandler) != 0)
{
// Evento de salida de la aplicación
if (mEventHandler->type == SDL_QUIT)
{
mSection.name = PROG_SECTION_QUIT;
break;
}
// Cualquier tecla pulsada
if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
{
mSection.name = PROG_SECTION_TITLE;
mSection.subsection = TITLE_SECTION_1;
}
}
// Limpia el destino
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderClear(mRenderer);
// Dibuja los objetos
mSprite->render();
// Dibuja el fade
if (mCounter >= INIT_FADE)
{
Uint16 alpha = (255 * (mCounter - INIT_FADE)) / fadeLenght;
if (alpha < 256)
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, alpha);
else
SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_RenderFillRect(mRenderer, &rect);
}
// Actualiza la pantalla
SDL_RenderPresent(mRenderer);
// Comprueba si ha terminado el logo
if (SDL_GetTicks() - mTicks > mTicksSpeed)
{
// Actualiza el contador de ticks
mTicks = SDL_GetTicks();
if (mCounter == 0)
{
if (JA_GetMusicState() == JA_MUSIC_PLAYING)
JA_StopMusic();
}
if (mCounter == END_LOGO + 20)
{
mCounter = 0;
mSection.name = PROG_SECTION_INTRO;
mSection.subsection = 0;
}
else
{
mCounter++;
}
}
}
return mSection;
}

44
source/logo.h Normal file
View File

@@ -0,0 +1,44 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "sprite.h"
#include "jail_audio.h"
#ifndef LOGO_H
#define LOGO_H
// Logo
class Logo
{
private:
LTexture *mTexture; // Textura con los graficos
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
Sprite *mSprite; // Sprite con la textura del logo
std::string *mFileList; // Lista de ficheros
Uint16 mCounter; // Contador
section_t mSection; // Estado del bucle principal para saber si continua o se sale
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
public:
// Constructor
Logo(SDL_Renderer *renderer, std::string *fileList);
// Destructor
~Logo();
// Inicializa las variables
void init();
// Carga los recursos
bool loadMedia();
// Bucle principal
section_t run();
};
#endif

View File

@@ -1,5 +1,3 @@
#include <stdio.h>
#include <string>
#include "const.h" #include "const.h"
#include "ltexture.h" #include "ltexture.h"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
@@ -16,7 +14,7 @@ LTexture::LTexture()
LTexture::~LTexture() LTexture::~LTexture()
{ {
// Deallocate // Deallocate
free(); unload();
} }
bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer) bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
@@ -46,14 +44,14 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
} }
// Get rid of preexisting texture // Get rid of preexisting texture
free(); unload();
// The final texture // The final texture
SDL_Texture *newTexture = NULL; SDL_Texture *newTexture = NULL;
// Load image at specified path // Load image at specified path
//SDL_Surface *loadedSurface = IMG_Load(path.c_str()); //SDL_Surface *loadedSurface = IMG_Load(path.c_str());
SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)data, width, height, depth, pitch, pixel_format); SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format);
if (loadedSurface == NULL) if (loadedSurface == NULL)
{ {
printf("Unable to load image %s!\n", path.c_str()); printf("Unable to load image %s!\n", path.c_str());
@@ -61,7 +59,7 @@ bool LTexture::loadFromFile(std::string path, SDL_Renderer *renderer)
else else
{ {
// Color key image // Color key image
SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, COLOR_KEY_R, COLOR_KEY_G, COLOR_KEY_B)); //SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, COLOR_KEY_R, COLOR_KEY_G, COLOR_KEY_B));
// Create texture from surface pixels // Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface); newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
@@ -102,7 +100,7 @@ bool LTexture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_Te
return mTexture != NULL; return mTexture != NULL;
} }
void LTexture::free() void LTexture::unload()
{ {
// Free texture if it exists // Free texture if it exists
if (mTexture != NULL) if (mTexture != NULL)
@@ -132,7 +130,7 @@ void LTexture::setAlpha(Uint8 alpha)
SDL_SetTextureAlphaMod(mTexture, alpha); SDL_SetTextureAlphaMod(mTexture, alpha);
} }
void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, double angle, SDL_Point *center, SDL_RendererFlip flip) 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 // Set rendering space and render to screen
SDL_Rect renderQuad = {x, y, mWidth, mHeight}; SDL_Rect renderQuad = {x, y, mWidth, mHeight};
@@ -144,6 +142,9 @@ void LTexture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, doub
renderQuad.h = clip->h; renderQuad.h = clip->h;
} }
renderQuad.w = renderQuad.w * zoomW;
renderQuad.h = renderQuad.h * zoomH;
// Render to screen // Render to screen
SDL_RenderCopyEx(renderer, mTexture, clip, &renderQuad, angle, center, flip); SDL_RenderCopyEx(renderer, mTexture, clip, &renderQuad, angle, center, flip);
} }

View File

@@ -23,7 +23,7 @@ public:
bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
// Deallocates texture // Deallocates texture
void free(); void unload();
// Set color modulation // Set color modulation
void setColor(Uint8 red, Uint8 green, Uint8 blue); void setColor(Uint8 red, Uint8 green, Uint8 blue);
@@ -35,7 +35,7 @@ public:
void setAlpha(Uint8 alpha); void setAlpha(Uint8 alpha);
// Renders texture at given point // Renders texture at given point
void render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip = NULL, double angle = 0.0, SDL_Point *center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE); 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 // Set self as render target
void setAsRenderTarget(SDL_Renderer *renderer); void setAsRenderTarget(SDL_Renderer *renderer);

View File

@@ -1,10 +1,8 @@
/* /*
This source code copyrighted by JailDesigner (2020) Código fuente creado por JailDesigner (2020)
started on Castalla 15-07-2020. Empezado en Castalla el 15/07/2020.
Using some sample source code from Lazy Foo' Productions
*/
/*Descripción del enfoque utilizado para crear el juego. Descripción del enfoque utilizado para crear el juego.
El programa contine una serie de clases/objetos básicos: la clase sprite 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 permite dibujar partes de un fichero png en pantalla. La clase AnimatedSprite
@@ -17,11 +15,11 @@ A continuación tenemos las clases enfocadas a la lógica del juego, la clase pl
contiene la información del jugador, la clase balloon la de los enemigos y la 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 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 muy simple y sirve para pintar el fondo de la pantalla. Por ultimo, la clase
gamedirector es la que realiza toda la lógica y se encarga de hacer interactuar mDirector es la que realiza toda la lógica y se encarga de hacer interactuar
al resto de objetos entre si. al resto de objetos entre si.
El objeto gamedirector tiene tres estados: titulo, juego y pausa. Segun su estado 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 gamedirector 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 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 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 cerrar la aplicacion, saltar al estado de pausa y para mover al jugador. Recorre
@@ -36,95 +34,24 @@ En los vectores que contienen objetos, se considera activos los objetos que tien
un tipo asociado diferente a NO_KIND un tipo asociado diferente a NO_KIND
*/ */
#include "ifdefs.h" #include "director.h"
#include <time.h>
#include <stdio.h> #include <stdio.h>
#include <string>
#include "const.h"
#include "gamedirector.h"
int main(int argc, char *args[]) int main(int argc, char *args[])
{ {
// Inicia el generador de numeros aleatorios printf("Starting the game...\n\n");
srand(time(nullptr));
// Crea el objeto Director
Director *mDirector = new Director(args[0]);
// Crea el objeto gameDirector // Bucle principal
GameDirector *gameDirector = new GameDirector(); mDirector->run();
// Establece el valor de la variable con el path del ejecutable // Destruye el objeto Director
gameDirector->setExecutablePath(args[0]); delete mDirector;
mDirector = nullptr;
// Inicializa la lista de ficheros printf("\nShutting down the game...\n");
gameDirector->setFileList();
// Comprueba que existen todos los ficheros return 0;
if (!gameDirector->checkFileList())
{
return -1;
}
// Arranca SDL y crea la ventana
if (!gameDirector->initSDL())
{
printf("Failed to initialize!\n");
return -1;
}
else
{
// Carga los recursos
if (!gameDirector->loadMedia(GAME_STATE_INIT))
{
printf("Failed to load media!\n");
}
else
{
// Inicializa el objeto gameDirector
gameDirector->init(false);
printf("Starting the game...\n\n");
// Mientras no se quiera salir del juego
while (!(gameDirector->getGameStatus() == GAME_STATE_QUIT))
{
switch (gameDirector->getGameStatus())
{
case GAME_STATE_LOGO:
gameDirector->loadMedia(GAME_STATE_LOGO);
gameDirector->runLogo();
gameDirector->unLoadMedia(GAME_STATE_LOGO);
break;
case GAME_STATE_INTRO:
gameDirector->loadMedia(GAME_STATE_INTRO);
gameDirector->runIntro();
gameDirector->unLoadMedia(GAME_STATE_INTRO);
break;
case GAME_STATE_TITLE:
gameDirector->loadMedia(GAME_STATE_TITLE);
gameDirector->runTitle();
gameDirector->unLoadMedia(GAME_STATE_TITLE);
break;
case GAME_STATE_PLAYING:
gameDirector->loadMedia(GAME_STATE_PLAYING);
gameDirector->runGame();
gameDirector->unLoadMedia(GAME_STATE_PLAYING);
break;
case GAME_STATE_GAME_OVER_SCREEN:
gameDirector->loadMedia(GAME_STATE_GAME_OVER_SCREEN);
gameDirector->runGameOverScreen();
gameDirector->unLoadMedia(GAME_STATE_GAME_OVER_SCREEN);
break;
case GAME_STATE_INSTRUCTIONS:
gameDirector->loadMedia(GAME_STATE_INSTRUCTIONS);
gameDirector->runInstructions();
gameDirector->unLoadMedia(GAME_STATE_INSTRUCTIONS);
break;
}
}
}
// Libera todos los recursos y cierra SDL
delete gameDirector;
printf("Shutting down the game...\n");
return 0;
}
} }

View File

@@ -1,29 +1,33 @@
#include "ifdefs.h"
#include "const.h" #include "const.h"
#include "text.h"
#include "menu.h" #include "menu.h"
// Constructor // Constructor
Menu::Menu() Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList)
{ {
init("", 0, 0, 0, nullptr, nullptr, nullptr); mRenderer = renderer;
mText = text;
mInput = input;
mFileList = fileList;
} }
Menu::~Menu() Menu::~Menu()
{ {
mRenderer = nullptr; mRenderer = nullptr;
mText = nullptr; mText = nullptr;
mInput = nullptr;
mFileList = nullptr;
} }
// Inicializador // Inicializador
void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text) void Menu::init(std::string name, int x, int y, int backgroundType)
{ {
loadMedia();
// Inicia variables // Inicia variables
mName = name; mName = name;
mSelector.index = 0; mSelector.index = 0;
mTotalItems = 0; mTotalItems = 0;
mItemSelected = MENU_NO_OPTION; mItemSelected = MENU_NO_OPTION;
mVerticalPadding = 1;
mPosX = x; mPosX = x;
mPosY = y; mPosY = y;
mRectBG.rect.x = 0; mRectBG.rect.x = 0;
@@ -33,53 +37,58 @@ void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *te
mRectBG.r = 0; mRectBG.r = 0;
mRectBG.g = 0; mRectBG.g = 0;
mRectBG.b = 0; mRectBG.b = 0;
mSelector.rect.x = 0; mBackgroundType = backgroundType;
mSelector.rect.y = 0; mIsCenteredOnX = false;
mSelector.rect.w = 0; mIsCenteredOnY = false;
mSelector.rect.h = 0; 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.r = 0;
mSelector.g = 0; mSelector.g = 0;
mSelector.b = 0; mSelector.b = 0;
mSelector.a = 255; mSelector.a = 255;
mBackgroundType = backgroundType;
mText = text;
mRenderer = renderer;
mIsCentered = false;
mAreElementsCentered = false;
mCenter = x + ((SCREEN_WIDTH - x) / 2);
mWidestItem = 0;
// Selector
mSelector.origin = 0;
mSelector.target = 0;
mSelector.y = 0;
mSelector.numJumps = 4;
mSelector.despY = 0;
mSelector.moving = false;
// Sprite con los graficos del selector
//mSelectorSprite.setWidth(8);
//mSelectorSprite.setHeight(8);
//mSelectorSprite.setPosX(0);
//mSelectorSprite.setPosY(0);
//mSelectorSprite.setTexture(texture);
//mSelectorSprite.setRenderer(renderer);
//mSelectorSprite.setSpriteClip(0, 0, mSelectorSprite.getWidth(), mSelectorSprite.getHeight());
// Elementos del menu // Elementos del menu
for (int i = 0; i < 10; i++) for (int i = 0; i < MENU_MAX_ITEMS; i++)
{ {
mItem[i].label = ""; mItem[i].label = "";
mItem[i].w = 0; mItem[i].rect = {0, 0, 0, 0};
mItem[i].h = 0;
mItem[i].x = 0;
mItem[i].y = 0;
mItem[i].hPaddingUp = 0;
mItem[i].hPaddingDown = 0; mItem[i].hPaddingDown = 0;
mItem[i].selectable = false;
mItem[i].greyed = false;
mItem[i].linkedDown = false;
mItem[i].linkedUp = false;
} }
}
// Mueve el grafico del selector al elemento seleccionado // Carga los recursos necesarios para la sección 'Title'
//moveSelectorSprite(mSelector.index); 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 // Obtiene el nombre del menu
@@ -91,55 +100,70 @@ std::string Menu::getName()
// Obtiene el valor de la variable // Obtiene el valor de la variable
Uint8 Menu::getItemSelected() Uint8 Menu::getItemSelected()
{ {
return mItemSelected; // Al llamar a esta funcion, se obtiene el valor y se borra
const int temp = mItemSelected;
mItemSelected = MENU_NO_OPTION;
return temp;
} }
// Mueve el grafico del selector al elemento seleccionado
/*void Menu::moveSelectorSprite(int pos)
{
mSelector.rect.y = mItem[pos].y - 1;
}*/
// Actualiza la posicion y el estado del selector // Actualiza la posicion y el estado del selector
void Menu::updateSelector() void Menu::updateSelector()
{ {
if (mSelector.moving) if (mSelector.moving)
{ {
// Calcula el desplazamiento en Y
mSelector.y += mSelector.despY; mSelector.y += mSelector.despY;
if (mSelector.despY > 0) // Va hacia abajo if (mSelector.despY > 0) // Va hacia abajo
{ {
if (mSelector.y > mSelector.target) // Ha llegado al destino if (mSelector.y > mSelector.targetY) // Ha llegado al destino
{ {
mSelector.origin = mSelector.y = mSelector.target; mSelector.originY = mSelector.y = mSelector.targetY;
mSelector.moving = false; mSelector.moving = false;
} }
} }
if (mSelector.despY < 0) // Va hacia abajo if (mSelector.despY < 0) // Va hacia arriba
{ {
if (mSelector.y < mSelector.target) // Ha llegado al destino if (mSelector.y < mSelector.targetY) // Ha llegado al destino
{ {
mSelector.origin = mSelector.y = mSelector.target; mSelector.originY = mSelector.y = mSelector.targetY;
mSelector.moving = false; mSelector.moving = false;
} }
} }
mSelector.rect.y = int(mSelector.y) - 1; mSelector.rect.y = int(mSelector.y);
} }
else else
{ {
mSelector.rect.y = int(mSelector.y) - 1; mSelector.rect.y = int(mSelector.y);
} }
}
// Establece el origen del selector if (mSelector.resizing)
void Menu::setSelectorOrigin(int value) {
{ // Calcula el incremento en H
mSelector.origin = value; mSelector.h += mSelector.incH;
} if (mSelector.incH > 0) // Crece
{
// Establece el destino del selector if (mSelector.h > mSelector.targetH) // Ha llegado al destino
void Menu::setSelectorTarget(int value) {
{ //mSelector.originH = mSelector.targetH = mSelector.rect.h = getSelectorHeight(mSelector.index);
mSelector.target = value; 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 // Coloca el selector en una posición específica
@@ -148,8 +172,12 @@ void Menu::setSelectorPos(Uint8 index)
if (index < mTotalItems) if (index < mTotalItems)
{ {
mSelector.index = index; mSelector.index = index;
mSelector.y = mSelector.origin = mSelector.target = mItem[mSelector.index].y; 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.moving = false;
mSelector.resizing = false;
} }
} }
@@ -159,13 +187,9 @@ Uint16 Menu::getWidestItem()
Uint16 result = 0; Uint16 result = 0;
// Obtenemos la anchura del item mas ancho // Obtenemos la anchura del item mas ancho
for (Uint8 i = 0; i < mTotalItems; i++) for (int i = 0; i < mTotalItems; i++)
{ if (mItem[i].rect.w > result)
if (mItem[i].w > result) result = mItem[i].rect.w;
{
result = mItem[i].w;
}
}
return result; return result;
} }
@@ -175,42 +199,55 @@ void Menu::reset()
{ {
mItemSelected = MENU_NO_OPTION; mItemSelected = MENU_NO_OPTION;
mSelector.index = 0; mSelector.index = 0;
//moveSelectorSprite(mSelector.index); mSelector.originY = mSelector.targetY = mSelector.y = mItem[0].rect.y;
mSelector.origin = mSelector.target = mSelector.y = mItem[0].y; mSelector.originH = mSelector.targetH = mItem[0].rect.h;
mSelector.moving = false; mSelector.moving = false;
} mSelector.resizing = false;
// Deja el menu sin elemento seleccionado
void Menu::deselectItem()
{
mItemSelected = MENU_NO_OPTION;
} }
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño // Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void Menu::reorganize() void Menu::reorganize()
{ {
setRectSize(); setRectSize();
if (mIsCentered) if (mIsCenteredOnX)
centerMenu(mCenter); centerMenuOnX(mCenterX);
if (mAreElementsCentered) if (mIsCenteredOnY)
centerMenuElements(); centerMenuOnY(mCenterY);
if (mAreElementsCenteredOnX)
centerMenuElementsOnX();
} }
// Deja el menu apuntando al siguiente elemento // Deja el menu apuntando al siguiente elemento
bool Menu::increaseSelectorIndex() bool Menu::increaseSelectorIndex()
{ {
bool success = false; bool success = false;
mSelector.y = mSelector.origin = mItem[mSelector.index].y;
// 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)) if (mSelector.index < (mTotalItems - 1))
{ {
mSelector.index++; mSelector.index++;
while ((!mItem[mSelector.index].selectable) && (mSelector.index < (mTotalItems - 1)))
mSelector.index++;
success = true; success = true;
} }
mSelector.target = mItem[mSelector.index].y; if (success)
mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps; { // Establece las coordenadas y altura de destino
mSelector.moving = true; 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; return success;
} }
@@ -218,41 +255,33 @@ bool Menu::increaseSelectorIndex()
bool Menu::decreaseSelectorIndex() bool Menu::decreaseSelectorIndex()
{ {
bool success = false; bool success = false;
mSelector.y = mSelector.origin = mItem[mSelector.index].y;
// 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) if (mSelector.index > 0)
{ {
mSelector.index--; mSelector.index--;
while ((!mItem[mSelector.index].selectable) && (mSelector.index > 0))
mSelector.index--;
success = true; success = true;
} }
mSelector.target = mItem[mSelector.index].y; if (success)
mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps; { // Establece las coordenadas y altura de destino
mSelector.moving = true; mSelector.targetY = mItem[mSelector.index].rect.y;
return success; mSelector.despY = (mSelector.targetY - mSelector.originY) / mSelector.numJumps;
}
// Comprueba la entrada (teclado, gamepad) y actua en consecuencia mSelector.targetH = getSelectorHeight(mSelector.index);
bool Menu::checkInput(Uint8 input) mSelector.incH = (mSelector.targetH - mSelector.originH) / mSelector.numJumps;
{
bool success = false; mSelector.moving = true;
switch (input) if (mSelector.incH != 0)
{ mSelector.resizing = true;
case INPUT_UP:
success = decreaseSelectorIndex();
//moveSelectorSprite(mSelector.index);
break;
case INPUT_DOWN:
success = increaseSelectorIndex();
//moveSelectorSprite(mSelector.index);
break;
case INPUT_ACCEPT:
mItemSelected = mSelector.index;
break;
case INPUT_CANCEL:
mItemSelected = mDefaultActionWhenCancel;
break;
} }
return success; return success;
} }
@@ -273,67 +302,76 @@ void Menu::render()
} }
// Renderiza el rectangulo del selector // 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_SetRenderDrawColor(mRenderer, mSelector.r, mSelector.g, mSelector.b, mSelector.a);
SDL_RenderFillRect(mRenderer, &mSelector.rect); SDL_RenderFillRect(mRenderer, &temp);
// Renderiza el sprite del selector // Renderiza el borde del fondo
//mSelectorSprite.render(); if (mBackgroundType == MENU_BACKGROUND_SOLID)
{
SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, 255);
SDL_RenderDrawRect(mRenderer, &mRectBG.rect);
}
// Renderitza el text // Renderitza el texto
for (Uint8 i = 0; i < mTotalItems; i++) for (int i = 0; i < mTotalItems; i++)
{ {
if (i == mSelector.index) if (i == mSelector.index)
{ {
mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, mSelector.itemR, mSelector.itemG, mSelector.itemB); 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 else if (mItem[i].selectable)
{ {
mText->write(mItem[i].x, mItem[i].y, mItem[i].label, 0); 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 // Establece el rectangulo de fondo del menu y el selector
void Menu::setRectSize() void Menu::setRectSize()
{ {
Uint8 i = 0; mRectBG.rect.w = findWidth() + mText->getCharacterWidth();
mRectBG.rect.w = 0; mRectBG.rect.h = findHeight() + mText->getCharacterWidth();
mRectBG.rect.h = 0;
mSelector.rect.w = 0;
mSelector.rect.h = 0;
// Obtenemos la anchura del item mas ancho y la altura de la suma de alturas de los items // La posición X es la del menú menos medio caracter
for (i = 0; i < mTotalItems; i++) mRectBG.rect.x = mPosX - (mText->getCharacterWidth() / 2);
{
if (mItem[i].w > mRectBG.rect.w)
{
mRectBG.rect.w = mItem[i].w;
}
mRectBG.rect.h += mItem[i].h + mItem[i].hPaddingDown;
}
// La anchura de la cadena más larga, mas un caracter, mas la anchura del sprite del selector // La posición Y es la del menu menos la altura de medio caracter
mRectBG.rect.w += (mText->getSize() * 1); // + mSelectorSprite.getWidth(); mRectBG.rect.y = mPosY - (mText->getCharacterWidth() / 2);
// La altura de la suma de los items mas un caracter y menos un pixel (porque el texto en realidad es de 7 pixeles)
mRectBG.rect.h += (mText->getSize() * 1) - 1;
// La posición X es la del menú menos la anchura del sprite del selector y menos medio caracter
mRectBG.rect.x = mPosX - (mText->getSize() / 2); // - mSelectorSprite.getWidth();
// La posición Y es la del menu menos la altura de medio caracter i el padding
mRectBG.rect.y = mPosY - (mText->getSize() / 2) - mVerticalPadding;
// Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo // Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo
mSelector.rect.h = (mText->getSize() * 1) + 1; setSelectorPos(mSelector.index);
mSelector.rect.w = mRectBG.rect.w;
mSelector.rect.x = mRectBG.rect.x;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Menu::setTotalItems(int num) void Menu::setTotalItems(int num)
{ {
mTotalItems = num; mTotalItems = num;
if (mTotalItems > MENU_MAX_ITEMS)
mTotalItems = MENU_MAX_ITEMS;
} }
// Establece el color del rectangulo de fondo // Establece el color del rectangulo de fondo
@@ -362,89 +400,86 @@ void Menu::setSelectorTextColor(int r, int g, int b)
mSelector.itemB = b; mSelector.itemB = b;
} }
// Centra el menu respecto un punto // Centra el menu respecto un punto en el eje X
void Menu::centerMenu(int value) void Menu::centerMenuOnX(int value)
{ {
mIsCentered = true; mIsCenteredOnX = true;
mCenter = value; mCenterX = value;
// Actualiza el rectangulo de fondo para recalcular las dimensiones // Actualiza el rectangulo de fondo para recalcular las dimensiones
setRectSize(); //setRectSize();
// Obten el acho del menu
mWidestItem = getWidestItem();
// Establece la nueva posición centrada en funcion del elemento más ancho // Establece la nueva posición centrada en funcion del elemento más ancho
mPosX = (value) - (mWidestItem / 2); mPosX = (value) - (findWidth() / 2);
// Reposiciona los elementos del menu // Reposiciona los elementos del menu
for (Uint8 i = 0; i < 10; i++) for (int i = 0; i < MENU_MAX_ITEMS; i++)
{ mItem[i].rect.x = mPosX;
mItem[i].x = mPosX;
}
// Recalcula el rectangulo de fondo // Recalcula el rectangulo de fondo
setRectSize(); setRectSize();
// Recoloca el selector
mSelector.origin = mSelector.target = mSelector.y = mItem[mSelector.index].y;
mSelector.moving = false;
//moveSelectorSprite(mSelector.index);
} }
// Centra los elementos del menu // Centra el menu respecto un punto en el eje Y
void Menu::centerMenuElements() void Menu::centerMenuOnY(int value)
{ {
mAreElementsCentered = true; mIsCenteredOnY = true;
mCenterY = value;
for (Uint8 i = 0; i < mTotalItems; i++) // Actualiza el rectangulo de fondo para recalcular las dimensiones
{ //setRectSize();
//mItem[i].x = (mCenter - ((mText->lenght(mItem[i].label, 0)) / 2));
mItem[i].x = (mCenter - (mItem[i].w / 2));
}
// Mueve el grafico del selector al elemento seleccionado // Establece la nueva posición centrada en funcion del elemento más ancho
//moveSelectorSprite(mSelector.index); 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 // Añade un item al menu
void Menu::addItem(std::string text, const Uint8 hPaddingUp, const Uint8 hPaddingDown) void Menu::addItem(std::string text, Uint8 hPaddingDown, bool selectable, bool greyed, bool linkedDown)
{ {
// Si es el primer item coge la posición y del propio menu // Si es el primer item coge la posición en el eje Y del propio menu
if (mTotalItems == 0) if (mTotalItems == 0)
{ mItem[mTotalItems].rect.y = mPosY;
mItem[mTotalItems].label = text;
mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0);
mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2);
mItem[mTotalItems].x = mPosX;
mItem[mTotalItems].y = mPosY;
mItem[mTotalItems].hPaddingUp = hPaddingUp;
mItem[mTotalItems].hPaddingDown = hPaddingDown;
}
else else
{ // En caso contrario, coge la posición en el eje Y a partir del elemento anterior
// En caso contrario, coge la posición y a partir del elemento anterior mItem[mTotalItems].rect.y = mItem[mTotalItems - 1].rect.y + mItem[mTotalItems - 1].rect.h + mItem[mTotalItems - 1].hPaddingDown;
if (mTotalItems < 10)
{ setItemCaption(mTotalItems, text);
mItem[mTotalItems].label = text; mItem[mTotalItems].rect.x = mPosX;
mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0); mItem[mTotalItems].hPaddingDown = hPaddingDown;
mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2); mItem[mTotalItems].selectable = selectable;
mItem[mTotalItems].x = mPosX; mItem[mTotalItems].greyed = greyed;
mItem[mTotalItems].y = mItem[mTotalItems - 1].y + mItem[mTotalItems - 1].h + mItem[mTotalItems - 1].hPaddingDown; mItem[mTotalItems].linkedDown = linkedDown;
mItem[mTotalItems].hPaddingUp = hPaddingUp; if (mTotalItems > 0)
mItem[mTotalItems].hPaddingDown = hPaddingDown; if (mItem[mTotalItems - 1].linkedDown)
} mItem[mTotalItems].linkedUp = true;
}
setTotalItems(mTotalItems + 1); setTotalItems(mTotalItems + 1);
mCenterX = mPosX + (findWidth() / 2);
//setSelectorPos(0);
reorganize(); reorganize();
setSelectorPos(0);
} }
// Cambia el texto de un item // Cambia el texto de un item
void Menu::setItemCaption(Uint8 index, std::string text) void Menu::setItemCaption(Uint8 index, std::string text)
{ {
mItem[index].label = text; mItem[index].label = text;
mItem[index].w = mText->lenght(mItem[index].label, 0); mItem[index].rect.w = mText->lenght(mItem[index].label);
mItem[index].rect.h = mText->getCharacterWidth();
reorganize(); reorganize();
} }
@@ -453,3 +488,85 @@ void Menu::setDefaultActionWhenCancel(Uint8 item)
{ {
mDefaultActionWhenCancel = 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;
}

View File

@@ -1,69 +1,93 @@
#pragma once #pragma once
#include "ifdefs.h"
#include "sprite.h" #include "sprite.h"
#include "text.h" #include "text.h"
#include "input.h"
#include "jail_audio.h"
#ifndef MENU_H #ifndef MENU_H
#define MENU_H #define MENU_H
#define MENU_MAX_ITEMS 50
// Clase menu // Clase menu
class Menu class Menu
{ {
public:
// Constructor
Menu();
// Destructor
~Menu();
// Inicializador
void init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text);
// 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();
// Deja el menu sin elemento seleccionado
void deselectItem();
// Comprueba la entrada (teclado, gamepad) y actua en consecuencia
bool checkInput(Uint8 input);
// 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
void centerMenu(int value);
// Centra los elementos del menu
void centerMenuElements();
// Añade un item al menu
void addItem(std::string text, const Uint8 hPaddingUp = 0, const Uint8 hPaddingDown = 0);
// 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);
private: 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 // Establece el valor de la variable
void setTotalItems(int num); void setTotalItems(int num);
@@ -79,112 +103,93 @@ private:
// Deja el menu apuntando al elemento anterior // Deja el menu apuntando al elemento anterior
bool decreaseSelectorIndex(); bool decreaseSelectorIndex();
// Mueve el grafico del selector al elemento seleccionado
//void moveSelectorSprite(int pos);
// Actualiza la posicion y el estado del selector // Actualiza la posicion y el estado del selector
void updateSelector(); void updateSelector();
// Establece el origen del selector
void setSelectorOrigin(int value);
// Establece el destino del selector
void setSelectorTarget(int value);
// Coloca el selector en una posición específica
void setSelectorPos(Uint8 index);
// Obtiene la anchura del elemento más ancho del menu // Obtiene la anchura del elemento más ancho del menu
Uint16 getWidestItem(); Uint16 getWidestItem();
// Posicion X/Y del texto del primer elemento del menu // Gestiona la entrada de teclado y mando durante el menu
int mPosX; // En esta posición se pinta la primera letra del primer elemento void checkMenuInput(Menu *menu);
int mPosY;
// Nombre del menu // Calcula el ancho del menu
std::string mName; Uint16 findWidth();
// Numero de items del menu // Calcula el alto del menu
Uint8 mTotalItems; Uint16 findHeight();
// Item del menu que ha sido seleccionado // Recoloca los elementos del menu en el eje Y
Uint8 mItemSelected; void replaceElementsOnY();
// Item del menu seleccionado cuando se cancela el menu // Calcula la altura del selector
Uint8 mDefaultActionWhenCancel; int getSelectorHeight(int value);
// Espacio de separacion entre items public:
Uint8 mVerticalPadding; // Constructor
Menu(SDL_Renderer *renderer, Text *text, Input *input, std::string *fileList);
// Tipo de fondo para el menu // Destructor
Uint8 mBackgroundType; ~Menu();
// Sprite con los graficos del selector // Inicializador
//Sprite mSelectorSprite; void init(std::string name, int x, int y, int backgroundType);
struct rectangle // Obtiene el nombre del menu
{ std::string getName();
SDL_Rect rect;
Uint8 r; // Rojo
Uint8 g; // Verde
Uint8 b; // Azul
Uint8 a; // Transparencia
};
rectangle mRectBG; // Rectangulo de fondo del menu // Obtiene el valor de la variable
Uint8 getItemSelected();
// Estructura para cada elemento del menu // Deja el menu apuntando al primer elemento
struct item void reset();
{
std::string label;
int x;
int y;
Uint8 w;
Uint8 h;
Uint8 hPaddingUp;
Uint8 hPaddingDown;
};
item mItem[10]; // Gestiona la entrada de teclado y mando durante el menu
void checkInput();
// Texto para poder escribir los items del menu // Actualiza la logica del menu
Text *mText; void update();
// Puntero al renderizador de la ventana // Pinta el menu en pantalla
SDL_Renderer *mRenderer; void render();
// Variable para saber si el menu debe estar centrado respecto a un punto // Establece el color del rectangulo de fondo
bool mIsCentered; void setBackgroundColor(int r, int g, int b, int alpha);
// Centro del menu // Establece el color del rectangulo del selector
int mCenter; void setSelectorColor(int r, int g, int b, int alpha);
// Variable para saber si los elementos van centrados // Establece el color del texto del selector
bool mAreElementsCentered; void setSelectorTextColor(int r, int g, int b);
// Anchura del elemento más ancho // Centra el menu respecto a un punto en el eje X
Uint16 mWidestItem; void centerMenuOnX(int value);
struct selector // Centra el menu respecto a un punto en el eje Y
{ void centerMenuOnY(int value);
double origin; // Coordenada de origen
double target; // Coordenada de destino
double y; // Coordenada actual
Uint8 numJumps; // Numero de pasos preestablecido para llegar al destino
double despY; // (target - origin) / numJumps
bool moving; // Indica si el selector está avanzando hacia el destino
Uint8 index; // Elemento del menu que tiene el foco
SDL_Rect rect;
Uint8 r; // Rojo
Uint8 g; // Verde
Uint8 b; // Azul
Uint8 a; // Transparencia
Uint8 itemR; // Rojo
Uint8 itemG; // Verde
Uint8 itemB; // Azul
};
selector mSelector; // 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 #endif

View File

@@ -1,17 +1,38 @@
#include "const.h" #include "const.h"
#include "movingsprite.h" #include "movingsprite.h"
#include <iostream>
// Constructor // Constructor
MovingSprite::MovingSprite() MovingSprite::MovingSprite()
{ {
init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr); clear();
} }
// Destructor // Destructor
MovingSprite::~MovingSprite() MovingSprite::~MovingSprite()
{ {
init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr); 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 // Iniciador
@@ -33,6 +54,21 @@ void MovingSprite::init(float x, float y, int w, int h, float velx, float vely,
setAccelX(accelx); setAccelX(accelx);
setAccelY(accely); 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 // Establece la textura donde están los gráficos para el sprite
setTexture(texture); setTexture(texture);
@@ -46,55 +82,77 @@ void MovingSprite::init(float x, float y, int w, int h, float velx, float vely,
// Mueve el sprite // Mueve el sprite
void MovingSprite::move() void MovingSprite::move()
{ {
mPosX += mVelX; if (mEnabled)
mPosY += mVelY; {
mPosX += mVelX;
mPosY += mVelY;
mVelX += mAccelX; mVelX += mAccelX;
mVelY += mAccelY; mVelY += mAccelY;
}
} }
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void MovingSprite::render() void MovingSprite::render()
{ {
mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip); if (mEnabled)
mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip, mZoomW, mZoomH, mAngle);
} }
// Establece el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getPosX() float MovingSprite::getPosX()
{ {
return mPosX; return mPosX;
} }
// Establece el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getPosY() float MovingSprite::getPosY()
{ {
return mPosY; return mPosY;
} }
// Establece el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getVelX() float MovingSprite::getVelX()
{ {
return mVelX; return mVelX;
} }
// Establece el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getVelY() float MovingSprite::getVelY()
{ {
return mVelY; return mVelY;
} }
// Establece el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getAccelX() float MovingSprite::getAccelX()
{ {
return mAccelX; return mAccelX;
} }
// Establece el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getAccelY() float MovingSprite::getAccelY()
{ {
return mAccelY; 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 // Establece el valor de la variable
void MovingSprite::setPosX(float x) void MovingSprite::setPosX(float x)
{ {
@@ -129,4 +187,100 @@ void MovingSprite::setAccelX(float x)
void MovingSprite::setAccelY(float y) void MovingSprite::setAccelY(float y)
{ {
mAccelY = 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;
} }

View File

@@ -8,6 +8,25 @@
// Clase MovingSprite. Añade posicion y velocidad en punto flotante // Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite 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: public:
// Constructor // Constructor
MovingSprite(); MovingSprite();
@@ -21,57 +40,98 @@ public:
// Mueve el sprite // Mueve el sprite
void move(); 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 // Muestra el sprite por pantalla
void render(); void render();
// Obten el valor de la variable // Obten el valor de la variable
float getPosX(); float getPosX();
// Obten el valor de la variable // Obten el valor de la variable
float getPosY(); float getPosY();
// Obten el valor de la variable // Obten el valor de la variable
float getVelX(); float getVelX();
// Obten el valor de la variable // Obten el valor de la variable
float getVelY(); float getVelY();
// Obten el valor de la variable // Obten el valor de la variable
float getAccelX(); float getAccelX();
// Obten el valor de la variable // Obten el valor de la variable
float getAccelY(); 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 // Establece el valor de la variable
void setPosX(float x); void setPosX(float x);
// Establece el valor de la variable // Establece el valor de la variable
void setPosY(float y); void setPosY(float y);
// Establece el valor de la variable // Establece el valor de la variable
void setVelX(float x); void setVelX(float x);
// Establece el valor de la variable // Establece el valor de la variable
void setVelY(float y); void setVelY(float y);
// Establece el valor de la variable // Establece el valor de la variable
void setAccelX(float x); void setAccelX(float x);
// Establece el valor de la variable // Establece el valor de la variable
void setAccelY(float y); void setAccelY(float y);
private: // Establece el valor de la variable
// Posición void setZoomW(float w);
float mPosX;
float mPosY;
// Velocidad // Establece el valor de la variable
float mVelX; void setZoomH(float h);
float mVelY;
// Aceleración // Establece el valor de la variable
float mAccelX; void setAngle(double a);
float mAccelY;
// 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 #endif

View File

@@ -6,29 +6,42 @@ Player::Player()
{ {
mSpriteLegs = new AnimatedSprite(); mSpriteLegs = new AnimatedSprite();
mSpriteBody = new AnimatedSprite(); mSpriteBody = new AnimatedSprite();
init(0, 0, nullptr, nullptr, nullptr); mSpriteHead = new AnimatedSprite();
} }
// Destructor // Destructor
Player::~Player() Player::~Player()
{ {
init(0, 0, nullptr, nullptr, nullptr);
mSpriteLegs = nullptr;
mSpriteBody = nullptr;
delete mSpriteLegs; delete mSpriteLegs;
mSpriteLegs = nullptr;
delete mSpriteBody; delete mSpriteBody;
mSpriteBody = nullptr;
delete mSpriteHead;
mSpriteHead = nullptr;
} }
// Iniciador // Iniciador
void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer) void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody, LTexture *textureHead, LTexture *textureDead, SDL_Renderer *renderer)
{ {
// Copia punteros
mPlayerDeadTexture = textureDead;
// Inicializa variables de estado // Inicializa variables de estado
mAlive = true; mAlive = true;
mDeathCounter = DEATH_COUNTER;
mDeathIndex = 0;
mStatusWalking = PLAYER_STATUS_WALKING_STOP; mStatusWalking = PLAYER_STATUS_WALKING_STOP;
mStatusFiring = PLAYER_STATUS_FIRING_NO; mStatusFiring = PLAYER_STATUS_FIRING_NO;
mInvulnerable = false; mInvulnerable = false;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER; mInvulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
mPowerUp = false;
mPowerUpCounter = PLAYER_POWERUP_COUNTER;
mPowerUpHeadOffset = 0;
mExtraHit = false; mExtraHit = false;
mCoffees = 0;
mInput = true;
// Establece la altura y el ancho del jugador // Establece la altura y el ancho del jugador
mWidth = 3 * BLOCK; mWidth = 3 * BLOCK;
@@ -51,10 +64,6 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
// Establece la velocidad base // Establece la velocidad base
mBaseSpeed = 1.5; mBaseSpeed = 1.5;
// Establece el numero inicial de vidas
mStartingLives = 3;
mLives = mStartingLives;
// Establece la puntuación inicial // Establece la puntuación inicial
mScore = 0; mScore = 0;
@@ -67,6 +76,7 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
// Inicia el sprite // Inicia el sprite
mSpriteLegs->init(textureLegs, renderer); mSpriteLegs->init(textureLegs, renderer);
mSpriteBody->init(textureBody, renderer); mSpriteBody->init(textureBody, renderer);
mSpriteHead->init(textureHead, renderer);
// Establece el alto y ancho del sprite // Establece el alto y ancho del sprite
mSpriteLegs->setWidth(mWidth); mSpriteLegs->setWidth(mWidth);
@@ -75,6 +85,9 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setWidth(mWidth); mSpriteBody->setWidth(mWidth);
mSpriteBody->setHeight(mHeight); mSpriteBody->setHeight(mHeight);
mSpriteHead->setWidth(mWidth);
mSpriteHead->setHeight(mHeight);
// Establece la posición del sprite // Establece la posición del sprite
mSpriteLegs->setPosX(int(mPosX)); mSpriteLegs->setPosX(int(mPosX));
mSpriteLegs->setPosY(mPosY); mSpriteLegs->setPosY(mPosY);
@@ -82,6 +95,9 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setPosX(int(mPosX)); mSpriteBody->setPosX(int(mPosX));
mSpriteBody->setPosY(mPosY); mSpriteBody->setPosY(mPosY);
mSpriteHead->setPosX(int(mPosX));
mSpriteHead->setPosY(mPosY);
// Inicializa las variables para la animación // Inicializa las variables para la animación
mSpriteLegs->setCurrentFrame(0); mSpriteLegs->setCurrentFrame(0);
mSpriteLegs->setAnimationCounter(0); mSpriteLegs->setAnimationCounter(0);
@@ -89,6 +105,9 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setCurrentFrame(0); mSpriteBody->setCurrentFrame(0);
mSpriteBody->setAnimationCounter(0); mSpriteBody->setAnimationCounter(0);
mSpriteHead->setCurrentFrame(0);
mSpriteHead->setAnimationCounter(0);
// Establece el numero de frames de cada animacion // Establece el numero de frames de cada animacion
mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 4); mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 4);
mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 4); mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 4);
@@ -100,12 +119,13 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 4); mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 4); mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 4); mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 4); mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 4); mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 4); mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 4); mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 4);
mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 4); mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 4);
mSpriteHead->setAnimationNumFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 4);
// Establece la velocidad de cada animación // Establece la velocidad de cada animación
mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_STOP, 10); mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_STOP, 10);
@@ -118,12 +138,13 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 5); mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP, 10); mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP, 10);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP, 5); mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 5); mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 5); mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 5); mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 10); mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 5);
mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 5); mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_WALKING_STOP, 10);
mSpriteHead->setAnimationSpeed(PLAYER_ANIMATION_HEAD_FIRING_UP, 5);
// Establece si la animación se reproduce en bucle // Establece si la animación se reproduce en bucle
mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_STOP, true); mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_STOP, true);
@@ -136,12 +157,13 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_RIGHT, true); mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_RIGHT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP, true); mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP, true); mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, true); mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_WALKING_LEFT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, true); mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_FIRING_LEFT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, true); mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, true); mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, true);
mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, true); mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_WALKING_STOP, true);
mSpriteHead->setAnimationLoop(PLAYER_ANIMATION_HEAD_FIRING_UP, true);
// Establece los frames de cada animación // Establece los frames de cada animación
mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight); mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight);
@@ -189,39 +211,40 @@ void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody,
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 2, mWidth * 2, mHeight * 5, mWidth, mHeight); mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 2, mWidth * 2, mHeight * 5, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 3, mWidth * 3, mHeight * 5, mWidth, mHeight); mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 3, mWidth * 3, mHeight * 5, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 0, mWidth * 0, mHeight * 6, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 1, mWidth * 1, mHeight * 6, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 1, mWidth * 1, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 2, mWidth * 2, mHeight * 6, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 2, mWidth * 2, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 3, mWidth * 3, mHeight * 6, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, 3, mWidth * 3, mHeight * 0, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 0, mWidth * 0, mHeight * 7, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 0, mWidth * 0, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 1, mWidth * 1, mHeight * 7, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 1, mWidth * 1, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 2, mWidth * 2, mHeight * 7, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 2, mWidth * 2, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 3, mWidth * 3, mHeight * 7, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, 3, mWidth * 3, mHeight * 1, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 0, mWidth * 0, mHeight * 8, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 0, mWidth * 0, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 1, mWidth * 1, mHeight * 8, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 1, mWidth * 1, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 2, mWidth * 2, mHeight * 8, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 2, mWidth * 2, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 3, mWidth * 3, mHeight * 8, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, 3, mWidth * 3, mHeight * 2, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 0, mWidth * 0, mHeight * 9, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 0, mWidth * 0, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 1, mWidth * 1, mHeight * 9, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 1, mWidth * 1, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 2, mWidth * 2, mHeight * 9, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 2, mWidth * 2, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 3, mWidth * 3, mHeight * 9, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, 3, mWidth * 3, mHeight * 3, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 0, mWidth * 0, mHeight * 10, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 0, mWidth * 0, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 1, mWidth * 1, mHeight * 10, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 1, mWidth * 1, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 2, mWidth * 2, mHeight * 10, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 2, mWidth * 2, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 3, mWidth * 3, mHeight * 10, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, 3, mWidth * 3, mHeight * 4, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 0, mWidth * 0, mHeight * 11, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 0, mWidth * 0, mHeight * 5, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 1, mWidth * 1, mHeight * 11, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 1, mWidth * 1, mHeight * 5, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 2, mWidth * 2, mHeight * 11, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 2, mWidth * 2, mHeight * 5, mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 3, mWidth * 3, mHeight * 11, mWidth, mHeight); mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, 3, mWidth * 3, mHeight * 5, mWidth, mHeight);
// Selecciona un frame para pintar // Selecciona un frame para pintar
mSpriteLegs->setSpriteClip(mSpriteLegs->getAnimationClip(PLAYER_ANIMATION_LEGS_WALKING_STOP, 0)); mSpriteLegs->setSpriteClip(mSpriteLegs->getAnimationClip(PLAYER_ANIMATION_LEGS_WALKING_STOP, 0));
mSpriteBody->setSpriteClip(mSpriteBody->getAnimationClip(PLAYER_ANIMATION_BODY_WALKING_STOP, 0)); mSpriteBody->setSpriteClip(mSpriteBody->getAnimationClip(PLAYER_ANIMATION_BODY_WALKING_STOP, 0));
mSpriteHead->setSpriteClip(mSpriteHead->getAnimationClip(PLAYER_ANIMATION_HEAD_WALKING_STOP, 0));
} }
// Actua en consecuencia de la entrada recibida // Actua en consecuencia de la entrada recibida
@@ -231,71 +254,29 @@ void Player::setInput(Uint8 input)
{ {
case INPUT_LEFT: case INPUT_LEFT:
mVelX = -mBaseSpeed; mVelX = -mBaseSpeed;
if (mExtraHit) setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
{
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
}
break; break;
case INPUT_RIGHT: case INPUT_RIGHT:
mVelX = mBaseSpeed; mVelX = mBaseSpeed;
if (mExtraHit) setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
{
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT);
}
break; break;
case INPUT_FIRE_UP: case INPUT_FIRE_UP:
if (mExtraHit) setFiringStatus(PLAYER_STATUS_FIRING_UP);
{
setFiringStatus(PLAYER_STATUS_FIRING_UP);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_UP);
}
break; break;
case INPUT_FIRE_LEFT: case INPUT_FIRE_LEFT:
if (mExtraHit) setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
{
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_LEFT);
}
break; break;
case INPUT_FIRE_RIGHT: case INPUT_FIRE_RIGHT:
if (mExtraHit) setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
{
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
}
else
{
setFiringStatus(PLAYER_STATUS_FIRING_RIGHT);
}
break; break;
default: default:
mVelX = 0; mVelX = 0;
if (mExtraHit) setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
{
setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
}
else
{
setWalkingStatus(PLAYER_STATUS_WALKING_STOP);
}
break; break;
} }
} }
@@ -309,7 +290,7 @@ void Player::move()
mPosX += mVelX; mPosX += mVelX;
// Si el jugador abandona el area de juego por los laterales // Si el jugador abandona el area de juego por los laterales
if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT)) if ((mPosX < PLAY_AREA_LEFT - 5) || (mPosX + mWidth > PLAY_AREA_RIGHT + 5))
{ {
// Restaura su posición // Restaura su posición
mPosX -= mVelX; mPosX -= mVelX;
@@ -321,6 +302,9 @@ void Player::move()
mSpriteBody->setPosX(getPosX()); mSpriteBody->setPosX(getPosX());
mSpriteBody->setPosY(mPosY); mSpriteBody->setPosY(mPosY);
mSpriteHead->setPosX(getPosX());
mSpriteHead->setPosY(mPosY);
} }
} }
@@ -331,16 +315,18 @@ void Player::render()
{ {
if (mInvulnerable) if (mInvulnerable)
{ {
if ((mInvulnerableTimer % 10) > 4) if ((mInvulnerableCounter % 10) > 4)
{ {
mSpriteLegs->render(); mSpriteLegs->render();
mSpriteBody->render(); mSpriteBody->render();
mSpriteHead->render();
} }
} }
else else
{ {
mSpriteLegs->render(); mSpriteLegs->render();
mSpriteBody->render(); mSpriteBody->render();
mSpriteHead->render();
} }
} }
} }
@@ -364,12 +350,35 @@ void Player::setFiringStatus(Uint8 status)
{ {
mStatusFiring = status; mStatusFiring = status;
mSpriteBody->setCurrentFrame(0); mSpriteBody->setCurrentFrame(0);
mSpriteHead->setCurrentFrame(0);
} }
} }
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
void Player::setAnimation() void Player::setAnimation()
{ {
// Actualiza los frames de la animación en función del número de cafes
for (int i = 0; i < 4; i++)
{
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, i, mWidth * i, mHeight * (0 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, i, mWidth * i, mHeight * (1 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, i, mWidth * i, mHeight * (2 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, i, mWidth * i, mHeight * (3 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, i, mWidth * i, mHeight * (4 + (6 * mCoffees)), mWidth, mHeight);
mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, i, mWidth * i, mHeight * (5 + (6 * mCoffees)), mWidth, mHeight);
}
// Actualiza los frames de la animación en función de si se tiene el PowerUp
for (int i = 0; i < 4; i++)
{
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_LEFT, i, (mWidth * i) + mPowerUpHeadOffset, mHeight * (0 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_LEFT, i, (mWidth * i) + mPowerUpHeadOffset, mHeight * (1 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_RIGHT, i, (mWidth * i) + mPowerUpHeadOffset, mHeight * (2 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_RIGHT, i, (mWidth * i) + mPowerUpHeadOffset, mHeight * (3 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_WALKING_STOP, i, (mWidth * i) + mPowerUpHeadOffset, mHeight * (4 + (6 * mCoffees)), mWidth, mHeight);
mSpriteHead->setAnimationFrames(PLAYER_ANIMATION_HEAD_FIRING_UP, i, (mWidth * i) + mPowerUpHeadOffset, mHeight * (5 + (6 * mCoffees)), mWidth, mHeight);
}
switch (mStatusWalking) switch (mStatusWalking)
{ {
case PLAYER_STATUS_WALKING_LEFT: case PLAYER_STATUS_WALKING_LEFT:
@@ -377,55 +386,28 @@ void Player::setAnimation()
switch (mStatusFiring) switch (mStatusFiring)
{ {
case PLAYER_STATUS_FIRING_UP: case PLAYER_STATUS_FIRING_UP:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_UP);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
}
break; break;
case PLAYER_STATUS_FIRING_LEFT: case PLAYER_STATUS_FIRING_LEFT:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_LEFT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
}
break; break;
case PLAYER_STATUS_FIRING_RIGHT: case PLAYER_STATUS_FIRING_RIGHT:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_RIGHT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
}
break; break;
case PLAYER_STATUS_FIRING_NO: case PLAYER_STATUS_FIRING_NO:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_LEFT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT);
}
break; break;
default: default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP); mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
break; break;
} }
break; break;
@@ -435,55 +417,28 @@ void Player::setAnimation()
switch (mStatusFiring) switch (mStatusFiring)
{ {
case PLAYER_STATUS_FIRING_UP: case PLAYER_STATUS_FIRING_UP:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_UP);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
}
break; break;
case PLAYER_STATUS_FIRING_LEFT: case PLAYER_STATUS_FIRING_LEFT:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_LEFT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
}
break; break;
case PLAYER_STATUS_FIRING_RIGHT: case PLAYER_STATUS_FIRING_RIGHT:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_RIGHT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
}
break; break;
case PLAYER_STATUS_FIRING_NO: case PLAYER_STATUS_FIRING_NO:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_RIGHT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT);
}
break; break;
default: default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP); mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
break; break;
} }
break; break;
@@ -493,55 +448,28 @@ void Player::setAnimation()
switch (mStatusFiring) switch (mStatusFiring)
{ {
case PLAYER_STATUS_FIRING_UP: case PLAYER_STATUS_FIRING_UP:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_UP);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP);
}
break; break;
case PLAYER_STATUS_FIRING_LEFT: case PLAYER_STATUS_FIRING_LEFT:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_LEFT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT);
}
break; break;
case PLAYER_STATUS_FIRING_RIGHT: case PLAYER_STATUS_FIRING_RIGHT:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_FIRING_RIGHT);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT);
}
break; break;
case PLAYER_STATUS_FIRING_NO: case PLAYER_STATUS_FIRING_NO:
if (mExtraHit) mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
{ mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT);
}
else
{
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
}
break; break;
default: default:
mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP); mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP);
mSpriteHead->animate(PLAYER_ANIMATION_HEAD_WALKING_STOP);
break; break;
} }
break; break;
@@ -601,7 +529,9 @@ void Player::updateCooldown()
{ {
if (mCooldown > 0) if (mCooldown > 0)
{ {
--mCooldown; mCooldown--;
if (mPowerUp)
mCooldown--;
} }
else else
{ {
@@ -616,23 +546,26 @@ void Player::update()
setAnimation(); setAnimation();
shiftColliders(); shiftColliders();
updateCooldown(); updateCooldown();
updateInvulnerableTimer(); updatePowerUpCounter();
updateInvulnerableCounter();
updateDeathCounter();
updatePowerUpHeadOffset();
} }
// Obtiene la puntuación del jugador // Obtiene la puntuación del jugador
int Player::getScore() Uint32 Player::getScore()
{ {
return mScore; return mScore;
} }
// Asigna un valor a la puntuación del jugador // Asigna un valor a la puntuación del jugador
void Player::setScore(int score) void Player::setScore(Uint32 score)
{ {
mScore = score; mScore = score;
} }
// Incrementa la puntuación del jugador // Incrementa la puntuación del jugador
void Player::addScore(int score) void Player::addScore(Uint32 score)
{ {
mScore += score; mScore += score;
} }
@@ -665,18 +598,18 @@ void Player::setScoreMultiplier(float value)
void Player::incScoreMultiplier() void Player::incScoreMultiplier()
{ {
if (mScoreMultiplier < 5.0f) if (mScoreMultiplier < 5.0f)
{
mScoreMultiplier += 0.1f; mScoreMultiplier += 0.1f;
} else
mScoreMultiplier = 5.0f;
} }
// Decrementa el valor de la variable hasta un mínimo // Decrementa el valor de la variable hasta un mínimo
void Player::decScoreMultiplier() void Player::decScoreMultiplier()
{ {
if (mScoreMultiplier > 1.0f) if (mScoreMultiplier > 1.0f)
{
mScoreMultiplier -= 0.1f; mScoreMultiplier -= 0.1f;
} else
mScoreMultiplier = 1.0f;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
@@ -692,28 +625,77 @@ void Player::setInvulnerable(bool value)
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Player::getInvulnerableTimer() Uint16 Player::getInvulnerableCounter()
{ {
return mInvulnerableTimer; return mInvulnerableCounter;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Player::setInvulnerableTimer(Uint16 value) void Player::setInvulnerableCounter(Uint16 value)
{ {
mInvulnerableTimer = value; mInvulnerableCounter = value;
} }
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updateInvulnerableTimer() void Player::updateInvulnerableCounter()
{ {
if (mInvulnerableTimer > 0) if (mInvulnerable)
{ {
--mInvulnerableTimer; if (mInvulnerableCounter > 0)
{
mInvulnerableCounter--;
}
else
{
mInvulnerable = false;
mInvulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
}
}
}
// Actualiza el valor de la variable
void Player::updateDeathCounter()
{
if (!mAlive)
if (mDeathCounter > 0)
mDeathCounter--;
}
// Obtiene el valor de la variable
bool Player::isPowerUp()
{
return mPowerUp;
}
// Establece el valor de la variable
void Player::setPowerUp(bool value)
{
mPowerUp = value;
}
// Obtiene el valor de la variable
Uint16 Player::getPowerUpCounter()
{
return mPowerUpCounter;
}
// Establece el valor de la variable
void Player::setPowerUpCounter(Uint16 value)
{
mPowerUpCounter = value;
}
// Actualiza el valor de la variable
void Player::updatePowerUpCounter()
{
if ((mPowerUpCounter > 0) && (mPowerUp))
{
mPowerUpCounter--;
} }
else else
{ {
mInvulnerable = false; mPowerUp = false;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER; mPowerUpCounter = PLAYER_POWERUP_COUNTER;
} }
} }
@@ -727,18 +709,42 @@ bool Player::hasExtraHit()
void Player::giveExtraHit() void Player::giveExtraHit()
{ {
mExtraHit = true; mExtraHit = true;
mCoffees++;
if (mCoffees > 2)
mCoffees = 2;
} }
// Quita el toque extra al jugador // Quita el toque extra al jugador
void Player::removeExtraHit() void Player::removeExtraHit()
{ {
mExtraHit = false; if (mCoffees > 0)
mCoffees--;
if (mCoffees == 0)
mExtraHit = false;
mInvulnerable = true; mInvulnerable = true;
mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER; mInvulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
}
// Habilita la entrada de ordenes
void Player::enableInput()
{
mInput = true;
}
// Deshabilita la entrada de ordenes
void Player::disableInput()
{
mInput = false;
}
// Devuelve el numero de cafes actuales
Uint8 Player::getCoffees()
{
return mCoffees;
} }
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &Player::getCollider() circle_t &Player::getCollider()
{ {
return mCollider; return mCollider;
} }
@@ -746,6 +752,36 @@ Circle &Player::getCollider()
// Actualiza el circulo de colisión a la posición del jugador // Actualiza el circulo de colisión a la posición del jugador
void Player::shiftColliders() void Player::shiftColliders()
{ {
mCollider.x = Uint16(mPosX + (mWidth / 2)); mCollider.x = int(mPosX + (mWidth / 2));
mCollider.y = mPosY + (mHeight / 2); mCollider.y = int(mPosY + (mHeight / 2));
}
// Obtiene el puntero a la textura con los gráficos de la animación de morir
LTexture *Player::getDeadTexture()
{
return mPlayerDeadTexture;
}
// Obtiene el valor de la variable
Uint16 Player::getDeathCounter()
{
return mDeathCounter;
}
// Actualiza el valor de la variable
void Player::updatePowerUpHeadOffset()
{
if (!mPowerUp)
mPowerUpHeadOffset = 0;
else
{
mPowerUpHeadOffset = 96;
if (mPowerUpCounter < 300)
{
if (mPowerUpCounter % 10 > 4)
mPowerUpHeadOffset = 96;
else
mPowerUpHeadOffset = 0;
}
}
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "struct.h" #include "utils.h"
#include "input.h"
#include "animatedsprite.h" #include "animatedsprite.h"
#ifndef PLAYER_H #ifndef PLAYER_H
@@ -8,7 +9,56 @@
// The player // The player
class Player class Player
{ {
private:
float mPosX; // Posicion en el eje X
int mPosY; // Posicion en el eje Y
Uint8 mWidth; // Anchura
Uint8 mHeight; // Altura
float mVelX; // Cantidad de pixeles a desplazarse en el eje X
int mVelY; // Cantidad de pixeles a desplazarse en el eje Y
float mBaseSpeed; // Velocidad base del jugador
int mCooldown; // Contador durante el cual no puede disparar
Uint32 mScore; // Puntos del jugador
float mScoreMultiplier; // Multiplicador de puntos
Uint8 mStatusWalking; // Estado del jugador
Uint8 mStatusFiring; // Estado del jugador
bool mAlive; // Indica si el jugador está vivo
Uint16 mDeathCounter; // Contador para la animación de morirse
bool mInvulnerable; // Indica si el jugador es invulnerable
Uint16 mInvulnerableCounter; // Contador para la invulnerabilidad
bool mExtraHit; // Indica si el jugador tiene un toque extra
Uint8 mCoffees; // Indica cuantos cafes lleva acumulados
bool mPowerUp; // Indica si el jugador tiene activo el modo PowerUp
Uint8 mPowerUpHeadOffset; // Variable para dibujar la cabeza normal o la del powerup
bool mInput; // Indica si puede recibir ordenes de entrada
AnimatedSprite *mSpriteLegs; // Sprite para dibujar las piernas
AnimatedSprite *mSpriteBody; // Sprite para dibujar el cuerpo
AnimatedSprite *mSpriteHead; // Sprite para dibujar la cabeza
LTexture *mPlayerDeadTexture; // Textura con los gráficos para la animación de muerte
circle_t mCollider; // Circulo de colisión del jugador
void shiftColliders(); // Actualiza el circulo de colisión a la posición del jugador
// Actualiza el valor de la variable
void updateInvulnerableCounter();
// Actualiza el valor de la variable
void updateDeathCounter();
// Actualiza el valor de la variable
void updatePowerUpHeadOffset();
public: public:
Uint8 mDeathIndex; // Apaño rapidito. Indice de SmartSprite donde esta ubicado el sprite de morirse
Uint16 mPowerUpCounter; // Temporizador para el modo PowerUp
// Constructor // Constructor
Player(); Player();
@@ -16,7 +66,7 @@ public:
~Player(); ~Player();
// Iniciador // Iniciador
void init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer); void init(float x, int y, LTexture *textureLegs, LTexture *textureBody, LTexture *textureHead, LTexture *textureDead, SDL_Renderer *renderer);
// Actua en consecuencia de la entrada recibida // Actua en consecuencia de la entrada recibida
void setInput(Uint8 input); void setInput(Uint8 input);
@@ -29,6 +79,8 @@ public:
// Establece el estado del jugador // Establece el estado del jugador
void setWalkingStatus(Uint8 status); void setWalkingStatus(Uint8 status);
// Establece el estado del jugador
void setFiringStatus(Uint8 status); void setFiringStatus(Uint8 status);
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
@@ -59,13 +111,13 @@ public:
void update(); void update();
// Obtiene la puntuación del jugador // Obtiene la puntuación del jugador
int getScore(); Uint32 getScore();
// Asigna un valor a la puntuación del jugador // Asigna un valor a la puntuación del jugador
void setScore(int score); void setScore(Uint32 score);
// Incrementa la puntuación del jugador // Incrementa la puntuación del jugador
void addScore(int score); void addScore(Uint32 score);
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool isAlive(); bool isAlive();
@@ -92,13 +144,25 @@ public:
void setInvulnerable(bool value); void setInvulnerable(bool value);
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool getInvulnerableTimer(); Uint16 getInvulnerableCounter();
// Establece el valor de la variable // Establece el valor de la variable
void setInvulnerableTimer(Uint16 value); void setInvulnerableCounter(Uint16 value);
// Obtiene el valor de la variable
bool isPowerUp();
// Establece el valor de la variable
void setPowerUp(bool value);
// Obtiene el valor de la variable
Uint16 getPowerUpCounter();
// Establece el valor de la variable
void setPowerUpCounter(Uint16 value);
// Actualiza el valor de la variable // Actualiza el valor de la variable
void updateInvulnerableTimer(); void updatePowerUpCounter();
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool hasExtraHit(); bool hasExtraHit();
@@ -109,65 +173,23 @@ public:
// Quita el toque extra al jugador // Quita el toque extra al jugador
void removeExtraHit(); void removeExtraHit();
// Habilita la entrada de ordenes
void enableInput();
// Deshabilita la entrada de ordenes
void disableInput();
// Devuelve el numero de cafes actuales
Uint8 getCoffees();
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &getCollider(); circle_t &getCollider();
private: // Obtiene el puntero a la textura con los gráficos de la animación de morir
// Posición X, Y del jugador LTexture *getDeadTexture();
float mPosX;
int mPosY;
// Altura y anchura del jugador // Obtiene el valor de la variable
Uint8 mWidth; Uint16 getDeathCounter();
Uint8 mHeight;
// Velocidad X, Y del jugador
float mVelX;
int mVelY;
// Velocidad base del jugador
float mBaseSpeed;
// Contador durante el cual no puede disparar
int mCooldown;
// Vidas actuales del jugador
Uint8 mLives;
// Vidas iniciales del jugador
Uint8 mStartingLives;
// Puntos del jugador
Uint32 mScore;
// Multiplicador de puntos
float mScoreMultiplier;
// Estado del jugador
Uint8 mStatusWalking;
Uint8 mStatusFiring;
// Indica si el jugador está vivo
bool mAlive;
// Indica si el jugador es invulnerable
bool mInvulnerable;
// Temporizador para la invulnerabilidad
Uint16 mInvulnerableTimer;
// Indica si el jugador tiene un toque extra
bool mExtraHit;
// Sprite para dibujar al jugador en pantalla
AnimatedSprite *mSpriteLegs;
AnimatedSprite *mSpriteBody;
// Circulo de colisión del jugador
Circle mCollider;
// Actualiza el circulo de colisión a la posición del jugador
void shiftColliders();
}; };
#endif #endif

View File

@@ -4,13 +4,13 @@
// Constructor // Constructor
SmartSprite::SmartSprite() SmartSprite::SmartSprite()
{ {
init(nullptr, nullptr); //init(nullptr, nullptr);
} }
// Destructor // Destructor
SmartSprite::~SmartSprite() SmartSprite::~SmartSprite()
{ {
init(nullptr, nullptr); //init(nullptr, nullptr);
} }
// Inicializador // Inicializador
@@ -38,6 +38,12 @@ void SmartSprite::init(LTexture *texture, SDL_Renderer *renderer)
mDestX = 0; mDestX = 0;
mDestY = 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 // El Id siempre es >=0, por lo tanto si no se le asigna Id se queda en negativo
mId = -1; mId = -1;
@@ -65,13 +71,13 @@ void SmartSprite::setEnabled(bool state)
// Obtiene el valor de la variable // Obtiene el valor de la variable
Uint16 SmartSprite::getEnabledTimer() Uint16 SmartSprite::getEnabledTimer()
{ {
return mEnabledTimer; return mEnabledCounter;
} }
// Establece el valor de la variable // Establece el valor de la variable
void SmartSprite::setEnabledTimer(Uint16 time) void SmartSprite::setEnabledTimer(Uint16 time)
{ {
mEnabledTimer = time; mEnabledCounter = time;
} }
// Establece el valor de la variable // Establece el valor de la variable
@@ -103,7 +109,7 @@ bool SmartSprite::update()
{ {
if (mEnabled) if (mEnabled)
{ {
move(); MovingSprite::update();
// Comprueba si se desplaza en el eje X hacia la derecha // Comprueba si se desplaza en el eje X hacia la derecha
if ((getAccelX() > 0) || ((getAccelX() == 0) && (getVelX() > 0))) if ((getAccelX() > 0) || ((getAccelX() == 0) && (getVelX() > 0)))
@@ -119,7 +125,6 @@ bool SmartSprite::update()
setAccelX(0.0f); setAccelX(0.0f);
} }
} }
// Comprueba si se desplaza en el eje X hacia la izquierda // Comprueba si se desplaza en el eje X hacia la izquierda
else if ((getAccelX() < 0) || ((getAccelX() == 0) && (getVelX() < 0))) else if ((getAccelX() < 0) || ((getAccelX() == 0) && (getVelX() < 0)))
{ {
@@ -178,12 +183,12 @@ bool SmartSprite::update()
if (mIsOnDestination) if (mIsOnDestination)
{ {
// Si el contador es mayor que cero, lo decrementa // Si el contador es mayor que cero, lo decrementa
if (mEnabledTimer > 0) if (mEnabledCounter > 0)
{ {
--mEnabledTimer; --mEnabledCounter;
} }
// Si ha llegado a cero, deshabilita el objeto o manda el aviso en función de si tiene Id // Si ha llegado a cero, deshabilita el objeto o manda el aviso en función de si tiene Id
else if (mEnabledTimer == 0) else if (mEnabledCounter == 0)
{ {
if (mId < 0) if (mId < 0)
{ {

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "struct.h" #include "utils.h"
#include "animatedsprite.h" #include "animatedsprite.h"
#ifndef SMARTSPRITE_H #ifndef SMARTSPRITE_H
@@ -8,6 +8,15 @@
// Clase SmartSprite // Clase SmartSprite
class SmartSprite : public AnimatedSprite 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: public:
// Constructor // Constructor
SmartSprite(); SmartSprite();
@@ -47,7 +56,7 @@ public:
// Actualiza la posición y comprueba si ha llegado a su destino // Actualiza la posición y comprueba si ha llegado a su destino
bool update(); bool update();
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool isOnDestination(); bool isOnDestination();
@@ -59,26 +68,6 @@ public:
// Establece el valor de la variable // Establece el valor de la variable
void setIntroEvents(Uint8 *value); void setIntroEvents(Uint8 *value);
private:
// Indica si esta habilitado
bool mEnabled;
// Contador
Uint16 mEnabledTimer;
// Indica si está en el destino
bool mIsOnDestination;
// Posicion de destino
int mDestX;
int mDestY;
// Identificador
int mId;
// Dirección del array de eventos donde notificar el estado
Uint8 *mIntroEvents;
}; };
#endif #endif

View File

@@ -16,14 +16,14 @@ Sprite::~Sprite()
// Inicializador // Inicializador
void Sprite::init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer) void Sprite::init(int x, int y, int w, int h, 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 // Establece la posición X,Y del sprite
setPosX(x); setPosX(x);
setPosY(y); setPosY(y);
// Establece el alto y el ancho del sprite
setWidth(w);
setHeight(h);
// Establece el puntero al renderizador de la ventana // Establece el puntero al renderizador de la ventana
setRenderer(renderer); setRenderer(renderer);
@@ -32,6 +32,9 @@ void Sprite::init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *r
// Establece el rectangulo de donde coger la imagen // Establece el rectangulo de donde coger la imagen
setSpriteClip(0, 0, w, h); setSpriteClip(0, 0, w, h);
// Habilita el objeto
setEnabled(true);
} }
// Inicializador // Inicializador
@@ -58,7 +61,8 @@ void Sprite::init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer)
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void Sprite::render() void Sprite::render()
{ {
mTexture->render(mRenderer, mPosX, mPosY, &mSpriteClip); if (mEnabled)
mTexture->render(mRenderer, mPosX, mPosY, &mSpriteClip);
} }
// Obten el valor de la variable // Obten el valor de la variable
@@ -146,4 +150,16 @@ void Sprite::setTexture(LTexture *texture)
void Sprite::setRenderer(SDL_Renderer *renderer) void Sprite::setRenderer(SDL_Renderer *renderer)
{ {
mRenderer = 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;
} }

View File

@@ -8,44 +8,56 @@
// Clase sprite // Clase sprite
class 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: public:
// Constructor // Constructor
Sprite(); Sprite();
// Destructor // Destructor
~Sprite(); ~Sprite();
// Inicializador // Inicializador
void init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer); 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); void init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer);
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void render(); void render();
// Obten el valor de la variable // Obten el valor de la variable
int getPosX(); int getPosX();
// Obten el valor de la variable // Obten el valor de la variable
int getPosY(); int getPosY();
// Obten el valor de la variable // Obten el valor de la variable
int getWidth(); int getWidth();
// Obten el valor de la variable // Obten el valor de la variable
int getHeight(); int getHeight();
// Establece el valor de la variable // Establece el valor de la variable
void setPosX(int x); void setPosX(int x);
// Establece el valor de la variable // Establece el valor de la variable
void setPosY(int y); void setPosY(int y);
// Establece el valor de la variable // Establece el valor de la variable
void setWidth(int w); void setWidth(int w);
// Establece el valor de la variable // Establece el valor de la variable
void setHeight(int h); void setHeight(int h);
// Obten el valor de la variable // Obten el valor de la variable
SDL_Rect getSpriteClip(); SDL_Rect getSpriteClip();
@@ -56,32 +68,19 @@ public:
void setSpriteClip(int x, int y, int w, int h); void setSpriteClip(int x, int y, int w, int h);
// Obten el valor de la variable // Obten el valor de la variable
LTexture* getTexture(); LTexture *getTexture();
// Establece el valor de la variable // Establece el valor de la variable
void setTexture(LTexture *texture); void setTexture(LTexture *texture);
// Establece el valor de la variable // Establece el valor de la variable
void setRenderer(SDL_Renderer *renderer); void setRenderer(SDL_Renderer *renderer);
// Establece el valor de la variable
void setEnabled(bool value);
protected: // Comprueba si el objeto está habilitado
// Posición X,Y donde dibujar el sprite bool isEnabled();
int mPosX;
int mPosY;
// Alto y ancho del sprite
Uint16 mWidth;
Uint16 mHeight;
// Puntero al renderizador de la ventana
SDL_Renderer *mRenderer;
// Textura donde estan todos los dibujos del sprite
LTexture *mTexture;
// Rectangulo de la textura que se dibujará en pantalla
SDL_Rect mSpriteClip;
}; };
#endif #endif

View File

@@ -1,42 +0,0 @@
#pragma once
#include "ifdefs.h"
#ifndef STRUCT_H
#define STRUCT_H
// Estructura para definir un circulo
struct Circle
{
Uint16 x;
Uint16 y;
Uint8 r;
};
// Estructura para definir todas las entradas que aceptará el programa
struct Input
{
Uint8 up;
Uint8 down;
Uint8 left;
Uint8 right;
Uint8 escape;
Uint8 pause;
Uint8 fire;
Uint8 fireLeft;
Uint8 fireRight;
Uint8 accept;
Uint8 cancel;
};
// Estructura para mapear el teclado usado en la demo
struct DemoKeys
{
Uint8 left;
Uint8 right;
Uint8 noInput;
Uint8 fire;
Uint8 fireLeft;
Uint8 fireRight;
};
#endif

View File

@@ -1,158 +1,64 @@
#include "const.h" #include "const.h"
#include "text.h" #include "text.h"
#include <iostream>
#include <fstream>
// Constructor // Constructor
Text::Text() Text::Text(std::string file, LTexture *texture, SDL_Renderer *renderer)
{ {
mSprite = new Sprite(); mSprite = new Sprite();
init(nullptr, nullptr, 0, 0); mSprite->setTexture(texture);
mSprite->setRenderer(renderer);
mFile = file;
init();
} }
// Destructor // Destructor
Text::~Text() Text::~Text()
{ {
delete mSprite; delete mSprite;
mSprite = nullptr;
} }
// Inicializador // Inicializador
void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size) void Text::init()
{ {
// Inicializa variables
mType = type;
mSize = size;
// Inicia los valores del sprite que dibuja las letras
mSprite->setWidth(size);
mSprite->setHeight(size);
mSprite->setPosX(0);
mSprite->setPosY(0);
mSprite->setTexture(texture);
mSprite->setRenderer(renderer);
mSprite->setSpriteClip(0, 0, mSprite->getWidth(), mSprite->getHeight());
// Cadena con los caracteres ascii que se van a inicializar
// std::string text = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-/().:#!";
std::string text = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ{\\[]]^_`abcdefghijklmnopqrstuvwxyz";
// Inicializa a cero el vector con las coordenadas // Inicializa a cero el vector con las coordenadas
for (Uint8 i = 0; i < 255; i++) for (int i = 0; i < 128; i++)
{ {
mOffset[i].x = 0; mOffset[i].x = 0;
mOffset[i].y = 0; mOffset[i].y = 0;
mOffset[i].w = 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 // Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (Uint8 i = 0; i < text.length(); ++i) for (int i = 32; i < 128; i++)
{ {
mOffset[int(text[i])].x = ((int(text[i]) - 32) % 15) * mSprite->getWidth(); mOffset[i].x = ((i - 32) % 15) * mBoxWidth;
mOffset[int(text[i])].y = ((int(text[i]) - 32) / 15) * mSprite->getHeight(); mOffset[i].y = ((i - 32) / 15) * mBoxHeight;
if (type == TEXT_FIXED)
{
mOffset[int(text[i])].w = size;
}
}
// Establece el ancho de cada caracter
if (type == TEXT_VARIABLE)
{
mOffset[int(' ')].w = 7;
mOffset[int('-')].w = 6;
mOffset[int('/')].w = 5;
mOffset[int('(')].w = 5;
mOffset[int(')')].w = 5;
mOffset[int('.')].w = 4;
mOffset[int(':')].w = 4;
mOffset[int('#')].w = 7;
mOffset[int('!')].w = 7;
mOffset[int('\'')].w = 3;
mOffset[int('0')].w = 7;
mOffset[int('1')].w = 5;
mOffset[int('2')].w = 7;
mOffset[int('3')].w = 7;
mOffset[int('4')].w = 7;
mOffset[int('5')].w = 7;
mOffset[int('6')].w = 7;
mOffset[int('7')].w = 7;
mOffset[int('8')].w = 7;
mOffset[int('9')].w = 7;
mOffset[int('A')].w = 7;
mOffset[int('B')].w = 7;
mOffset[int('C')].w = 7;
mOffset[int('D')].w = 7;
mOffset[int('E')].w = 7;
mOffset[int('F')].w = 7;
mOffset[int('G')].w = 7;
mOffset[int('H')].w = 7;
mOffset[int('I')].w = 4;
mOffset[int('J')].w = 6;
mOffset[int('K')].w = 8;
mOffset[int('L')].w = 6;
mOffset[int('M')].w = 9;
mOffset[int('N')].w = 8;
mOffset[int('O')].w = 8;
mOffset[int('P')].w = 7;
mOffset[int('Q')].w = 8;
mOffset[int('R')].w = 7;
mOffset[int('S')].w = 6;
mOffset[int('T')].w = 8;
mOffset[int('U')].w = 7;
mOffset[int('V')].w = 8;
mOffset[int('W')].w = 9;
mOffset[int('X')].w = 8;
mOffset[int('Y')].w = 8;
mOffset[int('Z')].w = 7;
mOffset[int('a')].w = 7;
mOffset[int('b')].w = 7;
mOffset[int('c')].w = 6;
mOffset[int('d')].w = 7;
mOffset[int('e')].w = 7;
mOffset[int('f')].w = 5;
mOffset[int('g')].w = 7;
mOffset[int('h')].w = 7;
mOffset[int('i')].w = 4;
mOffset[int('j')].w = 5;
mOffset[int('k')].w = 7;
mOffset[int('l')].w = 4;
mOffset[int('m')].w = 10;
mOffset[int('n')].w = 7;
mOffset[int('o')].w = 7;
mOffset[int('p')].w = 7;
mOffset[int('q')].w = 7;
mOffset[int('r')].w = 6;
mOffset[int('s')].w = 6;
mOffset[int('t')].w = 5;
mOffset[int('u')].w = 7;
mOffset[int('v')].w = 7;
mOffset[int('w')].w = 9;
mOffset[int('x')].w = 7;
mOffset[int('y')].w = 7;
mOffset[int('z')].w = 7;
} }
} }
// Escribe el texto en pantalla // Escribe texto en pantalla
void Text::write(int x, int y, std::string text) void Text::write(int x, int y, std::string text, int kerning, int lenght)
{ {
Uint16 shift = 0; Uint16 shift = 0;
for (Uint8 i = 0; i < text.length(); ++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);
}
}
// Escribe el texto en pantalla con kerning if (lenght == -1)
void Text::write(int x, int y, std::string text, int kerning) lenght = text.length();
{
Uint16 shift = 0; for (int i = 0; i < lenght; ++i)
for (Uint8 i = 0; i < text.length(); ++i)
{ {
mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight());
mSprite->setPosX(x + shift); mSprite->setPosX(x + shift);
@@ -162,83 +68,110 @@ void Text::write(int x, int y, std::string text, int kerning)
} }
} }
// Escribe una cantidad determinada de caracteres del texto en pantalla
void Text::write(int x, int y, std::string text, int kerning, Uint8 lenght)
{
Uint16 shift = 0;
for (Uint8 i = 0; i < lenght; ++i)
{
if (text[i] == '*')
{
shift = 0;
y += mSize;
}
else
{
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 // Escribe el texto con colores
void Text::writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B) void Text::writeColored(int x, int y, std::string text, color_t color, int kerning, int lenght)
{ {
mSprite->getTexture()->setColor(R, G, B); mSprite->getTexture()->setColor(color.r, color.g, color.b);
write(x, y, text); write(x, y, text, kerning, lenght);
mSprite->getTexture()->setColor(255, 255, 255); mSprite->getTexture()->setColor(255, 255, 255);
} }
// Escribe el texto centrado en un punto x y con kerning // Escribe el texto con sombra
void Text::writeCentered(int x, int y, std::string text, int kerning) void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, int kerning, int lenght)
{ {
// Uint16 lenght = Text::lenght(text, kerning); mSprite->getTexture()->setColor(color.r, color.g, color.b);
x = x - (Text::lenght(text, kerning) / 2); write(x + shadowDistance, y + shadowDistance, text, kerning, lenght);
Uint16 shift = 0; mSprite->getTexture()->setColor(255, 255, 255);
for (Uint8 i = 0; i < text.length(); ++i) 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)
{ {
mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
mSprite->setPosX(x + shift); writeColored(x - shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
mSprite->setPosY(y); writeColored(x + shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
mSprite->render(); writeColored(x - shadowDistance, y - shadowDistance, text, shadowColor, kerning, lenght);
shift += (mOffset[int(text[i])].w + kerning);
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 // Obtiene la longitud en pixels de una cadena
Uint16 Text::lenght(std::string text, int kerning) Uint16 Text::lenght(std::string text, int kerning)
{ {
Uint16 shift = 0; Uint16 shift = 0;
for (Uint8 i = 0; i < text.length(); ++i)
{ for (int i = 0; i < text.length(); ++i)
shift += (mOffset[int(text[i])].w + kerning); shift += (mOffset[int(text[i])].w + kerning);
}
return shift; return shift;
} }
// Obtiene el valor de la variable // Inicializa el vector de offsets desde un fichero
Uint8 Text::getType() void Text::initOffsetFromFile()
{ {
return mType; 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++;
};
}
} }
// Establece el valor de la variable // Devuelve el valor de la variable
void Text::setType(Uint8 type) Uint8 Text::getCharacterWidth()
{ {
mType = type; return mBoxWidth;
}
// Obtiene el valor de la variable
Uint8 Text::getSize()
{
return mSize;
}
// Establece el valor de la variable
void Text::setSize(Uint8 size)
{
mSize = size;
} }

View File

@@ -1,66 +1,66 @@
#pragma once #pragma once
#include "sprite.h" #include "sprite.h"
#include "utils.h"
#ifndef TEXT_H #ifndef TEXT_H
#define 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 // Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text class Text
{ {
public:
// Constructor
Text();
// Destructor
~Text();
// Inicializador
void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size);
// Escribe el texto en pantalla
void write(int x, int y, std::string text);
void write(int x, int y, std::string text, int kerning);
void write(int x, int y, std::string text, int kerning, Uint8 lenght);
// Escribe el texto con colores
void writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B);
// Escribe el texto centrado en un punto x y con kerning
void writeCentered(int x, int y, std::string text, int kerning);
// Obtiene la longitud en pixels de una cadena
Uint16 lenght(std::string text, int kerning);
// Obtiene el valor de la variable
Uint8 getType();
// Establece el valor de la variable
void setType(Uint8 type);
// Obtiene el valor de la variable
Uint8 getSize();
// Establece el valor de la variable
void setSize(Uint8 size);
private: private:
// Objeto con los graficos para el texto Sprite *mSprite; // Objeto con los graficos para el texto
Sprite *mSprite;
// Coordenadas dentro del PNG para cada código ascii y su anchura
struct Offset struct Offset
{ {
int x; int x;
int y; int y;
Uint8 w; Uint8 w;
}; };
Offset mOffset[128]; // Vector con las posiciones y ancho de cada letra
// Vector con las posiciones y ancho de cada letra Uint8 mBoxWidth; // Anchura de la caja de cada caracter en el png
Offset mOffset[255]; Uint8 mBoxHeight; // Altura de la caja de cada caracter en el png
std::string mFile; // Fichero con los descriptores de la fuente
// Indica si el texto es de anchura fija o variable // Inicializa el vector de offsets desde un fichero
Uint8 mType; void initOffsetFromFile();
Uint8 mSize;
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 #endif

1030
source/title.cpp Normal file

File diff suppressed because it is too large Load Diff

119
source/title.h Normal file
View File

@@ -0,0 +1,119 @@
#pragma once
#include "ifdefs.h"
#include "const.h"
#include "utils.h"
#include "sprite.h"
#include "movingsprite.h"
#include "smartsprite.h"
#include "item.h"
#include "text.h"
#include "menu.h"
#include "fade.h"
#include "input.h"
#include "instructions.h"
#include "game.h"
#include "jail_audio.h"
#ifndef TITLE_H
#define TITLE_H
// Title
class Title
{
private:
SDL_Window *mWindow; // Ventana de la aplicación
AnimatedSprite *mDustBitmapL; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
AnimatedSprite *mDustBitmapR; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
bool mMenuVisible; // Indicador para saber si se muestra el menu del titulo o la frase intermitente
float mSin[360]; // Vector con los valores del seno precalculados
JA_Music mMusic; // Musica para el titulo
JA_Sound mSound; // Sonido con el impacto del título
LTexture *mItemsTexture; // Textura con los gráficos de los items para las instrucciones
LTexture *mTitleTexture; // Textura con los graficos para el titulo
LTexture *mTextTexture; // Textura con los gráficos para el texto
LTexture *mTextTexture2; // Textura con los gráficos para el texto
SDL_Event *mEventHandler; // Manejador de eventos
SDL_Rect mBackgroundWindow; // Ventana visible para la textura de fondo del titulo
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackground; // Textura dibujar el fondo del titulo
SmartSprite *mCoffeeBitmap; // Sprite con la palabra COFFEE para la pantalla de titulo
SmartSprite *mCrisisBitmap; // Sprite con la palabra CRISIS para la pantalla de titulo
Sprite *mTile; // Sprite para dibujar el fondo de pantalla del título
Sprite *mGradient; // Sprite para dibujar el degradado del titulo
std::string *mFileList; // Lista de ficheros
Lang *mLang; // Objeto para gestionar los textos en diferentes idiomas
Uint16 mBackgroundCounter; // Temporizador para el fondo de tiles de la pantalla de titulo
Uint16 mCounter; // Temporizador para la pantalla de titulo
Uint32 mTicks; // Contador de ticks para ajustar la velocidad del programa
Uint8 mBackgroundMode; // Variable para almacenar el tipo de efecto que hará el fondo de la pantalla de titulo
Uint8 mEvents[TITLE_TOTAL_EVENTS]; // Vector para coordinar los eventos de la pantalla de titulo
bool mDemo; // Indica si el modo demo estará activo
section_t mSection; // Indicador para el bucle del titulo
section_t mNextSection; // Indica cual es la siguiente sección a cargar cuando termine el contador del titulo
Uint8 mTicksSpeed; // Velocidad a la que se repiten los bucles del programa
Text *mText; // Objeto de texto para poder escribir textos en pantalla
Text *mText2; // Objeto de texto para poder escribir textos en pantalla
Fade *mFade; // Objeto para realizar fundidos en pantalla
Uint8 mPostFade; // Opción a realizar cuando termina el fundido
Input *mInput; // Objeto para leer las entradas de teclado o mando
Instructions *mInstructions; // Objeto para la sección de las instrucciones
Game *mDemoGame; // Objeto para lanzar la demo del juego
struct menu_t
{
Menu *title; // Menu de la pantalla de título
Menu *options; // Menú de la pantalla de opciones
Menu *active; // Menu activo (de momento para la pantalla del titulo)
bool keyPressed; // Variable para evitar la repetición de teclas en los menus
};
menu_t mMenu; // Variable con todos los objetos menus y sus variables
struct options_t *mOptions; // Variable con todas las variables de las opciones del programa
options_t mOptionsPrevious; // Variable de respaldo para las opciones
std::vector<input_t> mAvailableInputDevices; // Vector con todos los metodos de control disponibles
int mDeviceIndex[2]; // Indice para el jugador [i] del vector de dispositivos de entrada disponibles
// Carga los recursos necesarios para la sección 'Title'
bool loadMedia();
// Cambia el valor de la variable de modo de pantalla completa
void switchFullScreenModeVar();
// Actualiza los elementos de los menus
void updateMenuLabels();
// Aplica las opciones de menu seleccionadas
void applyOptions();
// Ejecuta la parte donde se muestran las instrucciones
void runInstructions(Uint8 mode);
// Ejecuta el juego en modo demo
void runDemoGame();
// Modifica las opciones para los controles de los jugadores
bool updatePlayerInputs(int numPlayer);
// Crea el mosaico de fondo del titulo
void createTiledBackground();
// Comprueba cuantos mandos hay conectados para gestionar el menu de opciones
void checkInputDevices();
public:
// Constructor
Title(SDL_Window *window, SDL_Renderer *renderer, Input *input, std::string *fileList, options_t *options, Lang *lang);
// Destructor
~Title();
// Inicializa las variables necesarias para la sección 'Title'
void init(bool demo = true, Uint8 subsection = TITLE_SECTION_1);
// Bucle para el titulo del juego
section_t run(Uint8 subsection = TITLE_SECTION_1);
};
#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

Some files were not shown because too many files have changed in this diff Show More