console: Format tabs semi-intelligently
[attac-man.git] / player.c
blob47493e96b3779eeeb70fcecafddb2667658cb97f
1 /*
2 Pacman Arena
3 Copyright (C) 2003 Nuno Subtil
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 static const char cvsid[] =
21 "$Id: player.c,v 1.27 2003/11/30 17:43:55 nsubtil Exp $";
23 #ifdef _WIN32
24 #include <windows.h>
25 #endif
27 #include <GL/gl.h>
28 #include <GL/glu.h>
29 #include <SDL.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
34 #include "object.h"
35 #include "audio.h"
36 #include "m_math.h"
37 #include "gfx.h"
38 #include "game.h"
39 #include "map.h"
40 #include "screen.h"
41 #include "render.h"
42 #include "shot.h"
43 #include "bomb.h"
44 #include "input.h"
46 #include "player.h"
47 #include "ghost.h"
49 GLfloat pacman_colors[2][4] = {
50 {PACMAN_YELLOW}, {PACMAN_BLUE}
52 int num_pacman_colors = 2;
54 void player_reset(struct game *game)
56 if(game->players)
57 free(game->players);
59 game->players = NULL;
60 game->n_players = 0;
63 void player_add_new(struct game *game)
65 struct player *new;
67 game->players = realloc(game->players, sizeof(struct player) * (game->n_players + 1));
68 new = &game->players[game->n_players];
69 game->n_players++;
71 new->state = PLAYER_STATE_STOPPED;
72 new->pill_time = 0;
74 new->position[X] = 0.0;
75 new->position[Y] = -0.5;
76 new->position[Z] = 0.0;
78 new->direction = DIRECTION_UP;
80 /* XXX - tudo isto não é suposto */
81 new->model_moving = object_read_file("gfx/pacman-moving.3d", &new->frames_moving);
82 new->model_stopped = object_read_file("gfx/pacman-stopped.3d", &new->frames_stopped);
83 new->model_dying = object_read_file("gfx/pacman-dying.3d", &new->frames_dying);
84 new->model_won = object_read_file("gfx/pacman-jumping.3d", &new->frames_won);
86 new->current_frame = 0.0;
88 /* XXX - ugly ? UGLY! */
89 if(game->n_players == 1)
91 new->keys[KEY_UP] = SDLK_UP;
92 new->keys[KEY_DOWN] = SDLK_DOWN;
93 new->keys[KEY_LEFT] = SDLK_LEFT;
94 new->keys[KEY_RIGHT] = SDLK_RIGHT;
95 new->keys[KEY_FIRE] = SDLK_SPACE;
96 new->keys[KEY_BOMB] = SDLK_b;
97 } else {
98 new->keys[KEY_UP] = SDLK_w;
99 new->keys[KEY_DOWN] = SDLK_s;
100 new->keys[KEY_LEFT] = SDLK_a;
101 new->keys[KEY_RIGHT] = SDLK_d;
102 new->keys[KEY_FIRE] = SDLK_f;
103 new->keys[KEY_BOMB] = SDLK_g;
106 new->speed = 4.0;
107 new->lives = PLAYER_START_LIVES;
108 new->score = 0;
109 new->multiplier = 0;
111 new->color = pacman_colors[(game->n_players - 1) % num_pacman_colors];
112 new->camera = (struct camera *)malloc(sizeof(struct camera));
113 new->camera->type = CAMERA_TYPE_LOOSE_TRAIL;
116 void player_update_dead(struct game *game, int player_no, float delta)
118 struct player *p = &game->players[player_no];
120 if(p->current_frame >= (float)(p->frames_dying - 1)) {
121 p->lives--;
123 if(p->lives != 0) {
124 /* colocar no jogo */
125 p->state = PLAYER_STATE_MOVING;
126 p->position[X] = p->start_position[X];
127 p->position[Y] = p->start_position[Y];
128 p->position[Z] = p->start_position[Z];
129 p->direction = DIRECTION_LEFT;
130 p->pill_time = 0.0;
131 p->speed = 4.0;
132 p->current_frame = 0.0;
134 return;
137 /* actualizar frames */
138 p->current_frame += delta * ANIM_FPS;
139 return;
143 * In TOMB_RAIDER, the camera always follows behind the player. So, as long
144 * as the forward (up, in this case) key is depressed, keep going in the
145 * current direction.
147 #define LEFT (p->camera->type == CAMERA_TYPE_TOMB_RAIDER ? KEY_UP : KEY_LEFT)
148 #define RIGHT (p->camera->type == CAMERA_TYPE_TOMB_RAIDER ? KEY_UP : KEY_RIGHT)
149 #define UP (KEY_UP)
150 #define DOWN (p->camera->type == CAMERA_TYPE_TOMB_RAIDER ? KEY_UP : KEY_DOWN)
152 * return 1 if we need to update the map
154 static int update_player_position(struct player *p, struct map *map, float delta)
156 int update_map = 0;
157 int dest_reached = 0, keep_moving = 0;
158 float dest_x, dest_z, frac_x, frac_z;
159 float new_position[3];
160 /* x,z modifier, for lack of a better word. */
161 float x_mod = 0.0, z_mod = 0.0;
163 new_position[X] = p->position[X];
164 new_position[Y] = p->position[Y];
165 new_position[Z] = p->position[Z];
167 if (p->state != PLAYER_STATE_MOVING)
168 return 0;
170 frac_x = p->position[X] - (float)((int)p->position[X]);
171 frac_z = p->position[Z] - (float)((int)p->position[Z]);
173 dest_x = (int)p->position[X] + 0.5;
174 dest_z = (int)p->position[Z] + 0.5;
176 switch(p->direction) {
177 case DIRECTION_UP:
178 new_position[Z] += MIN(delta * p->speed, 0.5);
179 if (frac_z > 0.5)
180 dest_z += 1.0;
181 dest_reached = new_position[Z] > dest_z;
182 if (!dest_reached)
183 z_mod = -1.0;
184 keep_moving = input_kstate(p->keys[UP]);
185 break;
186 case DIRECTION_DOWN:
187 new_position[Z] -= MIN(delta * p->speed, 0.5);
188 if (frac_z < 0.5)
189 dest_z -= 1.0;
190 dest_reached = new_position[Z] < dest_z;
191 if (!dest_reached)
192 z_mod = 1.0;
193 keep_moving = input_kstate(p->keys[DOWN]);
194 break;
195 case DIRECTION_LEFT:
196 new_position[X] -= MIN(delta * p->speed, 0.5);
197 if (frac_x < 0.5)
198 dest_x -= 1.0;
199 dest_reached = new_position[X] < dest_x;
200 if (!dest_reached)
201 x_mod = 1.0;
202 keep_moving = input_kstate(p->keys[LEFT]);
203 break;
204 case DIRECTION_RIGHT:
205 new_position[X] += MIN(delta * p->speed, 0.5);
206 if (frac_x > 0.5)
207 dest_x += 1.0;
208 dest_reached = new_position[X] > dest_x;
209 if (!dest_reached)
210 x_mod = -1.0;
211 keep_moving = input_kstate(p->keys[RIGHT]);
212 break;
213 default:
214 break;
217 if(dest_reached) {
218 update_map = 1;
220 if(keep_moving) {
221 p->position[X] = new_position[X];
222 p->position[Z] = new_position[Z];
223 } else {
224 p->position[X] = dest_x;
225 p->position[Z] = dest_z;
226 p->state = PLAYER_STATE_STOPPED;
228 } else {
229 if(MAP_CAN_ENTER(map,(int)dest_x,(int)dest_z)) {
230 p->position[X] = new_position[X];
231 p->position[Z] = new_position[Z];
232 } else {
233 p->position[X] = dest_x + x_mod;
234 p->position[Z] = dest_z + z_mod;
235 p->state = PLAYER_STATE_STOPPED;
239 return update_map;
242 int food_status_active(struct map *map, struct player *p)
244 struct pacman_food *food;
246 food = &MAP_FOOD(map, (int)p->position[X], (int)p->position[Z]);
247 return food->status == FOOD_STATUS_ACTIVE;
250 void eat_food(struct map *map, struct player *p)
252 struct pacman_food *food;
254 food = &MAP_FOOD(map, (int)p->position[X], (int)p->position[Z]);
255 food->status = FOOD_STATUS_EATEN;
256 audio_play_sample("sfx/chomp.wav");
257 p->score += 10;
260 int pill_status_active(struct map *map, struct player *p)
262 struct pacman_pill *pill;
264 pill = &MAP_PILL(map, (int)p->position[X], (int)p->position[Z]);
265 return pill->status == PILL_STATUS_ACTIVE;
268 void eat_pill(struct map *map, struct player *p)
270 struct pacman_pill *pill;
272 pill = &MAP_PILL(map, (int)p->position[X], (int)p->position[Z]);
273 pill->status = PILL_STATUS_EATEN;
274 audio_play_sample("sfx/glomp.wav");
275 p->pill_time = 10.0;
276 p->score += 50;
277 if (p->multiplier == 0) {
278 /* 200 / 400 / 800 / 1600 */
279 p->multiplier = 2;
283 void player_update(struct game *game, int player_no, float delta)
285 float vec[2];
286 int nx, ny;
287 int verify = 0, update_map = 0;
288 struct player *p = &game->players[player_no];
289 struct map *map = game->map;
291 if(p->state == PLAYER_STATE_DEAD) {
292 player_update_dead(game, player_no, delta);
293 return;
296 /* update p->position */
297 update_map = update_player_position(p, map, delta);
299 /* mapa */
300 vec[X] = p->position[X] - (float)((int)p->position[X]) + 0.5;
301 vec[Y] = p->position[Z] - (float)((int)p->position[Z]) + 0.5;
303 if(update_map || math_norm_vec2(vec) < 0.1) {
304 switch(MAP(map, (int)p->position[X], (int)p->position[Z]).content) {
305 case MAP_CONTENT_FOOD:
306 if (food_status_active(map, p))
307 eat_food(map, p);
308 break;
310 case MAP_CONTENT_PILL:
311 if (pill_status_active(map, p)) {
312 eat_pill(map, p);
313 ghost_taint_all(game);
315 break;
317 case MAP_CONTENT_TELEPORT:
318 game_teleport_player(game, player_no);
319 break;
323 /* teclas */
324 if(p->camera->type == CAMERA_TYPE_TOMB_RAIDER) {
325 /* change direction */
326 switch(p->direction)
328 case DIRECTION_UP:
329 /* left turns pacman left */
330 if(input_kstate(p->keys[KEY_LEFT]))
332 p->direction = DIRECTION_LEFT;
333 p->state = PLAYER_STATE_STOPPED;
334 input_kclear(p->keys[KEY_LEFT]);
337 /* right turns pacman right */
338 if(input_kstate(p->keys[KEY_RIGHT]))
340 p->direction = DIRECTION_RIGHT;
341 p->state = PLAYER_STATE_STOPPED;
342 input_kclear(p->keys[KEY_RIGHT]);
345 /* down turns pacman down */
346 if(input_kstate(p->keys[KEY_DOWN]))
348 p->direction = DIRECTION_DOWN;
349 p->state = PLAYER_STATE_STOPPED;
350 input_kclear(p->keys[KEY_DOWN]);
353 break;
355 case DIRECTION_DOWN:
356 /* left turns pacman right */
357 if(input_kstate(p->keys[KEY_LEFT]))
359 p->direction = DIRECTION_RIGHT;
360 p->state = PLAYER_STATE_STOPPED;
361 input_kclear(p->keys[KEY_LEFT]);
364 /* right turns pacman left */
365 if(input_kstate(p->keys[KEY_RIGHT]))
367 p->direction = DIRECTION_LEFT;
368 p->state = PLAYER_STATE_STOPPED;
369 input_kclear(p->keys[KEY_RIGHT]);
372 /* down turns pacman up */
373 if(input_kstate(p->keys[KEY_DOWN]))
375 p->direction = DIRECTION_UP;
376 p->state = PLAYER_STATE_STOPPED;
377 input_kclear(p->keys[KEY_DOWN]);
380 break;
382 case DIRECTION_LEFT:
383 /* left turns pacman down */
384 if(input_kstate(p->keys[KEY_LEFT]))
386 p->direction = DIRECTION_DOWN;
387 p->state = PLAYER_STATE_STOPPED;
388 input_kclear(p->keys[KEY_LEFT]);
391 /* right turns pacman up */
392 if(input_kstate(p->keys[KEY_RIGHT]))
394 p->direction = DIRECTION_UP;
395 p->state = PLAYER_STATE_STOPPED;
396 input_kclear(p->keys[KEY_RIGHT]);
399 /* down turns pacman right */
400 if(input_kstate(p->keys[KEY_DOWN]))
402 p->direction = DIRECTION_RIGHT;
403 p->state = PLAYER_STATE_STOPPED;
404 input_kclear(p->keys[KEY_DOWN]);
407 break;
409 case DIRECTION_RIGHT:
410 /* left turns pacman up */
411 if(input_kstate(p->keys[KEY_LEFT]))
413 p->direction = DIRECTION_UP;
414 p->state = PLAYER_STATE_STOPPED;
415 input_kclear(p->keys[KEY_LEFT]);
418 /* right turns pacman down */
419 if(input_kstate(p->keys[KEY_RIGHT]))
421 p->direction = DIRECTION_DOWN;
422 p->state = PLAYER_STATE_STOPPED;
423 input_kclear(p->keys[KEY_RIGHT]);
426 /* down turns pacman left */
427 if(input_kstate(p->keys[KEY_DOWN]))
429 p->direction = DIRECTION_LEFT;
430 p->state = PLAYER_STATE_STOPPED;
431 input_kclear(p->keys[KEY_DOWN]);
434 break;
437 /* move */
438 switch(p->direction)
440 case DIRECTION_UP:
441 /* up moves pacman up */
442 if(input_kstate(p->keys[KEY_UP]))
444 p->direction = DIRECTION_UP;
445 if(p->state == PLAYER_STATE_STOPPED)
447 p->state = PLAYER_STATE_MOVING;
448 verify = 1;
452 break;
454 case DIRECTION_DOWN:
455 /* up moves pacman down */
456 if(input_kstate(p->keys[KEY_UP]))
458 p->direction = DIRECTION_DOWN;
459 if(p->state == PLAYER_STATE_STOPPED)
461 p->state = PLAYER_STATE_MOVING;
462 verify = 1;
466 break;
468 case DIRECTION_LEFT:
469 /* up moves pacman left */
470 if(input_kstate(p->keys[KEY_UP]))
472 p->direction = DIRECTION_LEFT;
473 if(p->state == PLAYER_STATE_STOPPED)
475 p->state = PLAYER_STATE_MOVING;
476 verify = 1;
480 break;
482 case DIRECTION_RIGHT:
483 /* up moves pacman right */
484 if(input_kstate(p->keys[KEY_UP]))
486 p->direction = DIRECTION_RIGHT;
487 if(p->state == PLAYER_STATE_STOPPED)
489 p->state = PLAYER_STATE_MOVING;
490 verify = 1;
494 break;
496 } else {
497 if(input_kstate(p->keys[KEY_UP]) &&
498 (p->state == PLAYER_STATE_STOPPED ||
499 p->direction == DIRECTION_DOWN))
501 p->direction = DIRECTION_UP;
502 p->state = PLAYER_STATE_MOVING;
503 verify = 1;
504 } else
505 if(input_kstate(p->keys[KEY_LEFT]) &&
506 (p->state == PLAYER_STATE_STOPPED ||
507 p->direction == DIRECTION_RIGHT))
509 p->direction = DIRECTION_LEFT;
510 p->state = PLAYER_STATE_MOVING;
511 verify = 1;
512 } else
513 if(input_kstate(p->keys[KEY_RIGHT]) &&
514 (p->state == PLAYER_STATE_STOPPED ||
515 p->direction == DIRECTION_LEFT))
517 p->direction = DIRECTION_RIGHT;
518 p->state = PLAYER_STATE_MOVING;
519 verify = 1;
520 } else
521 if(input_kstate(p->keys[KEY_DOWN]) &&
522 (p->state == PLAYER_STATE_STOPPED ||
523 p->direction == DIRECTION_UP))
525 p->direction = DIRECTION_DOWN;
526 p->state = PLAYER_STATE_MOVING;
527 verify = 1;
531 if(input_kstate(p->keys[KEY_FIRE]))
533 shot_new(game, player_no, SHOT_TYPE_ROCKET, p->speed);
534 input_kclear(p->keys[KEY_FIRE]);
537 if(input_kstate(p->keys[KEY_BOMB]))
539 if((MAP(game->map, (int)p->position[X], (int)p->position[Z]).flags &
540 MAP_FLAG_BOMB) == 0)
541 bomb_new(game, player_no, 4.0);
543 input_kclear(p->keys[KEY_BOMB]);
546 if(verify)
548 /* validar nova direcção */
549 nx = (int)p->position[X];
550 ny = (int)p->position[Z];
552 switch(p->direction)
554 case DIRECTION_UP:
555 ny++;
556 break;
558 case DIRECTION_DOWN:
559 ny--;
560 break;
562 case DIRECTION_LEFT:
563 nx--;
564 break;
566 case DIRECTION_RIGHT:
567 nx++;
568 break;
571 if(!MAP_CAN_ENTER(map, nx, ny))
572 p->state = PLAYER_STATE_STOPPED;
574 /* align pacman with tile center */
575 p->position[X] = (float)((int)p->position[X]) + 0.5;
576 p->position[Z] = (float)((int)p->position[Z]) + 0.5;
579 /* frame da animação */
580 switch(p->state)
582 case PLAYER_STATE_MOVING:
583 if(p->direction == DIRECTION_LEFT || p->direction == DIRECTION_RIGHT)
584 p->current_frame =
585 (p->position[X] - (float)((int)p->position[X])) *
586 p->frames_moving;
587 else
588 p->current_frame = (p->position[Z] - (float)((int)p->position[Z])) *
589 p->frames_moving;
591 break;
593 case PLAYER_STATE_STOPPED:
594 p->current_frame += delta * ANIM_FPS;
595 break;
598 /* pill time! */
599 if(p->pill_time != 0.0)
601 p->pill_time -= delta;
602 if(p->pill_time <= 0.0)
604 p->multiplier = 0;
605 p->pill_time = 0.0;
606 ghost_untaint_all(game);
611 void player_kill(struct game *game, int player_no)
613 struct player *player;
615 player = &game->players[player_no];
616 player->state = PLAYER_STATE_DEAD;
617 player->current_frame = 0.0;
618 audio_play_sample("sfx/pacman-die.wav");