50 Commits
v0.3 ... v0.4

Author SHA1 Message Date
2929b1efb9 Actualizado el numero de versión 2022-08-28 07:51:46 +02:00
d937e5578f Retocado el menu del titulo 2022-08-28 07:50:08 +02:00
b6cbc65a2a corregido un bug en la caída del personaje 2022-08-28 07:30:13 +02:00
bc464206c1 Retocado el mapa 2022-08-27 23:26:48 +02:00
7c7e0c01e2 Añadidos enemigos tipo path 2022-08-27 22:53:06 +02:00
3f232c6c25 Debugando la clase enemy 2022-08-27 21:02:51 +02:00
8a79737520 Implementando el enemy engine 2022-08-27 18:42:59 +02:00
0e71bc97b3 Modificados algunos mapas 2022-08-27 17:29:56 +02:00
17b10a8fef Ya recuerda los items recogidos 2022-08-27 16:39:44 +02:00
ce33b4e10c Añadida la clase item_tracker 2022-08-27 16:08:22 +02:00
e94e750ca1 Modificados algunos printf 2022-08-27 14:35:51 +02:00
11a8ea8c24 Modificados algunos sonidos 2022-08-27 14:30:37 +02:00
58b238fa45 Ya coge los diamantes, aunque no los recuerda 2022-08-27 14:15:46 +02:00
2e102160e6 Plataformas moviles completadas 2022-08-27 09:36:43 +02:00
43c10d335b Ya se engancha verticalmente en las plataformas moviles 2022-08-27 07:55:06 +02:00
6b7c49aecd Trabajando en las colisiones con plataformas moviles 2022-08-26 21:25:51 +02:00
dda1e049c6 Ya detecta las plataformas móviles bajo los pies 2022-08-26 20:41:48 +02:00
5ff62a6950 Retocados nombres de variables antiguos 2022-08-26 19:53:19 +02:00
a4000d25db Empezando con los actores y polimorfismo. Ya pinta la plataforma movil 2022-08-26 13:36:31 +02:00
aea71599ff Creando subclases de actors 2022-08-26 07:24:22 +02:00
6b2901cebc Creado el primer boceto de la clase padre actor 2022-08-25 21:27:00 +02:00
39a8e9048a Cambiados los nombres de variables en text.h 2022-08-25 13:57:09 +02:00
a0613ddd8d Trabajando en el menu del titulo 2022-08-24 22:39:36 +02:00
1f4d094593 Retocando la clase menu 2022-08-24 13:58:52 +02:00
0749862af2 Cambiado el tipo de vector de la clase menu a std::vector 2022-08-23 20:50:55 +02:00
bca15cd29e Retocados los nombres de las variables de la clase menu 2022-08-23 20:08:28 +02:00
f2ea31a564 Añadido el degradado de fondo al archivo de mapa 2022-08-23 19:00:09 +02:00
2425ab5142 Añadida música al titulo 2022-08-23 17:03:10 +02:00
87f6ec39ea Añadida la clase Menu desde Coffee Crisis 2022-08-23 16:35:01 +02:00
6b9360ee18 Añadida la fuente Dogica 2022-08-23 14:00:52 +02:00
b61677bda9 Empezada la sección del titulo del juego 2022-08-23 12:35:56 +02:00
6b4926efb8 Completado el logo y la intro 2022-08-22 23:25:12 +02:00
f1e3cfe892 Añadidos los ficheros de intro y logo del coffee crisis 2022-08-22 17:44:24 +02:00
debdc861d5 Modificado el loop de las animaciones 2022-08-22 17:42:26 +02:00
7c7dcf1a12 Añadido mas texto al debug 2022-08-21 10:25:28 +02:00
b394395fa7 Añadida la música 2022-08-21 10:16:29 +02:00
6d2fe4541a Añadidos los enemigos 2022-08-20 20:49:35 +02:00
82089bb780 Empezando a trabajar con los enemigos 2022-08-20 19:11:59 +02:00
bb5d772a4b Borrado sync.sh 2022-08-20 17:31:42 +02:00
8c87534848 Desaparición de la carpeta media 2022-08-20 17:30:11 +02:00
75c6acdd53 Implementado el cambio de pantalla 2022-08-20 15:41:23 +02:00
7e93b3150f Terminados los tiles atravesables 2022-08-20 09:15:51 +02:00
8765049b69 Trabajando con el isOnFloor y los tiles passable 2022-08-19 14:05:56 +02:00
5144a14bcd Aladidos estados al jugador para mejorar el control sobre el salto y las caídas 2022-08-19 13:21:23 +02:00
1882f57c57 Cambiado el método de gestion de las colisiones del jugador. En vez de recular ahora corrige 2022-08-19 12:42:47 +02:00
0624cff845 Primera implementacion de tiles atravesables. No funcionará si estan apilados 2022-08-19 12:33:42 +02:00
76696f9eb7 Retocado un poco mas el salto 2022-08-19 07:21:25 +02:00
6a5f0b3b46 Convertido el juego a mapas con tiles de 8x8 2022-08-18 21:18:15 +02:00
c848a8b234 Antes de pasar el juego a tiles de 8x8 2022-08-18 20:41:53 +02:00
4de34c388d Añadidas físicas al movimiento y salto 2022-08-18 13:42:30 +02:00
116 changed files with 5462 additions and 649 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.vscode/*
.DS_Store
desktop.ini
thumbs.db
bin/*

View File

@@ -0,0 +1,10 @@
frames_per_row=6
frame_width=16
frame_height=16
[animation]
name=default
speed=8
loop=0
frames=0,1,2,3,4,5
[/animation]

BIN
data/actors/enemies/bug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,10 @@
frames_per_row=6
frame_width=16
frame_height=16
[animation]
name=default
speed=8
loop=0
frames=0,1,2,3,4,5
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,10 @@
frames_per_row=6
frame_width=16
frame_height=16
[animation]
name=default
speed=6
loop=0
frames=0,1,2,3,4,5
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,10 @@
frames_per_row=6
frame_width=16
frame_height=16
[animation]
name=default
speed=8
loop=0
frames=0,1,2,3,4,5
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,10 @@
frames_per_row=8
frame_width=16
frame_height=16
[animation]
name=default
speed=8
loop=0
frames=0,1,2,3,4,5,6,7
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,10 @@
frames_per_row=1
frame_width=16
frame_height=8
[animation]
name=default
speed=8
loop=0
frames=0
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 689 B

BIN
data/font/dogica.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

194
data/font/dogica.txt Normal file
View File

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

17
data/intro/intro.ani Normal file
View File

@@ -0,0 +1,17 @@
frames_per_row=4
frame_width=320
frame_height=240
[animation]
name=intro
speed=12
loop=-1
frames=0,1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
[/animation]
[animation]
name=menu
speed=12
loop=0
frames=18,26,18,26,18,26,18,26,18,26,18,26,18,26,18,19,20,21,22,23,24,25,26
[/animation]

View File

Before

Width:  |  Height:  |  Size: 670 KiB

After

Width:  |  Height:  |  Size: 670 KiB

BIN
data/logo/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.9" tiledversion="1.9.0" orientation="orthogonal" renderorder="right-down" width="20" height="13" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
<tileset firstgid="1" source="../../../volcano_2022_resources/tilesets/surface.tsx"/>
<layer id="2" name="actors" width="20" height="13">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,225,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="1" name="tiles" width="20" height="13">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,68,68,0,0,0,0,0,0,0,0,74,74,74,0,0,0,0,
74,74,74,75,75,74,74,68,68,68,68,68,74,74,78,74,68,74,68,68
</data>
</layer>
</map>

14
data/map/01.ene Normal file
View File

@@ -0,0 +1,14 @@
[path]
tileset=walking_eye.png
animation=walking_eye.ani
width=16
height=16
x=22
y=20
vx=0.4
vy=0
x1=22
y1=20
x2=27
y2=20
[/path]

View File

@@ -1,11 +1,74 @@
tileset_img=tiles_surface.png
bg_img=bg_surface.png
tileset_img=surface.png
enemy_file=01.ene
bgColor1=234,171,159
bgColor2=144,225,231
room_up=0
room_down=0
room_left=0
room_right=0
room_right=02.map
[tilemap]
01.tmx
[tilemap-end]
[/tilemap]
[actors]
[moving platform]
tileset=moving_platform.png
animation=moving_platform.ani
width=16
height=8
x=9
y=11
vx=0.3
vy=0
x1=9
y1=11
x2=15
y2=11
[/moving platform]
[moving platform]
tileset=moving_platform.png
animation=moving_platform.ani
width=16
height=8
x=20
y=14
vx=0
vy=0.3
x1=20
y1=14
x2=20
y2=21
[/moving platform]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=1
y=10
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=24
y=10
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=25
y=12
[/diamond]
[/actors]

View File

@@ -1,21 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.9" tiledversion="1.9.1" orientation="orthogonal" renderorder="right-down" width="20" height="13" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
<tileset firstgid="1" source="../../../volcano_2022_resources/media_work/map_work/tiles_surface.tsx"/>
<layer id="1" name="tiles" width="20" height="13">
<map version="1.9" tiledversion="1.9.1" orientation="orthogonal" renderorder="right-down" width="40" height="26" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="surface.tsx"/>
<layer id="1" name="Capa de patrones 1" width="40" height="26">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,65,65,0,0,0,0,
65,65,0,0,65,65,0,0,0,0,0,0,0,0,0,68,0,0,0,0,
0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,0,0,0,0,0,
0,49,0,0,0,0,0,47,0,0,0,0,0,77,74,76,0,0,0,0,
74,74,74,75,75,74,74,68,68,65,68,68,74,74,78,74,68,74,68,68
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,19,20,0,0,0,0,0,87,88,89,90,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,52,0,0,0,0,0,119,120,121,122,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,19,20,0,0,0,0,0,0,0,0,0,0,0,151,152,153,154,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,52,0,0,0,0,0,0,0,0,0,0,0,183,184,185,186,0,0,0,0,0,0,
0,18,19,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,50,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,19,20,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,52,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,94,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,237,238,0,0,0,0,0,0,0,0,125,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,362,364,0,0,0,0,0,0,0,0,369,371,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,426,428,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,362,364,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,426,428,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,583,584,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,239,240,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,93,94,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,366,367,367,368,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,0,125,126,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,430,431,431,432,0,0,0,0,577,578,579,580,581,582,0,0,0,0,0,0,0,0,159,160,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,191,192,0,0,0,0,0,93,94,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,189,190,241,242,0,0,0,125,126,0,0,0,0,0,0,
363,364,0,0,0,0,0,193,194,0,0,0,0,189,190,0,0,0,237,238,0,0,362,282,277,278,279,274,364,0,0,0,157,158,0,0,0,0,0,0,
295,396,0,0,0,0,0,225,226,0,0,0,0,189,190,0,0,362,275,275,275,275,313,314,309,310,311,312,396,0,0,0,189,190,0,0,237,238,0,0,
265,264,263,264,263,264,263,264,263,264,263,264,263,264,263,264,263,264,267,266,266,266,283,284,266,265,266,267,263,264,263,264,263,264,263,264,263,264,263,264,
295,296,295,296,295,296,295,296,295,265,295,296,295,296,295,296,295,296,295,296,295,296,315,316,298,297,298,296,295,296,295,296,295,296,295,296,295,296,295,296
</data>
</layer>
</map>

29
data/map/02.ene Normal file
View File

@@ -0,0 +1,29 @@
[path]
tileset=flying_eye.png
animation=flying_eye.ani
width=16
height=16
x=9
y=12
vx=0
vy=0.3
x1=9
y1=12
x2=9
y2=20
[/path]
[path]
tileset=flying_eye_horn.png
animation=flying_eye_horn.ani
width=16
height=16
x=15
y=5
vx=0.5
vy=0
x1=5
y1=5
x2=30
y2=5
[/path]

92
data/map/02.map Normal file
View File

@@ -0,0 +1,92 @@
tileset_img=surface.png
enemy_file=02.ene
bgColor1=234,100,159
bgColor2=144,235,231
bgColor1=153,229,80
bgColor2=95,205,228
room_up=0
room_down=03.map
room_left=01.map
room_right=0
[tilemap]
02.tmx
[/tilemap]
[actors]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=5
y=13
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=8
y=7
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=12
y=11
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=16
y=17
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=18
y=15
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=20
y=13
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=27
y=9
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=33
y=14
[/diamond]
[/actors]

34
data/map/02.tmx Normal file
View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.9" tiledversion="1.9.1" orientation="orthogonal" renderorder="right-down" width="40" height="26" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="surface.tsx"/>
<layer id="1" name="Capa de patrones 1" width="40" height="26">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,19,20,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,52,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,88,89,90,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,119,120,121,122,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,19,20,0,0,0,0,0,0,0,0,0,0,0,0,151,152,153,154,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,52,0,0,0,0,0,0,0,0,0,0,0,0,183,184,185,186,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,362,363,363,364,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,404,395,395,406,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,112,113,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,577,578,579,580,581,582,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,109,110,113,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,141,142,138,113,264,263,264,364,0,0,0,0,0,0,0,0,0,0,0,161,162,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,180,169,170,138,313,295,296,406,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,372,373,373,264,78,137,138,75,76,145,0,0,0,0,0,0,583,584,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,144,86,77,110,169,170,83,108,0,0,0,0,0,0,0,161,162,0,0,0,0,0,159,160,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,109,148,137,138,115,0,0,0,0,0,0,583,584,155,156,65,66,0,0,0,191,192,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,109,110,170,115,0,0,0,0,0,0,161,162,187,188,97,98,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,141,142,138,83,0,0,0,0,583,584,155,156,65,66,69,70,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,180,169,170,115,0,0,0,0,161,162,187,188,97,98,101,102,0,0,0,189,190,0,0,93,94,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,362,282,276,277,279,364,193,194,0,157,158,93,94,157,158,157,158,0,0,0,69,70,0,0,125,126,0,0,0,93,94,0,0,
0,0,0,0,0,0,0,394,314,308,309,311,396,225,226,0,189,190,125,126,189,190,189,190,0,0,0,101,102,0,0,157,158,0,0,0,125,126,0,0,
363,363,363,363,363,363,363,363,265,265,265,265,363,363,363,363,363,363,363,363,363,363,363,363,363,364,0,189,190,0,362,363,363,363,363,363,363,363,363,363,
295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,296,296,296,296,396,0,189,190,0,394,296,296,296,296,296,296,296,296,296
</data>
</layer>
</map>

44
data/map/03.ene Normal file
View File

@@ -0,0 +1,44 @@
[path]
tileset=walking_eye.png
animation=walking_eye.ani
width=16
height=16
x=13
y=23
vx=0.4
vy=0
x1=3
y1=23
x2=18
y2=23
[/path]
[path]
tileset=walking_eye.png
animation=walking_eye.ani
width=16
height=16
x=22
y=13
vx=0.4
vy=0
x1=20
y1=13
x2=24
y2=13
[/path]
[path]
tileset=walking_eye.png
animation=walking_eye.ani
width=16
height=16
x=27
y=8
vx=-0.4
vy=0
x1=25
y1=8
x2=29
y2=8
[/path]

44
data/map/03.map Normal file
View File

@@ -0,0 +1,44 @@
tileset_img=surface.png
enemy_file=03.ene
bgColor1=143,86,59
bgColor2=69,40,60
room_up=02.map
room_down=0
room_left=0
room_right=0
[tilemap]
03.tmx
[/tilemap]
[actors]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=25
y=19
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=22
y=12
[/diamond]
[diamond]
tileset=diamond.png
animation=diamond.ani
width=16
height=16
x=2
y=22
[/diamond]
[/actors]

34
data/map/03.tmx Normal file
View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.9" tiledversion="1.9.1" orientation="orthogonal" renderorder="right-down" width="40" height="26" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="surface.tsx"/>
<layer id="1" name="Capa de patrones 1" width="40" height="26">
<data encoding="csv">
260,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,432,0,189,190,0,430,431,431,431,431,431,431,431,431,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
291,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,577,578,579,580,581,582,0,0,0,0,0,0,0,0,292,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,291,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,577,578,579,580,581,582,0,0,0,0,0,0,0,0,292,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,0,0,260,
291,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,155,156,65,66,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,187,188,97,98,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,577,578,579,580,581,582,0,0,0,157,158,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,292,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,159,160,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,0,0,0,0,0,0,191,192,0,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,157,158,0,0,0,0,0,0,577,578,579,580,581,582,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,291,
291,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,159,160,0,0,0,0,0,0,0,0,189,190,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,191,192,577,578,579,580,581,582,0,0,67,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,70,0,0,189,190,0,0,0,157,158,0,0,0,0,0,0,0,260,
260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,102,0,0,189,190,0,0,0,189,190,0,0,0,0,0,0,0,260,
260,260,257,258,260,260,260,260,258,260,260,260,260,260,257,260,260,260,258,260,260,260,260,260,260,260,260,260,257,258,260,260,260,260,260,260,257,260,260,260
</data>
</layer>
</map>

BIN
data/map/surface.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

1028
data/map/surface.tsx Normal file

File diff suppressed because it is too large Load Diff

27
data/map/surface.world Normal file
View File

@@ -0,0 +1,27 @@
{
"maps": [
{
"fileName": "02.tmx",
"height": 208,
"width": 320,
"x": 256,
"y": 0
},
{
"fileName": "01.tmx",
"height": 208,
"width": 320,
"x": -64,
"y": 0
},
{
"fileName": "03.tmx",
"height": 208,
"width": 320,
"x": 256,
"y": 208
}
],
"onlyShowAdjacentMaps": false,
"type": "world"
}

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -1,31 +1,31 @@
png_width_in_tiles=8
tile_width=16
tile_height=24
frames_per_row=8
frame_width=16
frame_height=24
[animation]
name=stand
speed=8
loop=yes
frames=0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,3,4,5,6,7,0,0,0,0
loop=0
frames=0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,3,4,5,4,5,5,5,6,6,7,7,0,0
[/animation]
[animation]
name=walk
speed=6
loop=yes
speed=4
loop=0
frames=8,9,10,10,9,8,11,12,13,13,14,15
[/animation]
[animation]
name=jump
speed=10
loop=yes
frames=16
loop=-1
frames=16,17,18,17,16
[/animation]
[animation]
name=death
speed=10
loop=no
loop=-1
frames=24,25,26,27,28,29,30,31
[/animation]

BIN
data/player/player.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

4
data/sound/desktop.ini Normal file
View File

@@ -0,0 +1,4 @@
[ViewState]
Mode=
Vid=
FolderType=Generic

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

76
source/actor.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include "actor.h"
#include <fstream>
#include <sstream>
// Constructor
Actor::Actor()
{
}
// Constructor
Actor::Actor(actor_t actor)
{
// Obten punteros a objetos
asset = actor.asset;
renderer = actor.renderer;
// Crea objetos
texture = new LTexture();
loadTextureFromFile(texture, asset->get(actor.tileset), renderer);
sprite = new AnimatedSprite(texture, renderer, asset->get(actor.animation));
// Obten el resto de valores
sprite->setPosX(actor.x);
sprite->setPosY(actor.y);
sprite->setWidth(actor.w);
sprite->setHeight(actor.h);
sprite->setVelX(actor.vx);
sprite->setVelY(actor.vy);
sprite->setFlip(actor.vx > 0 ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL);
this->name = actor.name;
}
// Destructor
Actor::~Actor()
{
texture->unload();
delete texture;
texture = nullptr;
delete sprite;
sprite = nullptr;
}
// Pinta el enemigo en pantalla
void Actor::render()
{
sprite->render();
}
// Actualiza las variables del objeto
void Actor::update()
{
sprite->update();
sprite->animate();
}
// Obtiene el rectangulo de colision del enemigo
SDL_Rect &Actor::getCollider()
{
collider = sprite->getRect();
return collider;
}
// Obtiene el nombre del actor
actor_name_e Actor::getName()
{
return name;
}
// Obtiene el valor de la variable
int Actor::getIncX()
{
return sprite->getIncX();
}

73
source/actor.h Normal file
View File

@@ -0,0 +1,73 @@
#pragma once
#include <SDL2/SDL.h>
#include "utils.h"
#include "asset.h"
#include "animatedsprite.h"
#include <string>
#ifndef ACTOR_H
#define ACTOR_H
// Nombres de actores
enum actor_name_e
{
a_moving_platform,
a_key,
a_heart,
a_diamond,
a_door
};
// Estructura para pasar los datos de un enemigo
struct actor_t
{
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
std::string tileset; // Fichero con los graficos del enemigo
std::string animation; // Fichero con las animaciones del enemigo
int w; // Anchura del enemigo
int h; // Altura del enemigo
float x; // Posición inicial en el eje X
float y; // Posición inicial en el eje Y
float vx; // Velocidad en el eje X
float vy; // Velocidad en el eje Y
actor_name_e name; // Nombre del actor
};
// Clase Actor
class Actor
{
protected:
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
LTexture *texture; // Textura con los graficos del enemigo
AnimatedSprite *sprite; // Sprite del enemigo
SDL_Rect collider; // Caja de colisión
actor_name_e name; // Nombre del actor
public:
// Constructor
Actor();
Actor(actor_t actor);
// Destructor
virtual ~Actor();
// Pinta el enemigo en pantalla
void render();
// Actualiza las variables del objeto
virtual void update();
// Obtiene el rectangulo de colision del enemigo
SDL_Rect &getCollider();
// Obtiene el nombre del actor
actor_name_e getName();
// Obtiene el valor de la variable
int getIncX();
};
#endif

13
source/actor_diamond.cpp Normal file
View File

@@ -0,0 +1,13 @@
#include "actor_diamond.h"
#include <fstream>
#include <sstream>
// Constructor
ActorDiamond::ActorDiamond(actor_t actor) : Actor(actor)
{
}
// Destructor
ActorDiamond::~ActorDiamond()
{
}

25
source/actor_diamond.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include <SDL2/SDL.h>
#include "actor.h"
#include <string>
#ifndef ACTOR_DIAMOND_H
#define ACTOR_DIAMOND_H
// Clase Actor
class ActorDiamond : public Actor
{
private:
public:
// Constructor
ActorDiamond(actor_t actor);
// Destructor
~ActorDiamond();
};
#endif

View File

@@ -0,0 +1,39 @@
#include "actor_moving_platform.h"
#include <fstream>
#include <sstream>
// Constructor
ActorMovingPlatform::ActorMovingPlatform(actor_t actor, SDL_Point p1, SDL_Point p2) : Actor(actor)
{
this->p1 = p1;
this->p2 = p2;
}
// Destructor
ActorMovingPlatform::~ActorMovingPlatform()
{
}
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
void ActorMovingPlatform::checkPath()
{
// Comprueba los límites horizontales
if (sprite->getPosX() > p2.x || sprite->getPosX() < p1.x)
{
sprite->setVelX(sprite->getVelX() * (-1));
}
// Comprueba los límites verticales
if (sprite->getPosY() > p2.y || sprite->getPosY() < p1.y)
{
sprite->setVelY(sprite->getVelY() * (-1));
}
}
// Actualiza las variables del objeto
void ActorMovingPlatform::update()
{
checkPath();
sprite->update();
sprite->animate();
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include <SDL2/SDL.h>
#include "actor.h"
#include <string>
#ifndef ACTOR_MOVING_PLATFORM_H
#define ACTOR_MOVING_PLATFORM_H
// Clase Actor
class ActorMovingPlatform : public Actor
{
private:
SDL_Point p1; // Punto 1 (inicial) de la ruta
SDL_Point p2; // Punto 2 (final) de la ruta
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
void checkPath();
// Actualiza la variable
void updateShift();
public:
// Constructor
ActorMovingPlatform(actor_t actor, SDL_Point p1, SDL_Point p2);
// Destructor
~ActorMovingPlatform();
// Actualiza las variables del objeto
void update();
};
#endif

View File

@@ -1,10 +0,0 @@
#include "actors.h"
// Constructor
Actors::Actors()
{
}
Actors::~Actors()
{
}

View File

@@ -1,20 +0,0 @@
#pragma once
#include <SDL2/SDL.h>
#ifndef ACTORS_H
#define ACTORS_H
class Actors
{
private:
public:
// Constructor
Actors();
// Destructor
~Actors();
};
#endif

View File

@@ -10,12 +10,15 @@ AnimatedSprite::AnimatedSprite(LTexture *texture, SDL_Renderer *renderer, std::s
// Carga las animaciones
load(file);
// Inicializa variables
currentAnimation = 0;
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
for (auto a : animation)
for (auto &a : animation)
{
a.frames.clear();
}
@@ -25,33 +28,45 @@ AnimatedSprite::~AnimatedSprite()
// Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name)
{
int result = -1;
int index = -1;
for (int i = 0; i < animation.size(); i++)
{
if (animation[i].name == name)
{
result = i;
index = i;
}
}
return result;
if (index == -1)
{
printf("** Warning: could not find \"%s\" animation\n", name.c_str());
index = 0;
}
return index;
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate()
{
if (mEnabled)
if (enabled)
{
// Calcula el frame actual a partir del contador
animation[currentAnimation].currentFrame = animation[currentAnimation].counter / animation[currentAnimation].speed;
// Si alcanza el final de la animación, reinicia el contador de la animación
// en función de la variable loop
// en función de la variable loop y coloca el nuevo frame
if (animation[currentAnimation].currentFrame >= animation[currentAnimation].frames.size())
{
if (animation[currentAnimation].loop)
animation[currentAnimation].counter = 0;
else
if (animation[currentAnimation].loop == -1)
{ // Si no hay loop, deja el último frame
animation[currentAnimation].currentFrame = animation[currentAnimation].frames.size();
animation[currentAnimation].completed = true;
}
else
{ // Si hay loop, vuelve al frame indicado
animation[currentAnimation].counter = 0;
animation[currentAnimation].currentFrame = animation[currentAnimation].loop;
}
}
// En caso contrario
else
@@ -84,7 +99,7 @@ void AnimatedSprite::setAnimationSpeed(std::string name, int speed)
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, bool loop)
void AnimatedSprite::setAnimationLoop(std::string name, int loop)
{
animation[getIndex(name)].loop = loop;
}
@@ -96,9 +111,9 @@ void AnimatedSprite::setAnimationCompleted(std::string name, bool value)
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted(std::string name)
bool AnimatedSprite::animationIsCompleted()
{
return animation[getIndex(name)].completed;
return animation[currentAnimation].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
@@ -110,9 +125,10 @@ SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index)
// Carga la animación desde un fichero
bool AnimatedSprite::load(std::string filePath)
{
int png_width_in_tiles = 0;
int tile_width = 0;
int tile_height = 0;
int frames_per_row = 0;
int frame_width = 0;
int frame_height = 0;
// Indicador de éxito en la carga
bool success = true;
@@ -155,26 +171,19 @@ bool AnimatedSprite::load(std::string filePath)
}
else if (line.substr(0, pos) == "loop")
{
if (line.substr(pos + 1, line.length()) == "yes" || line.substr(pos + 1, line.length()) == "true")
{
buffer.loop = true;
}
else
{
buffer.loop = false;
}
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, tile_width, tile_height};
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
int num_tile = std::stoi(tmp);
rect.x = (num_tile % png_width_in_tiles) * tile_width;
rect.y = (num_tile / png_width_in_tiles) * tile_height;
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect);
}
}
@@ -199,17 +208,17 @@ bool AnimatedSprite::load(std::string filePath)
// Procesa las dos subcadenas
if (pos != line.npos)
{
if (line.substr(0, pos) == "png_width_in_tiles")
if (line.substr(0, pos) == "frames_per_row")
{
png_width_in_tiles = std::stoi(line.substr(pos + 1, line.length()));
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "tile_width")
else if (line.substr(0, pos) == "frame_width")
{
tile_width = std::stoi(line.substr(pos + 1, line.length()));
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "tile_height")
else if (line.substr(0, pos) == "frame_height")
{
tile_height = std::stoi(line.substr(pos + 1, line.length()));
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
@@ -221,7 +230,7 @@ bool AnimatedSprite::load(std::string filePath)
}
// Cierra el fichero
printf("Closing file %s\n", filename.c_str());
printf("Closing file %s\n\n", filename.c_str());
file.close();
}
// El fichero no se puede abrir
@@ -231,6 +240,9 @@ bool AnimatedSprite::load(std::string filePath)
success = false;
}
// Pone un valor por defecto
setPos({0, 0, frame_width, frame_height});
return success;
}

View File

@@ -1,4 +1,5 @@
#pragma once
#include <SDL2/SDL.h>
#include "movingsprite.h"
#include <vector>
@@ -18,7 +19,7 @@ private:
std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación
bool loop; // Indica si la animación se reproduce en bucle
int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed; // Indica si ha finalizado la animación
int currentFrame; // Frame actual
int counter; // Contador para las animaciones
@@ -28,7 +29,7 @@ private:
public:
// Constructor
AnimatedSprite(LTexture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file="");
AnimatedSprite(LTexture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = "");
// Destructor
~AnimatedSprite();
@@ -45,14 +46,14 @@ public:
// Establece la velocidad de una animación
void setAnimationSpeed(std::string name, int speed);
// Establece si la animación se reproduce en bucle
void setAnimationLoop(std::string name, bool loop);
// Establece el frame al que vuelve la animación al finalizar
void setAnimationLoop(std::string name, int loop);
// Establece el valor de la variable
void setAnimationCompleted(std::string name, bool value);
// Comprueba si ha terminado la animación
bool animationIsCompleted(std::string name);
bool animationIsCompleted();
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(std::string name, Uint8 index);
@@ -64,7 +65,7 @@ public:
bool load(std::string filePath);
// Establece la animacion actual
void setCurrentAnimation(std::string name);
void setCurrentAnimation(std::string name = "default");
// Actualiza las variables del objeto
void update();

View File

@@ -1,4 +1,5 @@
#pragma once
#include <SDL2/SDL.h>
#include <string>
#include <vector>

71
source/enemy.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include "enemy.h"
#include <fstream>
#include <sstream>
// Constructor
Enemy::Enemy()
{
}
// Constructor
Enemy::Enemy(enemy_t enemy)
{
// Obten punteros a objetos
asset = enemy.asset;
renderer = enemy.renderer;
// Crea objetos
texture = new LTexture();
loadTextureFromFile(texture, asset->get(enemy.tileset), renderer);
sprite = new AnimatedSprite(texture, renderer, asset->get(enemy.animation));
// Obten el resto de valores
sprite->setPosX(enemy.x);
sprite->setPosY(enemy.y);
sprite->setWidth(enemy.w);
sprite->setHeight(enemy.h);
sprite->setVelX(enemy.vx);
sprite->setVelY(enemy.vy);
sprite->setCurrentAnimation();
sprite->setFlip(enemy.vx > 0 ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL);
collider = getRect();
}
// Destructor
Enemy::~Enemy()
{
texture->unload();
delete texture;
texture = nullptr;
delete sprite;
sprite = nullptr;
}
// Pinta el enemigo en pantalla
void Enemy::render()
{
sprite->render();
}
// Actualiza las variables del objeto
void Enemy::update()
{
sprite->update();
sprite->animate();
collider = getRect();
}
// Devuelve el rectangulo que contiene al enemigo
SDL_Rect Enemy::getRect()
{
return sprite->getRect();
}
// Obtiene el rectangulo de colision del enemigo
SDL_Rect &Enemy::getCollider()
{
return collider;
}

58
source/enemy.h Normal file
View File

@@ -0,0 +1,58 @@
#pragma once
#include <SDL2/SDL.h>
#include "utils.h"
#include "asset.h"
#include "animatedsprite.h"
#include <string>
#ifndef ENEMY_H
#define ENEMY_H
// Estructura para pasar los datos de un enemigo
struct enemy_t
{
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
std::string tileset; // Fichero con los graficos del enemigo
std::string animation; // Fichero con las animaciones del enemigo
int w; // Anchura del enemigo
int h; // Altura del enemigo
float x; // Posición inicial en el eje X
float y; // Posición inicial en el eje Y
float vx; // Velocidad en el eje X
float vy; // Velocidad en el eje Y
};
// Clase Enemy
class Enemy
{
protected:
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
LTexture *texture; // Textura con los graficos del enemigo
AnimatedSprite *sprite; // Sprite del enemigo
SDL_Rect collider; // Caja de colisión
public:
// Constructor
Enemy();
Enemy(enemy_t enemy);
// Destructor
virtual ~Enemy();
// Pinta el enemigo en pantalla
void render();
// Actualiza las variables del objeto
virtual void update();
// Devuelve el rectangulo que contiene al enemigo
SDL_Rect getRect();
// Obtiene el rectangulo de colision del enemigo
SDL_Rect &getCollider();
};
#endif

170
source/enemy_engine.cpp Normal file
View File

@@ -0,0 +1,170 @@
#include "enemy_engine.h"
#include <fstream>
#include <sstream>
// Constructor
EnemyEngine::EnemyEngine(SDL_Renderer *renderer, Asset *asset, Player *player, Map *map, std::string file)
{
this->renderer = renderer;
this->asset = asset;
this->player = player;
this->map = map;
load(file);
}
// Destructor
EnemyEngine::~EnemyEngine()
{
// Elimina todos los enemigos anteriores
for (auto enemy : enemies)
{
delete enemy;
}
enemies.clear();
}
// Pinta los enemigos en pantalla
void EnemyEngine::render()
{
for (auto enemy : enemies)
{
enemy->render();
}
}
// Actualiza las variables del objeto
void EnemyEngine::update()
{
for (auto enemy : enemies)
{
enemy->update();
}
}
// Carga las variables desde un fichero
bool EnemyEngine::load(std::string file_path)
{
// Indicador de éxito en la carga
bool success = true;
std::string filename = file_path.substr(file_path.find_last_of("\\/") + 1);
std::string line;
std::ifstream file(file_path);
// El fichero se puede abrir
if (file.good())
{
// Procesa el fichero linea a linea
printf("Reading file %s\n", filename.c_str());
while (std::getline(file, line))
{
// Si la linea contiene el texto [actor] se realiza el proceso de carga de los actores
if (line == "[path]")
{
enemy_t enemy;
enemy.asset = asset;
enemy.renderer = renderer;
SDL_Point p1, p2;
do
{
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (!setEnemy(&enemy, &p1, &p2, line.substr(0, pos), line.substr(pos + 1, line.length())))
{
printf("Warning: file %s\n, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
success = false;
}
} while (line != "[/path]");
printf("** enemy path loaded\n\n");
enemies.push_back(new EnemyPath(enemy, p1, p2));
}
}
// Cierra el fichero
printf("Closing file %s\n\n", filename.c_str());
file.close();
}
// El fichero no se puede abrir
else
{
printf("Warning: Unable to open %s file\n", filename.c_str());
success = false;
}
return success;
}
// Asigna variables a una estructura enemy_t
bool EnemyEngine::setEnemy(enemy_t *enemy, SDL_Point *p1, SDL_Point *p2, std::string var, std::string value)
{
const int tile_size = 8;
// Indicador de éxito en la asignación
bool success = true;
if (var == "tileset")
{
enemy->tileset = value;
}
else if (var == "animation")
{
enemy->animation = value;
}
else if (var == "width")
{
enemy->w = std::stof(value);
}
else if (var == "height")
{
enemy->h = std::stof(value);
}
else if (var == "x")
{
enemy->x = std::stof(value) * tile_size;
}
else if (var == "y")
{
enemy->y = std::stof(value) * tile_size;
}
else if (var == "vx")
{
enemy->vx = std::stof(value);
}
else if (var == "vy")
{
enemy->vy = std::stof(value);
}
else if (var == "x1")
{
p1->x = std::stoi(value) * tile_size;
}
else if (var == "x2")
{
p2->x = std::stoi(value) * tile_size;
}
else if (var == "y1")
{
p1->y = std::stoi(value) * tile_size;
}
else if (var == "y2")
{
p2->y = std::stoi(value) * tile_size;
}
else if (var == "[/path]")
{
}
else
{
success = false;
}
return success;
}

46
source/enemy_engine.h Normal file
View File

@@ -0,0 +1,46 @@
#pragma once
#include <SDL2/SDL.h>
#include "utils.h"
#include "asset.h"
#include "enemy.h"
#include "enemy_path.h"
#include "map.h"
#include "player.h"
#include <string>
#include <vector>
#ifndef ENEMY_ENGINE_H
#define ENEMY_ENGINE_H
// Clase EnemyEngine
class EnemyEngine
{
private:
SDL_Renderer *renderer; // El renderizador de la ventana
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
Map *map; // Mapa con la información de la habitación
Player *player; // Puntero con el jugador
std::vector<EnemyPath *> enemies; // Vector con la lista de enemigos
// Carga las variables desde un fichero
bool load(std::string file_path);
// Asigna variables a una estructura enemy_t
bool setEnemy(enemy_t *enemy, SDL_Point *p1, SDL_Point *p2, std::string var, std::string value);
public:
// Constructor
EnemyEngine(SDL_Renderer *renderer, Asset *asset, Player *player, Map *map, std::string file);
// Destructor
~EnemyEngine();
// Pinta los enemigos en pantalla
void render();
// Actualiza las variables del objeto
void update();
};
#endif

43
source/enemy_path.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include "enemy_path.h"
#include <fstream>
#include <sstream>
// Constructor
EnemyPath::EnemyPath(enemy_t enemy, SDL_Point p1, SDL_Point p2) : Enemy(enemy)
{
// Obten el resto de valores
this->p1 = p1;
this->p2 = p2;
}
// Destructor
EnemyPath::~EnemyPath()
{
}
// Actualiza las variables del objeto
void EnemyPath::update()
{
sprite->update();
sprite->animate();
checkPath();
collider = getRect();
}
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
void EnemyPath::checkPath()
{
// Comprueba los límites horizontales
if (sprite->getPosX() > p2.x || sprite->getPosX() < p1.x)
{
sprite->setVelX(sprite->getVelX() * (-1));
sprite->flip();
}
// Comprueba los límites verticales
if (sprite->getPosY() > p2.y || sprite->getPosY() < p1.y)
{
sprite->setVelY(sprite->getVelY() * (-1));
sprite->flip();
}
}

33
source/enemy_path.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include <SDL2/SDL.h>
#include "enemy.h"
#include <string>
#ifndef ENEMY_PATH_H
#define ENEMY_PATH_H
// Clase EnemyPath
class EnemyPath : public Enemy
{
private:
SDL_Point p1; // Punto 1 (inicial) de la ruta
SDL_Point p2; // Punto 2 (final) de la ruta
// Comprueba si ha llegado al limite del recorrido para darse media vuelta
void checkPath();
public:
// Constructor
EnemyPath(enemy_t enemy, SDL_Point p1, SDL_Point p2);
// Destructor
~EnemyPath();
// Actualiza las variables del objeto
void update();
};
#endif

View File

@@ -1,33 +1,55 @@
#include "game.h"
// Constructor
Game::Game(SDL_Renderer *renderer, Asset *asset, Screen *screen, Input *input)
Game::Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input)
{
// Copia punteros
this->renderer = renderer;
this->asset = asset;
this->screen = screen;
this->input = input;
// Reserva memoria para los objetos
eventHandler = new SDL_Event();
map = new Map(asset->get("01.map"), renderer, asset);
itemTracker = new ItemTracker();
map = new Map(asset->get("01.map"), renderer, asset, itemTracker);
player = new Player(renderer, asset, input, map);
enemyEngine = new EnemyEngine(renderer, asset, player, map, asset->get(map->getEnemyFile()));
// enemyEngine->setEnemies(asset->get(map->getEnemyFile()));
debugText = new Text(asset->get("debug.png"), asset->get("debug.txt"), renderer);
music = JA_LoadMusic(asset->get("music_surface.ogg").c_str());
// Inicializa variables
ticks = 0;
ticksSpeed = 15;
section.name = SECTION_PROG_GAME;
section.subsection = SUBSECTION_GAME_PLAY;
musicEnabled = true;
debug = false;
musicEnabled = !debug;
}
// Destructor
Game::~Game()
{
delete eventHandler;
delete itemTracker;
delete map;
delete player;
delete enemyEngine;
delete debugText;
JA_DeleteMusic(music);
}
// Bucle para el juego
section_t Game::run()
{
init();
if (musicEnabled)
{
JA_PlayMusic(music);
}
while (section.name == SECTION_PROG_GAME)
{
@@ -39,21 +61,11 @@ section_t Game::run()
}
}
JA_StopMusic();
return section;
}
// Inicializa las variables necesarias para la sección 'Game'
void Game::init()
{
ticks = 0;
ticksSpeed = 15;
section.name = SECTION_PROG_GAME;
section.subsection = SUBSECTION_GAME_PLAY;
debug = true;
}
// Actualiza el juego, las variables, comprueba la entrada, etc.
void Game::update()
{
@@ -75,6 +87,9 @@ void Game::update()
}
player->update();
checkScreenBorders();
enemyEngine->update();
map->update();
checkInput();
}
}
@@ -88,6 +103,7 @@ void Game::render()
// Dibuja los objetos
map->render();
enemyEngine->render();
player->render();
renderDebugInfo();
@@ -99,7 +115,31 @@ void Game::render()
void Game::checkInput()
{
if (input->checkInput(INPUT_BUTTON_2, REPEAT_FALSE))
{
debug = !debug;
musicEnabled = !debug;
if (musicEnabled)
{
JA_PlayMusic(music);
}
else
{
JA_StopMusic();
}
}
if (input->checkInput(INPUT_BUTTON_3, REPEAT_FALSE))
{
delete map;
map = new Map(asset->get("01.map"), renderer, asset, itemTracker);
delete player;
player = new Player(renderer, asset, input, map);
}
if (input->checkInput(INPUT_BUTTON_ESCAPE, REPEAT_FALSE))
{
section.name = SECTION_PROG_QUIT;
}
}
// Muestra información de depuración
@@ -110,12 +150,99 @@ void Game::renderDebugInfo()
return;
}
// Pinta la rejilla
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 16);
for (int i = 0; i < 240; i += 8)
{
SDL_RenderDrawLine(renderer, 0, i, 320, i);
}
for (int i = 0; i < 320; i += 8)
{
SDL_RenderDrawLine(renderer, i, 0, i, 240);
}
// Pinta el texto
int line = 0;
std::string text = "";
text = std::to_string((int)player->sprite->getPosX()) + "," + std::to_string((int)player->sprite->getPosY());
text = "R - Reload player and map";
debugText->write(1, 210, text, -1);
text = "D - Toggle debug mode";
debugText->write(1, 216, text, -1);
text = std::to_string((int)player->sprite->getPosX()) + "," + std::to_string((int)player->sprite->getPosY()) + "," + std::to_string((int)player->sprite->getWidth()) + "," + std::to_string((int)player->sprite->getHeight());
debugText->write(0, line, text, -1);
//text = std::to_string(player->checkMapCollisions());
//debugText->write(0, line+=6, text, -1);
text = "VY " + std::to_string(player->vy) + " " + std::to_string(player->jumpStrenght);
debugText->write(0, line += 6, text, -1);
text = "VX " + std::to_string(player->vx);
debugText->write(0, line += 6, text, -1);
text = "jump_pressed " + std::to_string(player->jumpPressed);
debugText->write(0, line += 6, text, -1);
text = "isOnFloor " + std::to_string(player->isOnFloor());
debugText->write(0, line += 6, text, -1);
const std::string foot_x = std::to_string(player->underFeet[0].x);
const std::string foot_y = std::to_string(player->underFeet[0].y);
const std::string gettile = std::to_string(player->map->getTile(player->underFeet[0]));
text = "getTile(" + foot_x + "," + foot_y + ") = " + gettile;
debugText->write(0, line += 6, text, -1);
text = "state " + std::to_string(player->state);
debugText->write(0, line += 6, text, -1);
text = map->getRoomFileName(b_top) + " " + map->getRoomFileName(b_right) + " " + map->getRoomFileName(b_bottom) + " " + map->getRoomFileName(b_left);
debugText->write(0, line += 6, text, -1);
text = "hookedOn = " + std::to_string(player->hookedOnMovingPlatform);
debugText->write(0, line += 6, text, -1);
text = "DIAMONDS = " + std::to_string(player->diamonds);
debugText->write(0, line += 6, text, -1);
// Pinta mascaras
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 128);
SDL_Rect rect = player->sprite->getRect();
SDL_RenderFillRect(renderer, &rect);
}
// Cambia el mapa
bool Game::changeMap(std::string file)
{
bool success = false;
// En las habitaciones los limites tienen la cadena del fichero o un 0 en caso de no limitar con nada
if (file != "0")
{ // Verifica que exista el fichero que se va a cargar
if (asset->get(file) != "")
{
// Elimina la habitación actual y crea un objeto nuevo a partir del fichero
delete map;
map = new Map(asset->get(file), renderer, asset, itemTracker);
// Elimina el gestor de enemigos y crea uno nuevo a partir de un fichero
delete enemyEngine;
enemyEngine = new EnemyEngine(renderer, asset, player, map, asset->get(map->getEnemyFile()));
success = true;
}
}
return success;
}
// Comprueba si el jugador está en el borde y se ha de cambiar el mapa
void Game::checkScreenBorders()
{
if (player->isOnScreenBorder())
{
if (changeMap(map->getRoomFileName(player->getBorder())))
{
player->setMap(map);
player->switchBorders();
}
}
}

View File

@@ -1,4 +1,5 @@
#pragma once
#include <SDL2/SDL.h>
#include "utils.h"
#include "asset.h"
@@ -6,6 +7,8 @@
#include "input.h"
#include "map.h"
#include "player.h"
#include "item_tracker.h"
#include "enemy_engine.h"
#include "text.h"
#ifndef GAME_H
@@ -19,13 +22,17 @@ private:
Screen *screen; // Objeto encargado de dibujar en pantalla
Input *input; // Objeto Input para gestionar las entradas
SDL_Event *eventHandler; // Manejador de eventos
JA_Music music; // Contiene la musica que se reproduce durante el juego
Text *debugText; // Objeto para escribir texto con información de debug
Map *map; // Objeto encargado de gestionar el mapeado del juego
Player *player; // Objeto para gestionar el jugador
ItemTracker *itemTracker; // Objeto para gestionar los items recogidos
EnemyEngine *enemyEngine; // Objeto encargado de gestionar los enemigos
section_t section; // Seccion actual dentro del programa
int ticks; // Contador de ticks para ajustar la velocidad del programa
int ticksSpeed; // Velocidad a la que se repiten los bucles del programa
Map *map; // Objeto encargado de gestionar el mapeado del juego
Player *player; // Objeto para gestionar el jugador
bool debug; // Indica si esta activo el modo de depuración
bool musicEnabled; // Indica si la musica puede sonar o no
// Actualiza el juego, las variables, comprueba la entrada, etc.
void update();
@@ -33,18 +40,21 @@ private:
// Pinta los objetos en pantalla
void render();
// Inicializa las variables necesarias para la sección 'Game'
void init();
// Comprueba la entrada
void checkInput();
// Muestra información de depuración
void renderDebugInfo();
// Cambia el mapa
bool changeMap(std::string file);
// Comprueba si el jugador está en el borde y se ha de cambiar el mapa
void checkScreenBorders();
public:
// Constructor
Game(SDL_Renderer *renderer, Asset *asset, Screen *screen, Input *input);
Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input);
// Destructor
~Game();

View File

@@ -5,16 +5,16 @@
Input::Input(std::string file)
{
// Fichero gamecontrollerdb.txt
mDBpath = file;
dbPath = file;
// Inicializa las variables
for (int i = 0; i < 17; i++)
{
mKeyBindings[i].scancode = 0;
mKeyBindings[i].active = false;
keyBindings[i].scancode = 0;
keyBindings[i].active = false;
mGameControllerBindings[i].button = SDL_CONTROLLER_BUTTON_INVALID;
mGameControllerBindings[i].active = false;
gameControllerBindings[i].button = SDL_CONTROLLER_BUTTON_INVALID;
gameControllerBindings[i].active = false;
}
discoverGameController();
@@ -23,20 +23,20 @@ Input::Input(std::string file)
// Destructor
Input::~Input()
{
for (int i = 0; i < mNumGamepads; i++)
mConnectedControllers[i] = nullptr;
for (int i = 0; i < numGamepads; i++)
connectedControllers[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;
keyBindings[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;
gameControllerBindings[input].button = button;
}
// Comprueba si un input esta activo
@@ -54,18 +54,18 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
if (repeat)
{
if (mKeystates[mKeyBindings[input].scancode] != 0)
if (mKeystates[keyBindings[input].scancode] != 0)
successKeyboard = true;
else
successKeyboard = false;
}
else
{
if (!mKeyBindings[input].active)
if (!keyBindings[input].active)
{
if (mKeystates[mKeyBindings[input].scancode] != 0)
if (mKeystates[keyBindings[input].scancode] != 0)
{
mKeyBindings[input].active = true;
keyBindings[input].active = true;
successKeyboard = true;
}
else
@@ -75,9 +75,9 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
else
{
if (mKeystates[mKeyBindings[input].scancode] == 0)
if (mKeystates[keyBindings[input].scancode] == 0)
{
mKeyBindings[input].active = false;
keyBindings[input].active = false;
successKeyboard = false;
}
else
@@ -93,18 +93,18 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
{
if (repeat)
{
if (SDL_GameControllerGetButton(mConnectedControllers[index], mGameControllerBindings[input].button) != 0)
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) != 0)
successGameController = true;
else
successGameController = false;
}
else
{
if (!mGameControllerBindings[input].active)
if (!gameControllerBindings[input].active)
{
if (SDL_GameControllerGetButton(mConnectedControllers[index], mGameControllerBindings[input].button) != 0)
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) != 0)
{
mGameControllerBindings[input].active = true;
gameControllerBindings[input].active = true;
successGameController = true;
}
else
@@ -114,9 +114,9 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
else
{
if (SDL_GameControllerGetButton(mConnectedControllers[index], mGameControllerBindings[input].button) == 0)
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) == 0)
{
mGameControllerBindings[input].active = false;
gameControllerBindings[input].active = false;
successGameController = false;
}
else
@@ -138,43 +138,43 @@ bool Input::discoverGameController()
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());
if (SDL_GameControllerAddMappingsFromFile(dbPath.c_str()) < 0)
printf("Error, could not load %s file: %s\n", dbPath.c_str(), SDL_GetError());
int nJoysticks = SDL_NumJoysticks();
mNumGamepads = 0;
numGamepads = 0;
// Cuenta el numero de mandos
for (int i = 0; i < nJoysticks; i++)
if (SDL_IsGameController(i))
mNumGamepads++;
numGamepads++;
printf("\nChecking for game controllers...\n");
printf("%i joysticks found, %i are gamepads\n", nJoysticks, mNumGamepads);
printf("%i joysticks found, %i are gamepads\n", nJoysticks, numGamepads);
if (mNumGamepads > 0)
if (numGamepads > 0)
{
found = true;
for (int i = 0; i < mNumGamepads; i++)
for (int i = 0; i < numGamepads; 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);
connectedControllers.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);
controllerNames.push_back(name);
}
else
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
//mGameController = mConnectedControllers[0];
//mGameController = connectedControllers[0];
SDL_GameControllerEventState(SDL_ENABLE);
}
@@ -184,7 +184,7 @@ bool Input::discoverGameController()
// Comprueba si hay algun mando conectado
bool Input::gameControllerFound()
{
if (mNumGamepads > 0)
if (numGamepads > 0)
return true;
else
return false;
@@ -193,8 +193,8 @@ bool Input::gameControllerFound()
// Obten el nombre de un mando de juego
std::string Input::getControllerName(int index)
{
if (mNumGamepads > 0)
return mControllerNames[index];
if (numGamepads > 0)
return controllerNames[index];
else
return "";
}
@@ -202,5 +202,5 @@ std::string Input::getControllerName(int index)
// Obten el numero de mandos conectados
int Input::getNumControllers()
{
return mNumGamepads;
return numGamepads;
}

View File

@@ -1,4 +1,5 @@
#pragma once
#include <SDL2/SDL.h>
#include <string>
#include <vector>
@@ -40,19 +41,19 @@ private:
Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo
};
keyBindings_t mKeyBindings[17]; // Vector con las teclas asociadas a los inputs predefinidos
keyBindings_t keyBindings[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
GameControllerBindings_t gameControllerBindings[17]; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<SDL_GameController *> mConnectedControllers; // Vector con todos los mandos conectados
std::vector<std::string> mControllerNames; // Vector con los nombres de los mandos
int mNumGamepads; // Numero de mandos conectados
std::string mDBpath; // Ruta al archivo gamecontrollerdb.txt
std::vector<SDL_GameController *> connectedControllers; // Vector con todos los mandos conectados
std::vector<std::string> controllerNames; // Vector con los nombres de los mandos
int numGamepads; // Numero de mandos conectados
std::string dbPath; // Ruta al archivo gamecontrollerdb.txt
// Comprueba si hay un mando conectado
bool discoverGameController();

103
source/intro.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include "intro.h"
// Constructor
Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset)
{
// Copia los punteros
this->renderer = renderer;
this->screen = screen;
this->asset = asset;
// Reserva memoria para los punteros
eventHandler = new SDL_Event();
texture = new LTexture();
loadTextureFromFile(texture, asset->get("intro.png"), renderer);
sprite = new AnimatedSprite(texture, renderer, asset->get("intro.ani"));
// Inicializa variables
section = {SECTION_PROG_INTRO, 0};
ticks = 0;
ticksSpeed = 15;
}
// Destructor
Intro::~Intro()
{
renderer = nullptr;
screen = nullptr;
asset = nullptr;
delete eventHandler;
eventHandler = nullptr;
texture->unload();
delete texture;
texture = nullptr;
delete sprite;
sprite = nullptr;
}
// Actualiza las variables
void Intro::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0)
{
// Evento de salida de la aplicación
if (eventHandler->type == SDL_QUIT)
{
section.name = SECTION_PROG_QUIT;
break;
}
// Cualquier tecla pulsada
if ((eventHandler->type == SDL_KEYDOWN) || (eventHandler->type == SDL_JOYBUTTONDOWN))
{
section.name = SECTION_PROG_TITLE;
section.subsection = 0;
}
}
sprite->animate();
// Comprueba si ha terminado la animación de la intro
if (sprite->animationIsCompleted())
{
section.name = SECTION_PROG_TITLE;
}
}
}
// Dibuja en pantalla
void Intro::render()
{
// Prepara para empezar a dibujar en la textura de juego
screen->start();
// Limpia la pantalla
screen->clean();
// Dibuja los objetos
sprite->render();
// Vuelca el contenido del renderizador en pantalla
screen->blit();
}
// Bucle principal
section_t Intro::run()
{
while (section.name == SECTION_PROG_INTRO)
{
update();
render();
}
return section;
}

45
source/intro.h Normal file
View File

@@ -0,0 +1,45 @@
#pragma once
#include <SDL2/SDL.h>
#include "const.h"
#include "asset.h"
#include "utils.h"
#include "screen.h"
#include "animatedsprite.h"
#include "jail_audio.h"
#ifndef INTRO_H
#define INTRO_H
// Clase Intro
class Intro
{
private:
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
LTexture *texture; // Textura con los graficos
SDL_Event *eventHandler; // Manejador de eventos
Asset *asset; // Objeto con los ficheros de recurso
AnimatedSprite *sprite; // Sprite para dibujar los graficos de la intro
section_t section; // Estado del bucle principal para saber si continua o se sale
int ticks; // Contador de ticks para ajustar la velocidad del programa
int ticksSpeed; // Velocidad a la que se repiten los bucles del programa
// Actualiza las variables
void update();
// Dibuja en pantalla
void render();
public:
// Constructor
Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset);
// Destructor
~Intro();
// Bucle principal
section_t run();
};
#endif

87
source/item_tracker.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include "item_tracker.h"
// Constructor
ItemTracker::ItemTracker()
{
}
// Destructor
ItemTracker::~ItemTracker()
{
list.clear();
}
// Comprueba si el objeto ya ha sido cogido
bool ItemTracker::hasBeenPicked(std::string name, SDL_Point pos)
{
bool success = false;
// Primero busca si ya hay una entrada con ese nombre
const int index = findByName(name);
if (index != -1)
{
// Luego busca si existe ya una entrada con esa posición
if (findByPos(index, pos) != -1)
{
success = true;
}
}
return success;
}
// Añade el objeto a la lista de objetos cogidos
void ItemTracker::addItem(std::string name, SDL_Point pos)
{
// Comprueba si el objeto no ha sido recogido con anterioridad
if (!hasBeenPicked(name, pos))
{
// Primero busca si ya hay una entrada con ese nombre
const int index = findByName(name);
if (index != -1)
{
list[index].pos.push_back(pos);
}
// En caso contrario crea la entrada
else
{
item_tracker_t item;
item.name = name;
item.pos.push_back(pos);
list.push_back(item);
}
}
}
// Busca una entrada en la lista por nombre
int ItemTracker::findByName(std::string name)
{
const int c = -1;
for (int i = 0; i < list.size(); i++)
{
if (list[i].name == name)
{
return i;
}
}
return c;
}
// Busca una entrada en la lista por posición
int ItemTracker::findByPos(int index, SDL_Point pos)
{
const int c = -1;
for (int i = 0; i < list[index].pos.size(); i++)
{
if ((list[index].pos[i].x == pos.x) && (list[index].pos[i].y == pos.y))
{
return i;
}
}
return c;
}

43
source/item_tracker.h Normal file
View File

@@ -0,0 +1,43 @@
#pragma once
#include <SDL2/SDL.h>
#include "utils.h"
#include <string>
#include <vector>
#ifndef ITEM_TRACKER_H
#define ITEM_TRACKER_H
struct item_tracker_t
{
std::string name; // Nombre de la habitación donde se encuentra el objeto
std::vector<SDL_Point> pos; // Lista de objetos cogidos de la habitación
};
// Clase Item_tracker
class ItemTracker
{
private:
std::vector<item_tracker_t> list; // Lista con todos los objetos recogidos
// Busca una entrada en la lista por nombre
int findByName(std::string name);
// Busca una entrada en la lista por posición
int findByPos(int index, SDL_Point pos);
public:
// Constructor
ItemTracker();
// Destructor
~ItemTracker();
// Comprueba si el objeto ya ha sido cogido
bool hasBeenPicked(std::string name, SDL_Point pos);
// Añade el objeto a la lista de objetos cogidos
void addItem(std::string name, SDL_Point pos);
};
#endif

View File

@@ -1,4 +1,5 @@
#pragma once
#include <SDL2/SDL.h>
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED };

137
source/logo.cpp Normal file
View File

@@ -0,0 +1,137 @@
#include "logo.h"
// Constructor
Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset)
{
// Copia la dirección de los objetos
this->renderer = renderer;
this->screen = screen;
this->asset = asset;
// Reserva memoria para los punteros
eventHandler = new SDL_Event();
texture = new LTexture();
loadTextureFromFile(texture, asset->get("logo.png"), renderer);
sprite = new Sprite(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, texture, renderer);
// Crea un backbuffer para el renderizador
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT);
if (backbuffer == NULL)
printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
// Inicializa variables
counter = 0;
section.name = SECTION_PROG_LOGO;
section.subsection = 0;
ticks = 0;
ticksSpeed = 15;
initFade = 100;
endLogo = 200;
postLogo = 20;
}
// Destructor
Logo::~Logo()
{
renderer = nullptr;
screen = nullptr;
asset = nullptr;
texture->unload();
delete texture;
texture = nullptr;
delete sprite;
sprite = nullptr;
delete eventHandler;
eventHandler = nullptr;
SDL_DestroyTexture(backbuffer);
backbuffer = nullptr;
}
// Actualiza las variables
void Logo::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0)
{
// Evento de salida de la aplicación
if (eventHandler->type == SDL_QUIT)
{
section.name = SECTION_PROG_QUIT;
break;
}
// Cualquier tecla pulsada
if ((eventHandler->type == SDL_KEYDOWN) || (eventHandler->type == SDL_JOYBUTTONDOWN))
{
section.name = SECTION_PROG_TITLE;
section.subsection = 0;
}
}
counter++;
// Comprueba si ha terminado el logo
if (counter == endLogo + postLogo)
{
section.name = SECTION_PROG_INTRO;
section.subsection = 0;
}
}
}
// Dibuja en pantalla
void Logo::render()
{
// Prepara para empezar a dibujar en la textura de juego
screen->start();
// Limpia la pantalla
screen->clean();
// Dibuja los objetos
sprite->render();
// Dibuja el fade
if (counter >= initFade)
{
const SDL_Rect rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
const color_t color = {0xFF, 0xFF, 0xFF};
const int fadeLenght = endLogo - initFade;
int alpha = (255 * (counter - initFade)) / fadeLenght;
if (alpha < 256)
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, alpha);
else
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
SDL_RenderFillRect(renderer, &rect);
}
// Vuelca el contenido del renderizador en pantalla
screen->blit();
}
// Bucle para el logo del juego
section_t Logo::run()
{
// Detiene la música
JA_StopMusic();
while (section.name == SECTION_PROG_LOGO)
{
update();
render();
}
return section;
}

50
source/logo.h Normal file
View File

@@ -0,0 +1,50 @@
#pragma once
#include <SDL2/SDL.h>
#include "const.h"
#include "utils.h"
#include "sprite.h"
#include "screen.h"
#include "asset.h"
#include "jail_audio.h"
#ifndef LOGO_H
#define LOGO_H
// Clase Logo
class Logo
{
private:
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
Asset *asset; // Objeto con los ficheros de recursos
LTexture *texture; // Textura con los graficos
SDL_Event *eventHandler; // Manejador de eventos
SDL_Texture *backbuffer; // Textura para usar como backbuffer
Sprite *sprite; // Sprite con la textura del logo
int counter; // Contador
section_t section; // Estado del bucle principal para saber si continua o se sale
int ticks; // Contador de ticks para ajustar la velocidad del programa
int ticksSpeed; // Velocidad a la que se repiten los bucles del programa
int initFade; // Tiempo del contador cuando inicia el fade a negro
int endLogo; // Tiempo del contador para terminar el logo
int postLogo; // Tiempo que dura el logo con el fade al maximo
// Actualiza las variables
void update();
// Dibuja en pantalla
void render();
public:
// Constructor
Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset);
// Destructor
~Logo();
// Bucle principal
section_t run();
};
#endif

View File

@@ -1,4 +1,5 @@
#pragma once
#include <SDL2/SDL.h>
#include <stdio.h>
#include <string>

View File

@@ -1,18 +1,26 @@
#include "map.h"
// Constructor
Map::Map(std::string file, SDL_Renderer *renderer, Asset *asset)
Map::Map(std::string file, SDL_Renderer *renderer, Asset *asset, ItemTracker *itemTracker)
{
// Inicializa variables
tile_size = 8;
map_width = 40;
map_height = 26;
tileset_width = 32;
name = file.substr(file.find_last_of("\\/") + 1);
enemy_file = "";
bgColor1 = bgColor2 = {0, 0, 0};
// Copia los punteros a objetos
this->asset = asset;
this->renderer = renderer;
this->itemTracker = itemTracker;
// Crea los objetos
texture_tile = new LTexture();
texture_bg = new LTexture();
load(file);
loadTextureFromFile(texture_tile, asset->get(tileset_img), renderer);
loadTextureFromFile(texture_bg, asset->get(bg_img), renderer);
// Crea la textura para el mapa de tiles de la habitación
map_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
@@ -21,11 +29,6 @@ Map::Map(std::string file, SDL_Renderer *renderer, Asset *asset)
// Pinta el mapa de la habitación en la textura
fillMapTexture();
// Inicializa variables
tile_width = 16;
map_width = 20;
map_height = 13;
}
// Destructor
@@ -35,10 +38,13 @@ Map::~Map()
texture_tile->unload();
delete texture_tile;
texture_bg->unload();
delete texture_bg;
SDL_DestroyTexture(map_texture);
for (auto actor : actors)
{
delete actor;
}
actors.clear();
}
// Carga las variables desde un fichero
@@ -99,7 +105,79 @@ bool Map::load(std::string file_path)
}
}
}
} while (line != "[tilemap-end]");
} while (line != "[/tilemap]");
}
// Si la linea contiene el texto [actor] se realiza el proceso de carga de los actores
else if (line == "[actors]")
{
do
{
std::getline(file, line);
if (line == "[moving platform]")
{
actor_t actor;
actor.asset = asset;
actor.renderer = renderer;
actor.name = a_moving_platform;
SDL_Point p1, p2;
do
{
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (!setActor(&actor, &p1, &p2, line.substr(0, pos), line.substr(pos + 1, line.length())))
{
printf("Warning: file %s\n, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
success = false;
}
} while (line != "[/moving platform]");
printf("** actor moving platform loaded\n\n");
actors.push_back(new ActorMovingPlatform(actor, p1, p2));
}
if (line == "[diamond]")
{
actor_t actor;
actor.asset = asset;
actor.renderer = renderer;
actor.name = a_diamond;
actor.vx = 0.0f;
actor.vy = 0.0f;
SDL_Point p1, p2;
do
{
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (!setActor(&actor, &p1, &p2, line.substr(0, pos), line.substr(pos + 1, line.length())))
{
printf("Warning: file %s\n, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
success = false;
}
} while (line != "[/diamond]");
// Comprueba si el actor no ha sido recogido previamente
if (!itemTracker->hasBeenPicked(name, {(int)actor.x, (int)actor.y}))
{
printf("** actor diamond loaded\n\n");
actors.push_back(new ActorDiamond(actor));
}
}
} while (line != "[/actors]");
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
@@ -117,7 +195,7 @@ bool Map::load(std::string file_path)
}
// Cierra el fichero
printf("Closing file %s\n", filename.c_str());
printf("Closing file %s\n\n", filename.c_str());
file.close();
}
// El fichero no se puede abrir
@@ -136,14 +214,34 @@ bool Map::setVars(std::string var, std::string value)
// Indicador de éxito en la asignación
bool success = true;
if (var == "bg_img")
{
bg_img = value;
}
else if (var == "tileset_img")
if (var == "tileset_img")
{
tileset_img = value;
}
else if (var == "bgColor1")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(value);
std::string tmp;
getline(ss, tmp, ',');
bgColor1.r = std::stoi(tmp);
getline(ss, tmp, ',');
bgColor1.g = std::stoi(tmp);
getline(ss, tmp, ',');
bgColor1.b = std::stoi(tmp);
}
else if (var == "bgColor2")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(value);
std::string tmp;
getline(ss, tmp, ',');
bgColor2.r = std::stoi(tmp);
getline(ss, tmp, ',');
bgColor2.g = std::stoi(tmp);
getline(ss, tmp, ',');
bgColor2.b = std::stoi(tmp);
}
else if (var == "room_up")
{
room_up = value;
@@ -160,15 +258,9 @@ bool Map::setVars(std::string var, std::string value)
{
room_right = value;
}
else if (var == "tilemap")
else if (var == "enemy_file")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(value);
std::string tmp;
while (getline(ss, tmp, ','))
{
tilemap.push_back(std::stoi(tmp));
}
enemy_file = value;
}
else if (var == "")
{
@@ -181,6 +273,71 @@ bool Map::setVars(std::string var, std::string value)
return success;
}
// Asigna variables a una estructura enemy_t
bool Map::setActor(actor_t *actor, SDL_Point *p1, SDL_Point *p2, std::string var, std::string value)
{
// Indicador de éxito en la asignación
bool success = true;
if (var == "tileset")
{
actor->tileset = value;
}
else if (var == "animation")
{
actor->animation = value;
}
else if (var == "width")
{
actor->w = std::stoi(value);
}
else if (var == "height")
{
actor->h = std::stoi(value);
}
else if (var == "x")
{
actor->x = std::stof(value) * tile_size;
}
else if (var == "y")
{
actor->y = std::stof(value) * tile_size;
}
else if (var == "vx")
{
actor->vx = std::stof(value);
}
else if (var == "vy")
{
actor->vy = std::stof(value);
}
else if (var == "x1")
{
p1->x = std::stoi(value) * tile_size;
}
else if (var == "x2")
{
p2->x = std::stoi(value) * tile_size;
}
else if (var == "y1")
{
p1->y = std::stoi(value) * tile_size;
}
else if (var == "y2")
{
p2->y = std::stoi(value) * tile_size;
}
else if ((var == "[/moving platform]") || (var == "[/diamond]"))
{
}
else
{
success = false;
}
return success;
}
// Crea la textura con el mapeado de la habitación
void Map::fillMapTexture()
{
@@ -189,23 +346,27 @@ void Map::fillMapTexture()
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer);
// Dibuja la textura de fondo
SDL_Rect clip = {0, 0, 320, 208};
texture_bg->render(renderer, 0, 0, &clip);
// Dibuja el degradado de fondo
const int num_lines = 208;
for (int i = 0; i < num_lines; i++)
{
float step = ((float)i / (float)num_lines);
int r = bgColor1.r + ((bgColor2.r - bgColor1.r) * step);
int g = bgColor1.g + ((bgColor2.g - bgColor1.g) * step);
int b = bgColor1.b + ((bgColor2.b - bgColor1.b) * step);
SDL_SetRenderDrawColor(renderer, r, g, b, 0xFF);
SDL_RenderDrawLine(renderer, 0, i, 319, i);
}
// Dibuja el mapeado de tiles
const int tile_size = 16;
const int tileset_width_in_tiles = 16;
const int map_width_in_tiles = 20;
const int map_height_in_tiles = 13;
SDL_Rect clip = {0, 0, tile_size, tile_size};
clip = {0, 0, tile_size, tile_size};
for (int y = 0; y < map_height_in_tiles; y++)
for (int x = 0; x < map_width_in_tiles; x++)
for (int y = 0; y < map_height; y++)
for (int x = 0; x < map_width; x++)
{
clip.x = ((tilemap[(y * map_width_in_tiles) + x] - 1) % tileset_width_in_tiles) * tile_size;
clip.y = ((tilemap[(y * map_width_in_tiles) + x] - 1) / tileset_width_in_tiles) * tile_size;
clip.x = ((tilemap[(y * map_width) + x] - 1) % tileset_width) * tile_size;
clip.y = ((tilemap[(y * map_width) + x] - 1) / tileset_width) * tile_size;
texture_tile->render(renderer, x * tile_size, y * tile_size, &clip);
}
@@ -219,12 +380,14 @@ void Map::fillMapTexture()
}
// Dibuja el marco del marcador
SDL_SetRenderDrawColor(renderer, 85, 50, 85, 0xFF);
SDL_Rect rect = {0, 208, 320, 32};
SDL_RenderDrawRect(renderer, &rect);
rect = {1, 209, 318, 30};
SDL_RenderDrawRect(renderer, &rect);
// SDL_SetRenderDrawColor(renderer, 85, 50, 85, 0xFF);
// SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
// SDL_Rect rect = {0, 208, 320, 32};
// SDL_RenderDrawRect(renderer, &rect);
// rect = {1, 209, 318, 30};
// SDL_RenderDrawRect(renderer, &rect);
// Vuelve a colocar el renderizador
SDL_SetRenderTarget(renderer, nullptr);
}
@@ -234,24 +397,210 @@ void Map::render()
// Dibuja la textura con el mapa en pantalla
SDL_Rect rect = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
SDL_RenderCopy(renderer, map_texture, &rect, NULL);
for (auto actor : actors)
{
actor->render();
}
}
// Actualiza todas las variables
void Map::update()
{
for (auto actor : actors)
{
actor->update();
}
}
// Devuelve el tipo de tile que hay en un punto
t_tile_map Map::getTile(SDL_Point p)
e_tile_map Map::getTile(SDL_Point p)
{
const int tile = tilemap[((p.y / tile_width) * map_width) + (p.x / tile_width)];
const int png_width = 16;
// Normalizamos los puntos para que no busque fuera del mapa
const int x = std::max(getPlayArea(b_left), (std::min(p.x, getPlayArea(b_right) - 1)));
const int y = std::max(getPlayArea(b_top), (std::min(p.y, getPlayArea(b_bottom) - 1)));
if (tile >= 0 && tile < 4 * png_width)
// Calcula el tile
const int tile = tilemap[((y / tile_size) * map_width) + (x / tile_size)];
const int png_width = 32;
// Las 8 primeras filas son tiles de fondo
if (tile >= 0 && tile < 8 * png_width)
{
return nothing;
}
else if (tile >= (4 * png_width) && tile < 8 * png_width)
// De la fila 8 a la 15 hay tiles de muro
else if (tile >= (8 * png_width) && tile < 16 * png_width)
{
return wall;
}
// A partir de la fila 16 son tiles atravesables
else
{
return travessable;
return passable;
}
return nothing;
}
// Devuelve el valor de la variable
int Map::getTileSize()
{
return tile_size;
}
// Devuelve el indice del tile correspondiente a un punto del mapa
int Map::getTileIndex(SDL_Point p)
{
return tilemap[((p.y / tile_size) * map_width) + (p.x / tile_size)];
}
// Devuelve el valor de los bordes de la zona de juego
int Map::getPlayArea(e_border border)
{
switch (border)
{
case b_top:
return 0;
break;
case b_left:
return 0;
break;
case b_right:
return tile_size * map_width;
break;
case b_bottom:
return tile_size * map_height;
break;
default:
break;
}
return -1;
}
// Devuelve el nombre del fichero de la habitación en funcion del borde
std::string Map::getRoomFileName(e_border border)
{
switch (border)
{
case b_top:
return room_up;
break;
case b_left:
return room_left;
break;
case b_right:
return room_right;
break;
case b_bottom:
return room_down;
break;
default:
break;
}
return "";
}
// Indica si hay colision con un actor a partir de un rectangulo
int Map::actorCollision(SDL_Rect &rect)
{
int index = 0;
for (auto actor : actors)
{
if (checkCollision(rect, actor->getCollider()))
{
return index;
}
index++;
}
return -1;
}
// Indica si hay colision con un actor a partir de un rectangulo
int Map::actorCollision(SDL_Point &p)
{
int index = 0;
for (auto actor : actors)
{
if (checkCollision(p, actor->getCollider()))
{
return index;
}
index++;
}
return -1;
}
// Devuelve el nombre del actor a pàrtir de un índice
int Map::getActorName(int index)
{
if (index != -1)
{
return actors[index]->getName();
}
return -1;
}
// Devuelve el rectangulo de colisión
SDL_Rect Map::getActorCollider(int index)
{
SDL_Rect rect = {0, 0, 0, 0};
if (index != -1)
{
rect = actors[index]->getCollider();
}
return rect;
}
// Devuelve el desplazamiento relativo del actor
int Map::getActorIncX(int index)
{
int shift = 0;
if (index != -1)
{
shift = actors[index]->getIncX();
}
return shift;
}
// Elimina un actor
bool Map::deleteActor(int index)
{
bool success = false;
if (actors[index] != nullptr)
{
delete actors[index];
success = true;
}
actors.erase(actors.begin() + index);
return success;
}
// Coge un item
void Map::getItem(int index)
{
const SDL_Rect r = getActorCollider(index);
itemTracker->addItem(name, {r.x, r.y});
}
// Obtiene el valor de la variable
std::string Map::getEnemyFile()
{
return enemy_file;
}

View File

@@ -4,6 +4,9 @@
#include "utils.h"
#include "asset.h"
#include "const.h"
#include "item_tracker.h"
#include "actor_moving_platform.h"
#include "actor_diamond.h"
#include <string>
#include <vector>
#include <sstream>
@@ -12,11 +15,20 @@
#ifndef MAP_H
#define MAP_H
enum t_tile_map
enum e_tile_map
{
nothing,
wall,
travessable
passable
};
enum e_border
{
b_none,
b_top,
b_bottom,
b_left,
b_right
};
// The player
@@ -25,20 +37,25 @@ class Map
private:
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
SDL_Renderer *renderer; // El renderizador de la ventana
std::string name; // Identificador de la habitación
std::string room_up; // Identificador de la habitación que se encuentra arriba
std::string room_down; // Identificador de la habitación que se encuentra abajp
std::string room_left; // Identificador de la habitación que se encuentra a la izquierda
std::string room_right; // Identificador de la habitación que se encuentra a la derecha
std::string enemy_file; // Fichero con los enemigos para la habitación
std::string tileset_img; // Imagen con los graficos para la habitación
std::string bg_img; // Imagen con los graficos para la habitación
std::vector<int> tilemap; // Indice de los tiles a dibujar en la habitación
LTexture *texture_tile; // Textura con los graficos de los tiles habitación
LTexture *texture_bg; // Textura con los graficos de fondo de la habitación
SDL_Texture *map_texture; // Textura para dibujar el mapa de la habitación
std::vector<Actor *> actors; // Listado con los actores de la habitación
color_t bgColor1; // Color superior del degradado de fondo
color_t bgColor2; // Color inferior del degradado de fondo
ItemTracker *itemTracker; // Objeto que gestiona los items que ya se han recogido
int tile_width; // Ancho del tile en pixels
int tile_size; // Ancho del tile en pixels
int map_width; // Ancho del mapa en tiles
int map_height; // Alto del mapa en tiles
int tileset_width; // Ancho del tileset en tiles
// Carga las variables desde un fichero
bool load(std::string file);
@@ -46,12 +63,15 @@ private:
// Asigna variables a partir de dos cadenas
bool setVars(std::string var, std::string value);
// Asigna variables a una estructura actor_t
bool setActor(actor_t *actor, SDL_Point *p1, SDL_Point *p2, std::string var, std::string value);
// Pinta el mapa de la habitación en la textura
void fillMapTexture();
public:
// Constructor
Map(std::string file, SDL_Renderer *renderer, Asset *asset);
Map(std::string file, SDL_Renderer *renderer, Asset *asset, ItemTracker *itemTracker);
// Destructor
~Map();
@@ -63,7 +83,43 @@ public:
void render();
// Devuelve el tipo de tile que hay en un punto
t_tile_map getTile(SDL_Point p);
e_tile_map getTile(SDL_Point p);
// Devuelve el valor de la variable
int getTileSize();
// Devuelve el indice del tile correspondiente a un punto del mapa
int getTileIndex(SDL_Point p);
// Devuelve el valor de los bordes de la zona de juego
int getPlayArea(e_border border);
// Devuelve el nombre del fichero de la habitación en funcion del borde
std::string getRoomFileName(e_border border);
// Indica si hay colision con un actor a partir de un rectangulo
int actorCollision(SDL_Rect &rect);
// Indica si hay colision con un actor a partir de un punto
int actorCollision(SDL_Point &p);
// Devuelve el nombre del actor a pàrtir de un índice
int getActorName(int index);
// Devuelve el rectangulo de colisión
SDL_Rect getActorCollider(int index);
// Devuelve el desplazamiento relativo del actor
int getActorIncX(int index);
// Elimina un actor
bool deleteActor(int index);
// Coge un item
void getItem(int index);
// Obtiene el valor de la variable
std::string getEnemyFile();
};
#endif

613
source/menu.cpp Normal file
View File

@@ -0,0 +1,613 @@
#include "const.h"
#include "menu.h"
// Constructor
Menu::Menu(SDL_Renderer *renderer, Text *text, Input *input)
{
this->renderer = renderer;
this->text = text;
this->input = input;
soundMove = nullptr;
soundAccept = nullptr;
soundCancel = nullptr;
}
Menu::~Menu()
{
renderer = nullptr;
text = nullptr;
input = nullptr;
if (soundMove)
{
JA_DeleteSound(soundMove);
}
if (soundAccept)
{
JA_DeleteSound(soundAccept);
}
if (soundCancel)
{
JA_DeleteSound(soundCancel);
}
}
// Inicializador
void Menu::init(std::string name, int x, int y, int backgroundType)
{
// Inicia variables
this->name = name;
selector.index = 0;
itemSelected = MENU_NO_OPTION;
this->x = x;
this->y = y;
rectBG.rect = {0, 0, 0, 0};
rectBG.color = {0, 0, 0};
rectBG.a = 0;
this->backgroundType = backgroundType;
isCenteredOnX = false;
isCenteredOnY = false;
areElementsCenteredOnX = false;
centerX = 0;
centerY = 0;
widestItem = 0;
colorGreyed = {128, 128, 128};
// Selector
selector.originY = 0;
selector.targetY = 0;
selector.despY = 0;
selector.originH = 0;
selector.targetH = 0;
selector.incH = 0;
selector.y = 0.0f;
selector.h = 0.0f;
selector.numJumps = 8;
selector.moving = false;
selector.resizing = false;
selector.rect = {0, 0, 0, 0};
selector.color = {0, 0, 0};
selector.itemColor = {0, 0, 0};
selector.a = 255;
}
// Carga los ficheros de audio
void Menu::loadAudioFile(std::string file, int sound)
{
switch (sound)
{
case SOUND_ACCEPT:
soundAccept = JA_LoadSound(file.c_str());
break;
case SOUND_CANCEL:
soundCancel = JA_LoadSound(file.c_str());
break;
case SOUND_MOVE:
soundMove = JA_LoadSound(file.c_str());
break;
default:
break;
}
}
// Obtiene el nombre del menu
std::string Menu::getName()
{
return name;
}
// Obtiene el valor de la variable
int Menu::getItemSelected()
{
// Al llamar a esta funcion, se obtiene el valor y se borra
const int temp = itemSelected;
itemSelected = MENU_NO_OPTION;
return temp;
}
// Actualiza la posicion y el estado del selector
void Menu::updateSelector()
{
if (selector.moving)
{
// Calcula el desplazamiento en Y
selector.y += selector.despY;
if (selector.despY > 0) // Va hacia abajo
{
if (selector.y > selector.targetY) // Ha llegado al destino
{
selector.originY = selector.y = selector.targetY;
selector.moving = false;
}
}
if (selector.despY < 0) // Va hacia arriba
{
if (selector.y < selector.targetY) // Ha llegado al destino
{
selector.originY = selector.y = selector.targetY;
selector.moving = false;
}
}
selector.rect.y = int(selector.y);
}
else
{
selector.rect.y = int(selector.y);
}
if (selector.resizing)
{
// Calcula el incremento en H
selector.h += selector.incH;
if (selector.incH > 0) // Crece
{
if (selector.h > selector.targetH) // Ha llegado al destino
{
// selector.originH = selector.targetH = selector.rect.h = getSelectorHeight(selector.index);
selector.originH = selector.h = selector.targetH;
selector.resizing = false;
}
}
if (selector.incH < 0) // Decrece
{
if (selector.h < selector.targetH) // Ha llegado al destino
{
// selector.originH = selector.targetH = selector.rect.h = getSelectorHeight(selector.index);
selector.originH = selector.h = selector.targetH;
selector.resizing = false;
}
}
selector.rect.h = int(selector.h);
}
else
{
selector.rect.h = getSelectorHeight(selector.index);
}
}
// Coloca el selector en una posición específica
void Menu::setSelectorPos(int index)
{
if (index < item.size())
{
selector.index = index;
selector.rect.y = selector.y = selector.originY = selector.targetY = item[selector.index].rect.y;
selector.rect.w = rectBG.rect.w;
selector.rect.x = rectBG.rect.x;
selector.originH = selector.targetH = selector.rect.h = getSelectorHeight(selector.index);
selector.moving = false;
selector.resizing = false;
}
}
// Obtiene la anchura del elemento más ancho del menu
int Menu::getWidestItem()
{
int result = 0;
// Obtenemos la anchura del item mas ancho
for (auto &i : item)
{
result = std::max(result, i.rect.w);
}
return result;
}
// Deja el menu apuntando al primer elemento
void Menu::reset()
{
itemSelected = MENU_NO_OPTION;
selector.index = 0;
selector.originY = selector.targetY = selector.y = item[0].rect.y;
selector.originH = selector.targetH = item[0].rect.h;
selector.moving = false;
selector.resizing = false;
}
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void Menu::reorganize()
{
setRectSize();
if (isCenteredOnX)
{
centerMenuOnX(centerX);
}
if (isCenteredOnY)
{
centerMenuOnY(centerY);
}
if (areElementsCenteredOnX)
{
centerMenuElementsOnX();
}
}
// Deja el menu apuntando al siguiente elemento
bool Menu::increaseSelectorIndex()
{
// Obten las coordenadas del elemento actual
selector.y = selector.originY = item[selector.index].rect.y;
selector.h = selector.originH = getSelectorHeight(selector.index);
// Calcula cual es el siguiente elemento
++selector.index %= item.size();
while (!item[selector.index].selectable)
{
++selector.index %= item.size();
}
// Establece las coordenadas y altura de destino
selector.targetY = item[selector.index].rect.y;
selector.despY = (selector.targetY - selector.originY) / selector.numJumps;
selector.targetH = getSelectorHeight(selector.index);
selector.incH = (selector.targetH - selector.originH) / selector.numJumps;
selector.moving = true;
if (selector.incH != 0)
{
selector.resizing = true;
}
return true;
}
// Deja el menu apuntando al elemento anterior
bool Menu::decreaseSelectorIndex()
{
// Obten las coordenadas del elemento actual
selector.y = selector.originY = item[selector.index].rect.y;
selector.h = selector.originH = getSelectorHeight(selector.index);
// Calcula cual es el siguiente elemento
if (selector.index == 0)
{
selector.index = item.size();
}
else
{
selector.index--;
}
while (!item[selector.index].selectable)
{
if (selector.index == 0)
{
selector.index = item.size();
}
else
{
selector.index--;
}
}
// Establece las coordenadas y altura de destino
selector.targetY = item[selector.index].rect.y;
selector.despY = (selector.targetY - selector.originY) / selector.numJumps;
selector.targetH = getSelectorHeight(selector.index);
selector.incH = (selector.targetH - selector.originH) / selector.numJumps;
selector.moving = true;
if (selector.incH != 0)
{
selector.resizing = true;
}
return true;
}
// Actualiza la logica del menu
void Menu::update()
{
checkInput();
updateSelector();
}
// Pinta el menu en pantalla
void Menu::render()
{
// Rendereritza el fondo del menu
if (backgroundType == MENU_BACKGROUND_SOLID)
{
SDL_SetRenderDrawColor(renderer, rectBG.color.r, rectBG.color.g, rectBG.color.b, rectBG.a);
SDL_RenderFillRect(renderer, &rectBG.rect);
}
// Renderiza el rectangulo del selector
const SDL_Rect temp = {selector.rect.x, selector.rect.y - 1, selector.rect.w, selector.rect.h + 1};
// temp.y--;
// temp.h++;
SDL_SetRenderDrawColor(renderer, selector.color.r, selector.color.g, selector.color.b, selector.a);
SDL_RenderFillRect(renderer, &temp);
// Renderiza el borde del fondo
if (backgroundType == MENU_BACKGROUND_SOLID)
{
SDL_SetRenderDrawColor(renderer, rectBG.color.r, rectBG.color.g, rectBG.color.b, 255);
SDL_RenderDrawRect(renderer, &rectBG.rect);
}
// Renderitza el texto
for (int i = 0; i < item.size(); i++)
{
if (i == selector.index)
{
const color_t color = {selector.itemColor.r, selector.itemColor.g, selector.itemColor.b};
text->writeColored(item[i].rect.x, item[i].rect.y, item[i].label, color);
}
else if (item[i].selectable)
{
text->write(item[i].rect.x, item[i].rect.y, item[i].label);
}
else if (item[i].greyed)
{
text->writeColored(item[i].rect.x, item[i].rect.y, item[i].label, colorGreyed);
}
else
// No seleccionable
{
if ((item[i].linkedUp) && (i == selector.index + 1))
{
const color_t color = {selector.itemColor.r, selector.itemColor.g, selector.itemColor.b};
text->writeColored(item[i].rect.x, item[i].rect.y, item[i].label, color);
}
else // No enlazado con el de arriba
{
text->write(item[i].rect.x, item[i].rect.y, item[i].label);
}
}
}
}
// Establece el rectangulo de fondo del menu y el selector
void Menu::setRectSize()
{
rectBG.rect.w = findWidth() + text->getCharacterWidth();
rectBG.rect.h = findHeight() + text->getCharacterWidth();
// La posición X es la del menú menos medio caracter
rectBG.rect.x = x - (text->getCharacterWidth() / 2);
// La posición Y es la del menu menos la altura de medio caracter
rectBG.rect.y = y - (text->getCharacterWidth() / 2);
// Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo
setSelectorPos(selector.index);
}
// Establece el color del rectangulo de fondo
void Menu::setBackgroundColor(color_t color, int alpha)
{
rectBG.color = color;
rectBG.a = alpha;
}
// Establece el color del rectangulo del selector
void Menu::setSelectorColor(color_t color, int alpha)
{
selector.color = color;
selector.a = alpha;
}
// Establece el color del texto del selector
void Menu::setSelectorTextColor(color_t color)
{
selector.itemColor = color;
}
// Centra el menu respecto un punto en el eje X
void Menu::centerMenuOnX(int value)
{
isCenteredOnX = true;
centerX = value;
// Establece la nueva posición centrada en funcion del elemento más ancho
x = (value) - (findWidth() / 2);
// Reposiciona los elementos del menu
for (auto &i : item)
{
i.rect.x = x;
}
// Recalcula el rectangulo de fondo
setRectSize();
}
// Centra el menu respecto un punto en el eje Y
void Menu::centerMenuOnY(int value)
{
isCenteredOnY = true;
centerY = value;
// Establece la nueva posición centrada en funcion del elemento más ancho
y = (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()
{
areElementsCenteredOnX = true;
for (auto &i : item)
{
i.rect.x = (centerX - (i.rect.w / 2));
}
}
// Añade un item al menu
void Menu::addItem(std::string text, int hPaddingDown, bool selectable, bool greyed, bool linkedDown)
{
item_t temp;
// Si es el primer item coge la posición en el eje Y del propio menu
if (item.size() == 0)
{
temp.rect.y = y;
}
else
// En caso contrario, coge la posición en el eje Y a partir del elemento anterior
{
temp.rect.y = item.back().rect.y + item.back().rect.h + item.back().hPaddingDown;
}
temp.rect.x = x;
temp.hPaddingDown = hPaddingDown;
temp.selectable = selectable;
temp.greyed = greyed;
temp.linkedDown = linkedDown;
item.push_back(temp);
setItemCaption(item.size() - 1, text);
if (item.size() > 0)
{
if (item[item.size() - 1].linkedDown)
{
item[item.size()].linkedUp = true;
}
}
centerX = x + (findWidth() / 2);
reorganize();
}
// Cambia el texto de un item
void Menu::setItemCaption(int index, std::string text)
{
item[index].label = text;
item[index].rect.w = this->text->lenght(item[index].label);
item[index].rect.h = this->text->getCharacterWidth();
reorganize();
const std::string texto = item[index].label + ":" + std::to_string(item[index].rect.w);
printf("Adding menu item -> %s\n", texto.c_str());
}
// Establece el indice del itemm que se usará por defecto al cancelar el menu
void Menu::setDefaultActionWhenCancel(int item)
{
defaultActionWhenCancel = item;
}
// Gestiona la entrada de teclado y mando durante el menu
void Menu::checkInput()
{
if (input->checkInput(INPUT_UP, REPEAT_FALSE))
{
if (decreaseSelectorIndex())
{
if (soundMove)
{
JA_PlaySound(soundMove);
}
}
}
if (input->checkInput(INPUT_DOWN, REPEAT_FALSE))
{
if (increaseSelectorIndex())
{
if (soundMove)
{
JA_PlaySound(soundMove);
}
}
}
if (input->checkInput(INPUT_ACCEPT, REPEAT_FALSE))
{
itemSelected = selector.index;
if (soundAccept)
{
JA_PlaySound(soundAccept);
}
}
if (input->checkInput(INPUT_CANCEL, REPEAT_FALSE))
{
itemSelected = defaultActionWhenCancel;
if (soundCancel)
{
JA_PlaySound(soundCancel);
}
}
}
// Calcula el ancho del menu
int Menu::findWidth()
{
return getWidestItem();
}
// Calcula el alto del menu
int Menu::findHeight()
{
int height = 0;
// Obtenemos la altura de la suma de alturas de los items
for (auto &i : item)
{
height += i.rect.h + i.hPaddingDown;
}
return height - item.back().hPaddingDown;
}
// Recoloca los elementos del menu en el eje Y
void Menu::replaceElementsOnY()
{
item[0].rect.y = y;
for (int i = 1; i < item.size(); i++)
{
item[i].rect.y = item[i - 1].rect.y + item[i - 1].rect.h + item[i - 1].hPaddingDown;
}
}
// Establece el estado seleccionable de un item
void Menu::setSelectable(int index, bool value)
{
item[index].selectable = value;
}
// Establece el estado agrisado de un item
void Menu::setGreyed(int index, bool value)
{
item[index].greyed = value;
}
// Establece el estado de enlace de un item
void Menu::setLinkedDown(int index, bool value)
{
item[index].linkedDown = value;
}
// Calcula la altura del selector
int Menu::getSelectorHeight(int value)
{
if (item[value].linkedDown)
{
return item[value].rect.h + item[value].hPaddingDown + item[value + 1].rect.h;
}
else
{
return item[value].rect.h;
}
}

197
source/menu.h Normal file
View File

@@ -0,0 +1,197 @@
#pragma once
#include <SDL2/SDL.h>
#include <vector>
#include "sprite.h"
#include "text.h"
#include "input.h"
#include "utils.h"
#include "jail_audio.h"
#ifndef MENU_H
#define MENU_H
// Tipos de fondos para el menu
#define MENU_BACKGROUND_TRANSPARENT 0
#define MENU_BACKGROUND_SOLID 1
// Tipos de archivos de audio
#define SOUND_ACCEPT 0
#define SOUND_MOVE 1
#define SOUND_CANCEL 2
// Opciones de menu
#define MENU_NO_OPTION -1
// Clase Menu
class Menu
{
private:
struct rectangle_t
{
SDL_Rect rect; // Rectangulo
color_t color; // Color
int a; // Transparencia
};
struct item_t
{
std::string label; // Texto
SDL_Rect rect; // Rectangulo que delimita el elemento
int 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
};
struct selector_t
{
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
int numJumps; // Numero de pasos preestablecido para llegar al destino
int index; // Elemento del menu que tiene el foco
SDL_Rect rect; // Rectangulo del selector
color_t color; // Color del selector
color_t itemColor; // Color del item
int a; // Cantidad de transparencia para el rectangulo del selector
};
std::string name; // Nombre del menu
int x; // Posición en el eje X de la primera letra del primer elemento
int y; // Posición en el eje Y de la primera letra del primer elemento
int h; // Altura del menu
int w; // Anchura del menu
int itemSelected; // Índice del item del menu que ha sido seleccionado
int defaultActionWhenCancel; // Indice del item del menu que se selecciona cuando se cancela el menu
int backgroundType; // Tipo de fondo para el menu
int centerX; // Centro del menu en el eje X
int centerY; // Centro del menu en el eje Y
bool isCenteredOnX; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje X
bool isCenteredOnY; // Variable para saber si el menu debe estar centrado respecto a un punto en el eje Y
bool areElementsCenteredOnX; // Variable para saber si los elementos van centrados en el eje X
int widestItem; // Anchura del elemento más ancho
JA_Sound soundAccept; // Sonido al aceptar o elegir una opción del menu
JA_Sound soundCancel; // Sonido al cancelar el menu
JA_Sound soundMove; // Sonido al mover el selector
SDL_Renderer *renderer; // Puntero al renderizador de la ventana
Text *text; // Texto para poder escribir los items del menu
Input *input; // Gestor de eventos de entrada de teclado o gamepad
color_t colorGreyed; // Color para los elementos agrisados
rectangle_t rectBG; // Rectangulo de fondo del menu
std::vector<item_t> item; // Estructura para cada elemento del menu
selector_t selector; // Variables para pintar el selector del menu
// Establece el rectangulo de fondo del menu
void setRectSize();
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void reorganize();
// Deja el menu apuntando al siguiente elemento
bool increaseSelectorIndex();
// Deja el menu apuntando al elemento anterior
bool decreaseSelectorIndex();
// Actualiza la posicion y el estado del selector
void updateSelector();
// Obtiene la anchura del elemento más ancho del menu
int getWidestItem();
// Gestiona la entrada de teclado y mando durante el menu
void checkMenuInput(Menu *menu);
// Calcula el ancho del menu
int findWidth();
// Calcula el alto del menu
int findHeight();
// Recoloca los elementos del menu en el eje Y
void replaceElementsOnY();
// Calcula la altura del selector
int getSelectorHeight(int value);
public:
// Constructor
Menu(SDL_Renderer *renderer, Text *text, Input *input);
// Destructor
~Menu();
// Inicializador
void init(std::string name, int x, int y, int backgroundType);
// Carga los ficheros de audio
void loadAudioFile(std::string file, int sound);
// Obtiene el nombre del menu
std::string getName();
// Obtiene el valor de la variable
int getItemSelected();
// Deja el menu apuntando al primer elemento
void reset();
// Gestiona la entrada de teclado y mando durante el menu
void checkInput();
// Actualiza la logica del menu
void update();
// Pinta el menu en pantalla
void render();
// Establece el color del rectangulo de fondo
void setBackgroundColor(color_t color, int alpha);
// Establece el color del rectangulo del selector
void setSelectorColor(color_t color, int alpha);
// Establece el color del texto del selector
void setSelectorTextColor(color_t color);
// Centra el menu respecto a un punto en el eje X
void centerMenuOnX(int value);
// Centra el menu respecto a un punto en el eje Y
void centerMenuOnY(int value);
// Centra los elementos del menu en el eje X
void centerMenuElementsOnX();
// Añade un item al menu
void addItem(std::string text, int hPaddingDown = 1, bool selectable = true, bool greyed = false, bool linkedDown = false);
// Cambia el texto de un item
void setItemCaption(int index, std::string text);
// Establece el indice del item que se usará por defecto al cancelar el menu
void setDefaultActionWhenCancel(int item);
// Coloca el selector en una posición específica
void setSelectorPos(int index);
// Establece el estado seleccionable de un item
void setSelectable(int index, bool value);
// Establece el estado agrisado de un item
void setGreyed(int index, bool value);
// Establece el estado de enlace de un item
void setLinkedDown(int index, bool value);
};
#endif

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