2 // C Implementation: player/tux
7 // Author: Tobias Glaesser <tobi.web@gmx.de> & Bill Kendrick, (C) 2004
9 // Copyright: See COPYING file that comes with this distribution
20 texture_type tux_life,
21 tux_right[3], tux_left[3],
22 bigtux_right[3], bigtux_left[3],
23 bigtux_right_jump, bigtux_left_jump,
24 ducktux_right, ducktux_left,
25 skidtux_right, skidtux_left,
26 firetux_right[3], firetux_left[3],
27 bigfiretux_right[3], bigfiretux_left[3],
28 bigfiretux_right_jump, bigfiretux_left_jump,
29 duckfiretux_right, duckfiretux_left,
30 skidfiretux_right, skidfiretux_left,
31 cape_right[2], cape_left[2],
32 bigcape_right[2], bigcape_left[2];
34 void player_init(player_type* pplayer)
36 pplayer->base.width = 32;
37 pplayer->base.height = 32;
39 pplayer->size = SMALL;
40 pplayer->got_coffee = NO;
43 pplayer->base.y = 240;
50 pplayer->jumping = NO;
52 pplayer->frame_main = 0;
58 pplayer->input.down = UP;
59 pplayer->input.fire = UP;
60 pplayer->input.left = UP;
61 pplayer->input.old_fire = UP;
62 pplayer->input.right = UP;
63 pplayer->input.up = UP;
65 pplayer->keymap.jump = SDLK_UP;
66 pplayer->keymap.duck = SDLK_DOWN;
67 pplayer->keymap.left = SDLK_LEFT;
68 pplayer->keymap.right = SDLK_RIGHT;
69 pplayer->keymap.fire = SDLK_LCTRL;
71 timer_init(&pplayer->invincible_timer);
72 timer_init(&pplayer->skidding_timer);
73 timer_init(&pplayer->safe_timer);
74 physic_init(&pplayer->hphysic);
75 physic_init(&pplayer->vphysic);
78 int player_key_event(player_type* pplayer, SDLKey key, int state)
80 if(key == pplayer->keymap.right)
82 pplayer->input.right = state;
85 else if( key == pplayer->keymap.left)
87 pplayer->input.left = state;
90 else if(key == pplayer->keymap.jump)
92 pplayer->input.up = state;
95 else if(key == pplayer->keymap.duck)
97 pplayer->input.down = state;
100 else if(key == pplayer->keymap.fire)
102 pplayer->input.fire = state;
109 void player_level_begin(player_type* pplayer)
112 pplayer->base.y = 240;
113 pplayer->base.xm = 0;
114 pplayer->base.ym = 0;
116 pplayer->input.down = UP;
117 pplayer->input.fire = UP;
118 pplayer->input.left = UP;
119 pplayer->input.old_fire = UP;
120 pplayer->input.right = UP;
121 pplayer->input.up = UP;
123 timer_init(&pplayer->invincible_timer);
124 timer_init(&pplayer->skidding_timer);
125 timer_init(&pplayer->safe_timer);
128 void player_action(player_type* pplayer)
130 /* --- HANDLE TUX! --- */
132 player_input(pplayer);
136 pplayer->base.x += pplayer->base.xm * frame_ratio;
137 pplayer->base.y += pplayer->base.ym * frame_ratio;
139 player_keep_in_bounds(pplayer);
146 /*if(physic_is_set(&pplayer->vphysic))
148 pplayer->base.ym = physic_get_velocity(&pplayer->vphysic);
152 if(!issolid( pplayer->base.x + 16, pplayer->base.y + pplayer->base.height))
154 if(!physic_is_set(&pplayer->vphysic))
156 physic_set_state(&pplayer->vphysic,PH_VT);
157 physic_set_start_vy(&pplayer->vphysic,0.);
159 pplayer->base.ym = physic_get_velocity(&pplayer->vphysic);
165 if (pplayer->base.ym > 0)
167 pplayer->base.y = (int)(pplayer->base.y / 32) * 32;
168 pplayer->base.ym = 0;
170 physic_init(&pplayer->vphysic);
173 while(issolid( pplayer->base.x + 16, pplayer->base.y + pplayer->base.height) && !issolid( pplayer->base.x + 16, pplayer->base.y))
177 while(issolid( pplayer->base.x + 16, pplayer->base.y) && !issolid( pplayer->base.x + 16, pplayer->base.y + pplayer->base.height))
181 while(issolid( pplayer->base.x - 1, pplayer->base.y) || issolid( pplayer->base.x - 1, pplayer->base.y+pplayer->base.height))
185 while(issolid( pplayer->base.x + 32, pplayer->base.y) || issolid( pplayer->base.x + 32, pplayer->base.y+pplayer->base.height))
190 if (isbrick(pplayer->base.x, pplayer->base.y - 1) ||
191 isfullbox(pplayer->base.x, pplayer->base.y - 1))
193 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
194 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
195 bumpbrick(pplayer->base.x, pplayer->base.y - 1);
196 tryemptybox(pplayer->base.x, pplayer->base.y - 1);
199 if (isbrick(pplayer->base.x+ 31, pplayer->base.y - 1) ||
200 isfullbox(pplayer->base.x+ 31, pplayer->base.y - 1))
202 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
203 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
204 bumpbrick(pplayer->base.x+ 31, pplayer->base.y - 1);
205 tryemptybox(pplayer->base.x+ 31, pplayer->base.y - 1);
209 /* Get a distro from a brick? */
211 if (shape(pplayer->base.x, pplayer->base.y - 1) == 'x' ||
212 shape(pplayer->base.x, pplayer->base.y - 1) == 'y')
214 add_bouncy_distro((((int)pplayer->base.x)
216 ((int)pplayer->base.y - 1 / 32) * 32);
217 DEBUG_MSG("should work");
218 if (counting_distros == NO)
220 counting_distros = YES;
221 distro_counter = 100;
224 if (distro_counter <= 0)
225 level_change(¤t_level,pplayer->base.x,pplayer->base.y - 1, 'a');
227 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
228 score = score + SCORE_DISTRO;
231 else if (shape(pplayer->base.x+ 31, pplayer->base.y - 1) == 'x' ||
232 shape(pplayer->base.x+ 31, pplayer->base.y - 1) == 'y')
234 add_bouncy_distro((((int)pplayer->base.x + 31)
236 ((int)pplayer->base.y - 1 / 32) * 32);
238 if (counting_distros == NO)
240 counting_distros = YES;
241 distro_counter = 100;
244 if (distro_counter <= 0)
245 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y - 1, 'a');
247 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
248 score = score + SCORE_DISTRO;
252 player_grabdistros(pplayer);
254 /* FIXME: this code is COMPLETLY broken!!! */
255 /* if (issolid(pplayer->base.x, pplayer->base.y + 31) &&
256 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y + 31))
258 while (issolid(pplayer->base.x, pplayer->base.y + 31))
260 if (pplayer->base.xm < 0)
262 else if (pplayer->base.xm > 0)
266 pplayer->base.xm = 0;
269 /*if (issolid(pplayer->base.x, pplayer->base.y) &&
270 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y))
272 while (issolid(pplayer->base.x, (pplayer->base.y)))
274 if (pplayer->base.xm < 0)
276 else if (pplayer->base.xm > 0)
280 pplayer->base.xm = 0;
283 /*if (issolid(pplayer->base.x, pplayer->base.y + 31))
285 /* Set down properly: * /
288 while (issolid(pplayer->base.x, pplayer->base.y + 31))
293 DEBUG_MSG("FIXME - UNDER certain circumstances I'm hanging in a loop here!");
294 /*the circumstances are:
295 issolid() is true and base.ym == 0
296 use of floating point varibles for base stuff* /
299 if (pplayer->base.ym < 0)
301 else if (pplayer->base.ym > 0)
306 /* Reset score multiplier (for multi-hits): */
308 if (pplayer->base.ym > 0)
309 score_multiplier = 1;
314 pplayer->base.ym = 0;
315 pplayer->jumping = NO;
316 pplayer->input.up = UP;
318 /* FIXME: this code is COMPLETLY broken!!! */
319 /*if (issolid(pplayer->base.x, pplayer->base.y) ||
320 (pplayer->size == BIG && !pplayer->duck &&
321 (issolid(pplayer->base.x, pplayer->base.y - 32))))
323 /*if (!issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y) &&
324 (pplayer->size == SMALL || pplayer->duck ||
325 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32)))* /
327 if (((!issolid(pplayer->base.x, pplayer->base.y- pplayer->base.ym * frame_ratio) && (issolid(pplayer->base.x, pplayer->base.y) || issolid(pplayer->base.x, pplayer->base.y+31))))
328 ||((!issolid(pplayer->base.x - pplayer->base.xm * frame_ratio, pplayer->base.y) && (issolid(pplayer->base.x, pplayer->base.y) || issolid(pplayer->base.x+32, pplayer->base.y)))))
329 /*(pplayer->size == SMALL || pplayer->duck ||
330 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))* /
332 pplayer->base.y = pplayer->base.y- pplayer->base.ym * frame_ratio;
333 pplayer->base.ym = 0;
336 if (((issolid(pplayer->base.x, pplayer->base.y) || issolid(pplayer->base.x+32, pplayer->base.y)) && (!issolid(pplayer->base.x - pplayer->base.xm * frame_ratio, pplayer->base.y))
337 /*(pplayer->size == SMALL || pplayer->duck ||
338 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))* /) ||
339 (!issolid(pplayer->base.x - pplayer->base.xm * frame_ratio, pplayer->base.y+pplayer->base.height) && (issolid(pplayer->base.x, pplayer->base.y+pplayer->base.height) || issolid(pplayer->base.x +32, pplayer->base.y+pplayer->base.height))))
341 pplayer->base.x = pplayer->base.x- pplayer->base.xm * frame_ratio;
342 pplayer->base.xm = 0;
345 if (pplayer->base.ym <= 0)
347 if (isbrick(pplayer->base.x, pplayer->base.y) ||
348 isfullbox(pplayer->base.x, pplayer->base.y))
350 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
351 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
352 bumpbrick(pplayer->base.x, pplayer->base.y);
353 tryemptybox(pplayer->base.x, pplayer->base.y);
356 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
357 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
359 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
360 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
361 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
362 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
364 /* Get a distro from a brick? * /
366 if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
367 shape(pplayer->base.x, pplayer->base.y) == 'y')
369 add_bouncy_distro(((pplayer->base.x+ 1)
371 (int)(pplayer->base.y / 32) * 32);
373 if (counting_distros == NO)
375 counting_distros = YES;
376 distro_counter = 100;
379 if (distro_counter <= 0)
380 level_change(¤t_level,pplayer->base.x,pplayer->base.y, 'a');
382 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
383 score = score + SCORE_DISTRO;
386 else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
387 shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
389 add_bouncy_distro(((pplayer->base.x+ 1 + 31)
391 (int)(pplayer->base.y / 32) * 32);
393 if (counting_distros == NO)
395 counting_distros = YES;
396 distro_counter = 100;
399 if (distro_counter <= 0)
400 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
402 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
403 score = score + SCORE_DISTRO;
410 pplayer->base.ym = 0;
411 pplayer->jumping = NO;
412 timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
415 /* Bump into things: * /
417 if (issolid(pplayer->base.x, pplayer->base.y) ||
418 (pplayer->size == BIG && !pplayer->duck &&
419 (issolid(pplayer->base.x, pplayer->base.y - 32))))
422 if (!issolid(pplayer->base.x, pplayer->base.y - pplayer->base.ym) &&
423 (pplayer->size == SMALL || pplayer->duck ||
424 !issolid(pplayer->base.x, pplayer->base.y - 32 - pplayer->base.ym)))
426 if (pplayer->base.ym <= 0)
429 /* FIXME: this code is COMPLETLY broken!!! */
430 if (pplayer->size == BIG)
432 /* Break bricks and empty boxes: * /
436 if (isbrick(pplayer->base.x, pplayer->base.y - 32) ||
437 isfullbox(pplayer->base.x, pplayer->base.y - 32))
439 trygrabdistro(pplayer->base.x, pplayer->base.y - 64, BOUNCE);
440 trybumpbadguy(pplayer->base.x, pplayer->base.y - 96);
442 if (isfullbox(pplayer->base.x, pplayer->base.y - 32))
444 bumpbrick(pplayer->base.x, pplayer->base.y - 32);
447 trybreakbrick(pplayer->base.x, pplayer->base.y - 32);
448 tryemptybox(pplayer->base.x, pplayer->base.y - 32);
451 if (isbrick(pplayer->base.x+ 31, pplayer->base.y - 32) ||
452 isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
454 trygrabdistro(pplayer->base.x+ 31,
455 pplayer->base.y - 64,
457 trybumpbadguy(pplayer->base.x+ 31,
458 pplayer->base.y - 96);
460 if (isfullbox(pplayer->base.x+
461 printf("%f",pplayer->base.ym); 31, pplayer->base.y - 32))
463 bumpbrick(pplayer->base.x+ 31, pplayer->base.y - 32);
466 trybreakbrick(pplayer->base.x+ 31,
467 pplayer->base.y - 32);
468 tryemptybox(pplayer->base.x+ 31,
469 pplayer->base.y - 32);
474 if (isbrick(pplayer->base.x, pplayer->base.y) ||
475 isfullbox(pplayer->base.x, pplayer->base.y))
477 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
478 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
479 if (isfullbox(pplayer->base.x, pplayer->base.y))
480 bumpbrick(pplayer->base.x, pplayer->base.y);
481 trybreakbrick(pplayer->base.x, pplayer->base.y);
482 tryemptybox(pplayer->base.x, pplayer->base.y);
485 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
486 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
488 trygrabdistro(pplayer->base.x+ 31,
489 pplayer->base.y - 32,
491 trybumpbadguy(pplayer->base.x+ 31,
492 pplayer->base.y - 64);
493 if (isfullbox(pplayer->base.x+ 31, pplayer->base.y))
494 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
495 trybreakbrick(pplayer->base.x+ 31, pplayer->base.y);
496 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
502 /* It's a brick and we're small, make the brick
503 bounce, and grab any distros above it: * /
505 if (isbrick(pplayer->base.x, pplayer->base.y) ||
506 isfullbox(pplayer->base.x, pplayer->base.y))
508 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
509 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
510 bumpbrick(pplayer->base.x, pplayer->base.y);
511 tryemptybox(pplayer->base.x, pplayer->base.y);
514 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
515 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
517 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
518 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
519 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
520 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
524 /* Get a distro from a brick? * /
526 if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
527 shape(pplayer->base.x, pplayer->base.y) == 'y')
529 add_bouncy_distro(((pplayer->base.x+ 1)
531 (int)(pplayer->base.y / 32) * 32);
533 if (counting_distros == NO)
535 counting_distros = YES;
536 distro_counter = 100;
539 if (distro_counter <= 0)
540 level_change(¤t_level,pplayer->base.x,pplayer->base.y, 'a');
542 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
543 score = score + SCORE_DISTRO;
546 else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
547 shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
549 add_bouncy_distro(((pplayer->base.x+ 1 + 31)
551 (int)(pplayer->base.y / 32) * 32);
553 if (counting_distros == NO)
555 counting_distros = YES;
556 distro_counter = 100;
559 if (distro_counter <= 0)
560 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
562 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
563 score = score + SCORE_DISTRO;
571 pplayer->base.y = (int)(pplayer->base.y / 32) * 32 + 30;
577 pplayer->base.y = (int)(pplayer->base.y / 32) * 32 - 32;
580 pplayer->base.ym = 0;
581 pplayer->jumping = NO;
582 timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
589 player_grabdistros(pplayer);
592 /* Slow down horizontally: * /
596 if (pplayer->input.right == UP && pplayer->input.left == UP)
598 if (isice(pplayer->base.x, pplayer->base.y + 32) ||
599 !issolid(pplayer->base.x, pplayer->base.y + 32))
601 /* Slowly on ice or in air: * /
603 if (pplayer->base.xm > 0)
605 else if (pplayer->base.xm < 0)
610 /* Quickly, otherwise: * /
612 pplayer->base.xm = pplayer->base.xm / 2;
617 /* Drop vertically: * /
619 if (!issolid(pplayer->base.x, pplayer->base.y + 32))
621 pplayer->base.ym = pplayer->base.ym + GRAVITY;
623 if (pplayer->base.ym > MAX_YM)
624 pplayer->base.ym = MAX_YM;
630 timer_check(&pplayer->safe_timer);
633 /* ---- DONE HANDLING TUX! --- */
635 /* Handle invincibility timer: */
638 if (current_music == HERRING_MUSIC && !timer_check(&pplayer->invincible_timer))
641 no, we are no more invincible
642 or we were not in invincible mode
643 but are we in hurry ?
647 if (timer_get_left(&time_left) < TIME_WARNING)
649 /* yes, we are in hurry
650 stop the herring_song, prepare to play the correct
653 current_music = HURRYUP_MUSIC;
657 current_music = LEVEL_MUSIC;
660 /* stop the old music if it's being played */
665 /* Handle skidding: */
667 timer_check(&pplayer->skidding_timer);
671 if (pplayer->base.x - scroll_x >= endpos && endpos != 0)
678 void player_handle_horizontal_input(player_type *pplayer, int dir)
680 if (pplayer->jumping == NO)
682 if ((dir ? (pplayer->base.xm < -SKID_XM) : (pplayer->base.xm > SKID_XM)) && !timer_started(&pplayer->skidding_timer) &&
683 pplayer->dir == !dir)
685 timer_start(&pplayer->skidding_timer, SKID_TIME);
687 play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
693 if ((dir ? (pplayer->base.xm < 0) : (pplayer->base.xm > 0)) && !isice(pplayer->base.x, pplayer->base.y + 32) &&
694 !timer_started(&pplayer->skidding_timer))
696 pplayer->base.xm = 0;
701 if (pplayer->dir == dir)
703 /* Facing the direction we're jumping? Go full-speed: */
705 if (pplayer->input.fire == UP)
707 pplayer->base.xm = pplayer->base.xm + ( dir ? WALK_SPEED : -WALK_SPEED) * frame_ratio;
711 if (pplayer->base.xm > MAX_WALK_XM)
712 pplayer->base.xm = MAX_WALK_XM;
716 if (pplayer->base.xm < -MAX_WALK_XM)
717 pplayer->base.xm = -MAX_WALK_XM;
720 else if ( pplayer->input.fire == DOWN)
722 pplayer->base.xm = pplayer->base.xm + ( dir ? RUN_SPEED : -RUN_SPEED) * frame_ratio;
726 if (pplayer->base.xm > MAX_RUN_XM)
727 pplayer->base.xm = MAX_RUN_XM;
731 if (pplayer->base.xm < -MAX_RUN_XM)
732 pplayer->base.xm = -MAX_RUN_XM;
737 /* Not facing the direction we're jumping?
740 pplayer->base.xm = pplayer->base.xm + ( dir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio;
744 if (pplayer->base.xm > MAX_WALK_XM / 2)
745 pplayer->base.xm = MAX_WALK_XM / 2;
749 if (pplayer->base.xm < -MAX_WALK_XM / 2)
750 pplayer->base.xm = -MAX_WALK_XM / 2;
758 void player_handle_vertical_input(player_type *pplayer)
760 if(pplayer->input.up == DOWN)
762 if (issolid(pplayer->base.x + 16, pplayer->base.y + pplayer->base.height + 1))
764 if(!physic_is_set(&pplayer->vphysic))
766 physic_set_state(&pplayer->vphysic,PH_VT);
767 physic_set_start_vy(&pplayer->vphysic,5.2);
768 pplayer->jumping = YES;
769 if (pplayer->size == SMALL)
770 play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
772 play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
776 else if(pplayer->input.up == UP && pplayer->jumping == YES)
779 DEBUG_MSG("Stop Jump");
780 pplayer->jumping = NO;
782 if (pplayer->base.ym > 0)
784 pplayer->base.y = (int)(pplayer->base.y / 32) * 32;
785 pplayer->base.ym = 0;
787 physic_init(&pplayer->vphysic);
789 else if(pplayer->input.up == UP)
791 if (issolid(pplayer->base.x + 16, pplayer->base.y + pplayer->base.height + 1))
793 physic_init(&pplayer->vphysic);
794 pplayer->jumping == NO;
798 pplayer->jumping = NO;
799 physic_set_state(&pplayer->vphysic,PH_VT);
800 physic_set_start_vy(&pplayer->vphysic,0);
801 if(physic_is_set(&pplayer->vphysic) && pplayer->vphysic.start_vx != 0)
803 physic_set_start_vy(&pplayer->vphysic,0);
807 if(!physic_is_set(&pplayer->vphysic))
809 physic_set_state(&pplayer->vphysic,PH_VT);
817 if (!issolid(pplayer->base.x, pplayer->base.y + 32) ||
818 pplayer->base.ym != 0)
820 /* If they're not on the ground, or are currently moving
821 vertically, don't jump! * /
823 pplayer->jumping = NO;
824 timer_stop(&pplayer->jump_timer);
828 /* Make sure we're not standing back up into a solid! * /
830 if (pplayer->size == SMALL || pplayer->duck == NO ||
831 !issolid(pplayer->base.x, pplayer->base.y))
833 pplayer->jumping = YES;
835 if (pplayer->size == SMALL)
836 play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
838 play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
842 /* Keep jumping for a while: * /
844 if (timer_check(&pplayer->jump_timer))
846 pplayer->base.ym = pplayer->base.ym - JUMP_SPEED * frame_ratio;
847 if (pplayer->base.ym < -YM_FOR_JUMP)
848 pplayer->base.ym = pplayer->base.ym/*-YM_FOR_JUMP* /;
852 void player_input(player_type *pplayer)
854 /* Handle key and joystick state: */
857 if (pplayer->input.right == DOWN && pplayer->input.left == UP)
859 player_handle_horizontal_input(pplayer,RIGHT);
861 else if (pplayer->input.left == DOWN && pplayer->input.right == UP)
863 player_handle_horizontal_input(pplayer,LEFT);
867 if(pplayer->base.xm > 0)
868 pplayer->base.xm = (int)(pplayer->base.xm - frame_ratio);
869 else if(pplayer->base.xm < 0)
870 pplayer->base.xm = (int)(pplayer->base.xm + frame_ratio);
875 if ( pplayer->input.up == DOWN || (pplayer->input.up == UP && pplayer->jumping == YES))
877 player_handle_vertical_input(pplayer);
882 if (pplayer->input.fire == DOWN && pplayer->input.old_fire == UP && pplayer->got_coffee)
884 add_bullet(pplayer->base.x, pplayer->base.y, pplayer->base.xm, pplayer->dir);
890 if (pplayer->input.down == DOWN)
892 if (pplayer->size == BIG)
897 if (pplayer->size == BIG && pplayer->duck == YES)
899 /* Make sure we're not standing back up into a solid! */
901 if (!issolid(pplayer->base.x + 16, pplayer->base.y - 16))
910 if (pplayer->input.right == UP && pplayer->input.left == UP)
912 pplayer->frame_main = 1;
917 if ((pplayer->input.fire == DOWN && (frame % 2) == 0) ||
919 pplayer->frame_main = (pplayer->frame_main + 1) % 4;
921 pplayer->frame = pplayer->frame_main;
923 if (pplayer->frame == 3)
929 void player_grabdistros(player_type *pplayer)
934 trygrabdistro(pplayer->base.x, pplayer->base.y, NO_BOUNCE);
935 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y, NO_BOUNCE);
937 trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height, NO_BOUNCE);
938 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height, NO_BOUNCE);
940 if(pplayer->size == BIG)
942 trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE);
943 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE);
949 /* Enough distros for a One-up? */
951 if (distros >= DISTROS_LIFEUP)
953 distros = distros - DISTROS_LIFEUP;
954 if(pplayer->lives < MAX_LIVES)
956 /*We want to hear the sound even, if MAX_LIVES is reached*/
957 play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
961 void player_draw(player_type* pplayer)
963 if (!timer_started(&pplayer->safe_timer) || (frame % 2) == 0)
965 if (pplayer->size == SMALL)
967 if (timer_started(&pplayer->invincible_timer))
971 if (pplayer->dir == RIGHT)
973 texture_draw(&cape_right[frame % 2],
974 pplayer->base.x- scroll_x, pplayer->base.y,
979 texture_draw(&cape_left[frame % 2],
980 pplayer->base.x- scroll_x, pplayer->base.y,
986 if (!pplayer->got_coffee)
988 if (pplayer->dir == RIGHT)
990 texture_draw(&tux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
994 texture_draw(&tux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
999 /* Tux got coffee! */
1001 if (pplayer->dir == RIGHT)
1003 texture_draw(&firetux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
1007 texture_draw(&firetux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
1013 if (timer_started(&pplayer->invincible_timer))
1017 if (pplayer->dir == RIGHT)
1019 texture_draw(&bigcape_right[frame % 2],
1020 pplayer->base.x- scroll_x, pplayer->base.y,
1025 texture_draw(&bigcape_left[frame % 2],
1026 pplayer->base.x-scroll_x, pplayer->base.y,
1031 if (!pplayer->got_coffee)
1035 if (!timer_started(&pplayer->skidding_timer))
1037 if (!pplayer->jumping || pplayer->base.ym > 0)
1039 if (pplayer->dir == RIGHT)
1041 texture_draw(&bigtux_right[pplayer->frame],
1042 pplayer->base.x- scroll_x, pplayer->base.y,
1047 texture_draw(&bigtux_left[pplayer->frame],
1048 pplayer->base.x- scroll_x, pplayer->base.y,
1054 if (pplayer->dir == RIGHT)
1056 texture_draw(&bigtux_right_jump,
1057 pplayer->base.x- scroll_x, pplayer->base.y,
1062 texture_draw(&bigtux_left_jump,
1063 pplayer->base.x- scroll_x, pplayer->base.y,
1070 if (pplayer->dir == RIGHT)
1072 texture_draw(&skidtux_right,
1073 pplayer->base.x- scroll_x, pplayer->base.y,
1078 texture_draw(&skidtux_left,
1079 pplayer->base.x- scroll_x, pplayer->base.y,
1086 if (pplayer->dir == RIGHT)
1088 texture_draw(&ducktux_right, pplayer->base.x- scroll_x, pplayer->base.y,
1093 texture_draw(&ducktux_left, pplayer->base.x- scroll_x, pplayer->base.y,
1100 /* Tux has coffee! */
1104 if (!timer_started(&pplayer->skidding_timer))
1106 if (!pplayer->jumping || pplayer->base.ym > 0)
1108 if (pplayer->dir == RIGHT)
1110 texture_draw(&bigfiretux_right[pplayer->frame],
1111 pplayer->base.x- scroll_x, pplayer->base.y,
1116 texture_draw(&bigfiretux_left[pplayer->frame],
1117 pplayer->base.x- scroll_x, pplayer->base.y,
1123 if (pplayer->dir == RIGHT)
1125 texture_draw(&bigfiretux_right_jump,
1126 pplayer->base.x- scroll_x, pplayer->base.y,
1131 texture_draw(&bigfiretux_left_jump,
1132 pplayer->base.x- scroll_x, pplayer->base.y,
1139 if (pplayer->dir == RIGHT)
1141 texture_draw(&skidfiretux_right,
1142 pplayer->base.x- scroll_x, pplayer->base.y,
1147 texture_draw(&skidfiretux_left,
1148 pplayer->base.x- scroll_x, pplayer->base.y,
1155 if (pplayer->dir == RIGHT)
1157 texture_draw(&duckfiretux_right, pplayer->base.x- scroll_x, pplayer->base.y,
1162 texture_draw(&duckfiretux_left, pplayer->base.x- scroll_x, pplayer->base.y,
1171 void player_collision(player_type* pplayer, void* p_c_object, int c_object)
1173 bad_guy_type* pbad_c = NULL;
1178 pbad_c = (bad_guy_type*) p_c_object;
1179 /* Hurt the player if he just touched it: */
1181 if (!pbad_c->dying && !pplayer->dying &&
1182 !timer_started(&pplayer->safe_timer) &&
1183 pbad_c->mode != HELD)
1185 if (pbad_c->mode == FLAT && pplayer->input.fire != DOWN)
1189 pbad_c->mode = KICK;
1190 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1192 if (pplayer->base.x<= pbad_c->base.x)
1194 pbad_c->dir = RIGHT;
1195 pbad_c->base.x = pbad_c->base.x + 16;
1200 pbad_c->base.x = pbad_c->base.x - 16;
1203 timer_start(&pbad_c->timer,5000);
1205 else if (pbad_c->mode == FLAT && pplayer->input.fire == DOWN)
1207 pbad_c->mode = HELD;
1210 else if (pbad_c->mode == KICK)
1212 if (pplayer->base.y < pbad_c->base.y - 16 &&
1213 timer_started(&pbad_c->timer))
1215 /* Step on (stop being kicked) */
1217 pbad_c->mode = FLAT;
1218 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1219 timer_start(&pbad_c->timer, 10000);
1223 /* Hurt if you get hit by kicked laptop: */
1225 if (timer_started(&pbad_c->timer))
1227 if (!timer_started(&pplayer->invincible_timer))
1229 player_kill(pplayer,SHRINK);
1233 pbad_c->dying = FALLING;
1234 pbad_c->base.ym = -8;
1235 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1242 if (!timer_started(&pplayer->invincible_timer ))
1244 player_kill(pplayer,SHRINK);
1248 pbad_c->dying = FALLING;
1249 pbad_c->base.ym = -8;
1250 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1264 void player_kill(player_type* pplayer, int mode)
1266 pplayer->base.ym = -5;
1268 play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
1270 if (pplayer->dir == RIGHT)
1271 pplayer->base.xm = -8;
1272 else if (pplayer->dir == LEFT)
1273 pplayer->base.xm = 8;
1275 if (mode == SHRINK && pplayer->size == BIG)
1277 if (pplayer->got_coffee)
1278 pplayer->got_coffee = NO;
1280 pplayer->size = SMALL;
1281 pplayer->base.height = 32;
1283 timer_start(&pplayer->safe_timer,TUX_SAFE_TIME);
1291 void player_dying(player_type *pplayer)
1293 pplayer->base.ym = pplayer->base.ym + gravity;
1298 player_remove_powerups(pplayer);
1299 pplayer->dying = NO;
1301 player_level_begin(pplayer);
1305 /* Remove Tux's power ups */
1306 void player_remove_powerups(player_type* pplayer)
1308 pplayer->got_coffee = NO;
1309 pplayer->size = SMALL;
1310 pplayer->base.height = 32;
1313 void player_keep_in_bounds(player_type* pplayer)
1315 /* Keep tux in bounds: */
1316 if (pplayer->base.x< 0)
1318 else if(pplayer->base.x< scroll_x)
1319 pplayer->base.x= scroll_x;
1320 else if (pplayer->base.x< 160 + scroll_x && scroll_x > 0 && debug_mode == YES)
1322 scroll_x = pplayer->base.x- 160;
1323 /*pplayer->base.x+= 160;*/
1329 else if (pplayer->base.x> screen->w / 2 + scroll_x && scroll_x < ((current_level.width * 32) - screen->w))
1331 /* Scroll the screen in past center: */
1333 scroll_x = pplayer->base.x- screen->w / 2;
1334 /*pplayer->base.x= 320 + scroll_x;*/
1336 if (scroll_x > ((current_level.width * 32) - screen->w))
1337 scroll_x = ((current_level.width * 32) - screen->w);
1339 else if (pplayer->base.x> 608 + scroll_x)
1341 /* ... unless there's no more to scroll! */
1343 /*pplayer->base.x= 608 + scroll_x;*/
1346 /* Keep in-bounds, vertically: */
1348 if (pplayer->base.y < 0)
1349 pplayer->base.y = 0;
1350 else if (pplayer->base.y > screen->h)
1352 player_kill(&tux,KILL);