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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
/*
* player.h -- Implementa el personaje controlado por el jugador.
* Copyright (C) 2018 Juan Marín Noguera
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file player.h Implementa el personaje controlado por el jugador.
*/
#ifndef __PLAYER_H
#define __PLAYER_H
#include "screen.h"
/** Ancho del personaje en píxeles. */
#define PLAYER_WIDTH 16
/** Representa el estado del personaje. */
typedef enum PlayerState {
/** Indica que el personaje está en estado "pequeño". */
PLAYER_ST_SMALL = 1,
/** Indica que el personaje está en estado "grande". */
PLAYER_ST_BIG = 2,
/** Indica que el personaje está en estado "flor". */
PLAYER_ST_FLOWER = 3,
/** Indica que el personaje está muerto. */
PLAYER_ST_DEAD = 0
} PlayerState;
/** Representa la posición relativa del personaje (de pie, saltando o
* agachado).
*/
typedef enum PlayerPos {
/** Indica que el personaje está de pie. */
PLAYER_POS_UPRIGHT,
/** Indica que el personaje está saltando. */
PLAYER_POS_JUMP,
/** Indica que el personaje está agachado. */
PLAYER_POS_GROUND
} PlayerPos;
/** Representa al personaje. */
typedef struct Player *Player;
/**
* \brief Crea una instancia de personaje.
* \param x La coordenada X de la posición de inicio.
* \param y La coordenada Y de la posición de inicio.
* \param lives El número de vidas con el que empieza.
* \return El personaje creado.
* \remarks Al crearse, el personaje está de pie, parado y mirando hacia
* la derecha.
*/
Player player_create(int x, int y, int lives);
/**
* \brief Libera una instancia de personaje.
* \param p El personaje a liberar.
*/
void player_free(Player p);
/**
* \brief Libera los recursos (im´genes) alojados por este TDA de forma
* global. Debe ser llamado antes de screen_end.
*/
void player_end();
/**
* \brief Obtiene la coordenada X de la posición actual del personaje.
* \param p El personaje.
* \return La coordenada X del personaje.
*/
double player_x(Player p);
/**
* \brief Establece la coordenada X de la posición del personaje.
* \param p El personaje.
* \param x El nuevo valor de la coordenada X.
*/
void player_set_x(Player p, double x);
/**
* \brief Obtiene la coordenada Y de la posición actual del personaje.
* \param p El personaje.
* \return La coordenada Y del personaje.
*/
double player_y(Player p);
/**
* \brief Establece la coordenada Y de la posición del personaje.
* \param p El personaje.
* \param y El nuevo valor de la coordenada Y.
*/
void player_set_y(Player p, double y);
/**
* \brief Obtiene la velocidad horizontal del personaje.
* \param p El personaje.
* \return La componente horizontal de la velocidad actual del personaje.
*/
double player_vx(Player p);
/**
* \brief Obtiene la velocidad vertical del personaje.
* \param p El personaje.
* \return La componente vertical de la velocidad actual del personaje.
*/
double player_vy(Player p);
/**
* \brief Obtiene el estado actual del personaje.
* \param p El personaje.
* \return El estado del personaje. Puede ser PLAYER_ST_SMALL, PLAYER_ST_BIG o
* PLAYER_ST_FLOWER.
*/
PlayerState player_state(Player p);
/**
* \brief Obtiene el número de monedas recogidas por el personaje.
* \param p El personaje.
* \return El número de monedas que tiene.
*/
int player_coins(Player p);
/**
* \brief Obtiene el número de vidas que le quedan al personaje,
* incluyendo la que esté siendo usada en el momento actual.
*/
int player_lives(Player p);
/**
* \brief Obtiene la posición (postura) actual del personaje.
* \param p El personaje.
* \return La posición del personale. Puede ser PLAYER_POS_UPRIGHT,
* PLAYER_POS_JUMP o PLAYER_POS_GROUND.
*/
PlayerPos player_pos(Player p);
/**
* \brief Obtiene la altura del personaje.
* \param p El personaje.
* \return La altura actual del personaje en píxeles.
*/
int player_height(Player p);
/**
* \brief Establece la posición actual del personaje.
* \param p El personaje.
* \param pos La nueva posición del personaje. Puede ser
* PLAYER_POS_UPRIGHT, PLAYER_POS_JUMP o PLAYER_POS_GROUND.
*/
void player_set_pos(Player p, PlayerPos pos);
/**
* \brief Actualiza la posición del personaje por un frame.
* \param p El personaje.
* \remarks La función actúa como si no hubiera nada alrededor del
* personaje (cae). Para evitarlo, se debe llamar posteriormente a
* player_correct_on_collision.
*/
void player_update(Player p);
/**
* \brief Comprueba si el personaje es vulnerable a daño por parte de
* enemigos (como Goombas y Koopas). El personaje se vuelve invulnerable tras
* chocar con uno y bajar de estado, durante un corto periodo de tiempo, y
* no se debería llamar a player_downgrade si esta función
* devuelve 0.
* \param p El personaje.
* \return Devuelve 0 si el personaje es invulnerable, u otro valor en caso
* contrario.
*/
int player_vulnerable(Player p);
/**
* \brief Corrige la posición del personaje después de llamar
* a player_update en caso de haber una colisión.
* \param p El personaje.
* \param dir El tipo de colisión por el que corregir la posición.
* Esta par´metro puede valer COLLISION_TOP, COLLISION_BOTTOM,
* COLLISION_LEFT o COLLISION_RIGHT (definidos en collision.h), o el resultado
* de hacer la disyunción lógica bit a bit (operador '|') para
* corregir varios tipos de colisión en la misma llamada a la
* función.
*/
void player_correct_on_collision(Player p, int dir);
/**
* \brief Acelera al personaje a la izquierda o a la derecha según
* valores fijos para la aceleración y la velocidad máxima.
* \param p El personaje.
* \param left Si es distinto de 0, la aceleración será hacia la
* izquierda. De lo contrario será hacia la derecha.
* \remarks Si el personaje está avanzando en dirección contraria,
* frena en seco antes de acelerar en esta dirección.
*/
void player_accel(Player p, int left);
/**
* \brief Hace saltar al personaje.
* \param p El personaje.
*/
void player_jump(Player p);
/**
* \brief Establece a cero la componente horizontal de la velocidad del
* personaje, salvo si este está saltando.
* \param p El personaje.
*/
void player_stop(Player p);
/**
* \brief Dibuja al personaje en la posición de la pantalla que le
* corresponde.
* \param scr La ventana donde dibujar al personaje.
* \param p El personaje.
* \param scroll El scroll, la coordenada X de la parte izquierda de la ventana
* respecto de la parte izquierda del mundo.
*/
void player_render(Screen scr, Player p, int scroll);
/**
* \brief Pasa al personaje al estado inferior al actual.
* \param p El personaje.
* \remarks Pasa de estado "flor" a "grande", de "grande" a "pequeño" y
* de "pequeño" a "muerto".
*/
void player_downgrade(Player p);
/**
* \brief Pasa al personaje a un estado dado si está en un estado
* inferior.
* \param p El personaje.
* \param state El nuevo estado, entre PLAYER_ST_DEAD, PLAYER_ST_SMALL,
* PLAYER_ST_BIG o PLAYER_ST_FLOWER.
*/
void player_upgrade_to(Player p, int state);
/**
* \brief "Mata" a un personaje (cambia su estado a "muerto").
* \param p El personaje.
*/
void player_die(Player p);
/**
* \brief Añade una moneda al contador de monedas recogidas por el
* personaje.
* \param p El personaje.
* \remarks Si se llega a un número de monedas múltiplo de 100,
* el personaje gana una vida extra.
*/
void player_add_coin(Player p);
/**
* \brief Resetea el personaje para empezar un mundo de nuevo.
* \param p El personaje.
* \return Un número distinto de 0 si quedan vidas como para empezar una
* nueva partida. De lo contrario devuelve 0.
* \remarks Al resetear, el personaje queda parado, mirando hacia la derecha.
* Si el personaje estaba en estado "muerto", se resetean las monedas y el
* personaje pasa a estado "pequeño", y de lo contrario el personaje
* conserva su estado. Esta función también disminuye el
* número de vidas en 1. Sin embargo, el personaje queda en las mismas
* coordenadas del mundo que tenía antes.
*/
int player_restart(Player p);
#endif // __PLAYER_H
|