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,YES);
72 timer_init(&pplayer->skidding_timer,YES);
73 timer_init(&pplayer->safe_timer,YES);
74 timer_init(&pplayer->frame_timer,YES);
75 physic_init(&pplayer->hphysic);
76 physic_init(&pplayer->vphysic);
79 int player_key_event(player_type* pplayer, SDLKey key, int state)
81 if(key == pplayer->keymap.right)
83 pplayer->input.right = state;
86 else if( key == pplayer->keymap.left)
88 pplayer->input.left = state;
91 else if(key == pplayer->keymap.jump)
93 pplayer->input.up = state;
96 else if(key == pplayer->keymap.duck)
98 pplayer->input.down = state;
101 else if(key == pplayer->keymap.fire)
103 pplayer->input.fire = state;
110 void player_level_begin(player_type* pplayer)
113 pplayer->base.y = 240;
114 pplayer->base.xm = 0;
115 pplayer->base.ym = 0;
117 pplayer->input.down = UP;
118 pplayer->input.fire = UP;
119 pplayer->input.left = UP;
120 pplayer->input.old_fire = UP;
121 pplayer->input.right = UP;
122 pplayer->input.up = UP;
124 timer_init(&pplayer->invincible_timer,YES);
125 timer_init(&pplayer->skidding_timer,YES);
126 timer_init(&pplayer->safe_timer,YES);
127 timer_init(&pplayer->frame_timer,YES);
128 physic_init(&pplayer->hphysic);
129 physic_init(&pplayer->vphysic);
132 void player_action(player_type* pplayer)
134 /* --- HANDLE TUX! --- */
136 player_input(pplayer);
140 pplayer->base.x += pplayer->base.xm * frame_ratio;
141 pplayer->base.y += pplayer->base.ym * frame_ratio;
143 player_keep_in_bounds(pplayer);
150 while(issolid( pplayer->base.x + 16, pplayer->base.y + pplayer->base.height) && !issolid( pplayer->base.x + 16, pplayer->base.y + 1))
154 while(issolid( pplayer->base.x + 16, pplayer->base.y + 1) && !issolid( pplayer->base.x + 16, pplayer->base.y + pplayer->base.height))
158 while(issolid( pplayer->base.x - 1, pplayer->base.y + 1) || issolid( pplayer->base.x - 1, pplayer->base.y+pplayer->base.height))
162 while(issolid( pplayer->base.x + 32, pplayer->base.y + 1) || issolid( pplayer->base.x + 32, pplayer->base.y+pplayer->base.height))
167 /*if(physic_is_set(&pplayer->vphysic))
169 pplayer->base.ym = physic_get_velocity(&pplayer->vphysic);
173 if( /*!issolid( pplayer->base.x + 16, pplayer->base.y + pplayer->base.height )*/ !player_on_ground(pplayer))
175 if(!physic_is_set(&pplayer->vphysic))
177 physic_set_state(&pplayer->vphysic,PH_VT);
178 physic_set_start_vy(&pplayer->vphysic,0.);
180 pplayer->base.ym = physic_get_velocity(&pplayer->vphysic);
186 if (pplayer->base.ym > 0)
188 pplayer->base.y = (int)(((int)(pplayer->base.y +1) / 32) * 32);
189 pplayer->base.ym = 0;
191 physic_init(&pplayer->vphysic);
194 if(pplayer->base.ym < 0)
197 if (isbrick(pplayer->base.x, pplayer->base.y) ||
198 isfullbox(pplayer->base.x, pplayer->base.y))
200 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
201 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
203 if(pplayer->size == BIG)
204 trybreakbrick(pplayer->base.x, pplayer->base.y);
206 bumpbrick(pplayer->base.x, pplayer->base.y);
207 tryemptybox(pplayer->base.x, pplayer->base.y);
210 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
211 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
213 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
214 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
216 if(pplayer->size == BIG)
217 trybreakbrick(pplayer->base.x+ 31, pplayer->base.y);
219 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
220 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
224 if(pplayer->size == SMALL)
226 /* Get a distro from a brick? */
228 if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
229 shape(pplayer->base.x, pplayer->base.y) == 'y')
231 add_bouncy_distro((((int)pplayer->base.x)
233 ((int)pplayer->base.y / 32) * 32);
234 if (counting_distros == NO)
236 counting_distros = YES;
237 distro_counter = 100;
240 if (distro_counter <= 0)
241 level_change(¤t_level,pplayer->base.x,pplayer->base.y - 1, 'a');
243 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
244 score = score + SCORE_DISTRO;
247 else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
248 shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
250 add_bouncy_distro((((int)pplayer->base.x + 31)
252 ((int)pplayer->base.y / 32) * 32);
253 if (counting_distros == NO)
255 counting_distros = YES;
256 distro_counter = 100;
259 if (distro_counter <= 0)
260 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
262 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
263 score = score + SCORE_DISTRO;
269 player_grabdistros(pplayer);
271 /* FIXME: this code is COMPLETLY broken!!! */
272 /* if (issolid(pplayer->base.x, pplayer->base.y + 31) &&
273 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y + 31))
275 while (issolid(pplayer->base.x, pplayer->base.y + 31))
277 if (pplayer->base.xm < 0)
279 else if (pplayer->base.xm > 0)
283 pplayer->base.xm = 0;
286 /*if (issolid(pplayer->base.x, pplayer->base.y) &&
287 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y))
289 while (issolid(pplayer->base.x, (pplayer->base.y)))
291 if (pplayer->base.xm < 0)
293 else if (pplayer->base.xm > 0)
297 pplayer->base.xm = 0;
300 /*if (issolid(pplayer->base.x, pplayer->base.y + 31))
302 /* Set down properly: * /
305 while (issolid(pplayer->base.x, pplayer->base.y + 31))
310 DEBUG_MSG("FIXME - UNDER certain circumstances I'm hanging in a loop here!");
311 /*the circumstances are:
312 issolid() is true and base.ym == 0
313 use of floating point varibles for base stuff* /
316 if (pplayer->base.ym < 0)
318 else if (pplayer->base.ym > 0)
323 /* Reset score multiplier (for multi-hits): */
325 if (pplayer->base.ym > 2)
326 score_multiplier = 1;
331 pplayer->base.ym = 0;
332 pplayer->jumping = NO;
333 pplayer->input.up = UP;
335 /* FIXME: this code is COMPLETLY broken!!! */
336 /*if (issolid(pplayer->base.x, pplayer->base.y) ||
337 (pplayer->size == BIG && !pplayer->duck &&
338 (issolid(pplayer->base.x, pplayer->base.y - 32))))
340 /*if (!issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y) &&
341 (pplayer->size == SMALL || pplayer->duck ||
342 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32)))* /
344 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))))
345 ||((!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)))))
346 /*(pplayer->size == SMALL || pplayer->duck ||
347 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))* /
349 pplayer->base.y = pplayer->base.y- pplayer->base.ym * frame_ratio;
350 pplayer->base.ym = 0;
353 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))
354 /*(pplayer->size == SMALL || pplayer->duck ||
355 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))* /) ||
356 (!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))))
358 pplayer->base.x = pplayer->base.x- pplayer->base.xm * frame_ratio;
359 pplayer->base.xm = 0;
362 if (pplayer->base.ym <= 0)
364 if (isbrick(pplayer->base.x, pplayer->base.y) ||
365 isfullbox(pplayer->base.x, pplayer->base.y))
367 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
368 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
369 bumpbrick(pplayer->base.x, pplayer->base.y);
370 tryemptybox(pplayer->base.x, pplayer->base.y);
373 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
374 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
376 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
377 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
378 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
379 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
381 /* Get a distro from a brick? * /
383 if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
384 shape(pplayer->base.x, pplayer->base.y) == 'y')
386 add_bouncy_distro(((pplayer->base.x+ 1)
388 (int)(pplayer->base.y / 32) * 32);
390 if (counting_distros == NO)
392 counting_distros = YES;
393 distro_counter = 100;
396 if (distro_counter <= 0)
397 level_change(¤t_level,pplayer->base.x,pplayer->base.y, 'a');
399 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
400 score = score + SCORE_DISTRO;
403 else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
404 shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
406 add_bouncy_distro(((pplayer->base.x+ 1 + 31)
408 (int)(pplayer->base.y / 32) * 32);
410 if (counting_distros == NO)
412 counting_distros = YES;
413 distro_counter = 100;
416 if (distro_counter <= 0)
417 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
419 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
420 score = score + SCORE_DISTRO;
427 pplayer->base.ym = 0;
428 pplayer->jumping = NO;
429 timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
432 /* Bump into things: * /
434 if (issolid(pplayer->base.x, pplayer->base.y) ||
435 (pplayer->size == BIG && !pplayer->duck &&
436 (issolid(pplayer->base.x, pplayer->base.y - 32))))
439 if (!issolid(pplayer->base.x, pplayer->base.y - pplayer->base.ym) &&
440 (pplayer->size == SMALL || pplayer->duck ||
441 !issolid(pplayer->base.x, pplayer->base.y - 32 - pplayer->base.ym)))
443 if (pplayer->base.ym <= 0)
446 /* FIXME: this code is COMPLETLY broken!!! */
447 if (pplayer->size == BIG)
449 /* Break bricks and empty boxes: * /
453 if (isbrick(pplayer->base.x, pplayer->base.y - 32) ||
454 isfullbox(pplayer->base.x, pplayer->base.y - 32))
456 trygrabdistro(pplayer->base.x, pplayer->base.y - 64, BOUNCE);
457 trybumpbadguy(pplayer->base.x, pplayer->base.y - 96);
459 if (isfullbox(pplayer->base.x, pplayer->base.y - 32))
461 bumpbrick(pplayer->base.x, pplayer->base.y - 32);
464 trybreakbrick(pplayer->base.x, pplayer->base.y - 32);
465 tryemptybox(pplayer->base.x, pplayer->base.y - 32);
468 if (isbrick(pplayer->base.x+ 31, pplayer->base.y - 32) ||
469 isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
471 trygrabdistro(pplayer->base.x+ 31,
472 pplayer->base.y - 64,
474 trybumpbadguy(pplayer->base.x+ 31,
475 pplayer->base.y - 96);
477 if (isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
479 bumpbrick(pplayer->base.x+ 31, pplayer->base.y - 32);
482 trybreakbrick(pplayer->base.x+ 31,
483 pplayer->base.y - 32);
484 tryemptybox(pplayer->base.x+ 31,
485 pplayer->base.y - 32);
490 if (isbrick(pplayer->base.x, pplayer->base.y) ||
491 isfullbox(pplayer->base.x, pplayer->base.y))
493 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
494 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
495 if (isfullbox(pplayer->base.x, pplayer->base.y))
496 bumpbrick(pplayer->base.x, pplayer->base.y);
497 trybreakbrick(pplayer->base.x, pplayer->base.y);
498 tryemptybox(pplayer->base.x, pplayer->base.y);
501 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
502 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
504 trygrabdistro(pplayer->base.x+ 31,
505 pplayer->base.y - 32,
507 trybumpbadguy(pplayer->base.x+ 31,
508 pplayer->base.y - 64);
509 if (isfullbox(pplayer->base.x+ 31, pplayer->base.y))
510 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
511 trybreakbrick(pplayer->base.x+ 31, pplayer->base.y);
512 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
518 /* It's a brick and we're small, make the brick
519 bounce, and grab any distros above it: * /
521 if (isbrick(pplayer->base.x, pplayer->base.y) ||
522 isfullbox(pplayer->base.x, pplayer->base.y))
524 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
525 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
526 bumpbrick(pplayer->base.x, pplayer->base.y);
527 tryemptybox(pplayer->base.x, pplayer->base.y);
530 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
531 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
533 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
534 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
535 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
536 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
540 /* Get a distro from a brick? * /
542 if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
543 shape(pplayer->base.x, pplayer->base.y) == 'y')
545 add_bouncy_distro(((pplayer->base.x+ 1)
547 (int)(pplayer->base.y / 32) * 32);
549 if (counting_distros == NO)
551 counting_distros = YES;
552 distro_counter = 100;
555 if (distro_counter <= 0)
556 level_change(¤t_level,pplayer->base.x,pplayer->base.y, 'a');
558 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
559 score = score + SCORE_DISTRO;
562 else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
563 shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
565 add_bouncy_distro(((pplayer->base.x+ 1 + 31)
567 (int)(pplayer->base.y / 32) * 32);
569 if (counting_distros == NO)
571 counting_distros = YES;
572 distro_counter = 100;
575 if (distro_counter <= 0)
576 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
578 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
579 score = score + SCORE_DISTRO;
587 pplayer->base.y = (int)(pplayer->base.y / 32) * 32 + 30;
593 pplayer->base.y = (int)(pplayer->base.y / 32) * 32 - 32;
596 pplayer->base.ym = 0;
597 pplayer->jumping = NO;
598 timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
605 player_grabdistros(pplayer);
608 /* Slow down horizontally: * /
612 if (pplayer->input.right == UP && pplayer->input.left == UP)
614 if (isice(pplayer->base.x, pplayer->base.y + 32) ||
615 !issolid(pplayer->base.x, pplayer->base.y + 32))
617 /* Slowly on ice or in air: * /
619 if (pplayer->base.xm > 0)
621 else if (pplayer->base.xm < 0)
626 /* Quickly, otherwise: * /
628 pplayer->base.xm = pplayer->base.xm / 2;
633 /* Drop vertically: * /
635 if (!issolid(pplayer->base.x, pplayer->base.y + 32))
637 pplayer->base.ym = pplayer->base.ym + GRAVITY;
639 if (pplayer->base.ym > MAX_YM)
640 pplayer->base.ym = MAX_YM;
646 timer_check(&pplayer->safe_timer);
649 /* ---- DONE HANDLING TUX! --- */
651 /* Handle invincibility timer: */
654 if (current_music == HERRING_MUSIC && !timer_check(&pplayer->invincible_timer))
657 no, we are no more invincible
658 or we were not in invincible mode
659 but are we in hurry ?
663 if (timer_get_left(&time_left) < TIME_WARNING)
665 /* yes, we are in hurry
666 stop the herring_song, prepare to play the correct
669 current_music = HURRYUP_MUSIC;
673 current_music = LEVEL_MUSIC;
676 /* stop the old music if it's being played */
681 /* Handle skidding: */
683 timer_check(&pplayer->skidding_timer);
687 if (pplayer->base.x - scroll_x >= endpos && endpos != 0)
694 int player_on_ground(player_type *pplayer)
696 if( issolid(pplayer->base.x + pplayer->base.width / 2, pplayer->base.y + pplayer->base.height + 1) ||
697 issolid(pplayer->base.x + 1, pplayer->base.y + pplayer->base.height + 1) ||
698 issolid(pplayer->base.x + pplayer->base.width - 1, pplayer->base.y + pplayer->base.height + 1) )
708 void player_handle_horizontal_input(player_type *pplayer, int dir)
710 if (pplayer->jumping == NO)
712 if ((dir ? (pplayer->base.xm < -SKID_XM) : (pplayer->base.xm > SKID_XM)) && !timer_started(&pplayer->skidding_timer) &&
713 pplayer->dir == !dir)
715 timer_start(&pplayer->skidding_timer, SKID_TIME);
717 play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
723 if ((dir ? (pplayer->base.xm < 0) : (pplayer->base.xm > 0)) && !isice(pplayer->base.x, pplayer->base.y + 32) &&
724 !timer_started(&pplayer->skidding_timer))
726 pplayer->base.xm = 0;
731 if (pplayer->dir == dir)
733 /* Facing the direction we're jumping? Go full-speed: */
735 if (pplayer->input.fire == UP)
737 pplayer->base.xm = pplayer->base.xm + ( dir ? WALK_SPEED : -WALK_SPEED) * frame_ratio;
741 if (pplayer->base.xm > MAX_WALK_XM)
742 pplayer->base.xm = MAX_WALK_XM;
746 if (pplayer->base.xm < -MAX_WALK_XM)
747 pplayer->base.xm = -MAX_WALK_XM;
750 else if ( pplayer->input.fire == DOWN)
752 pplayer->base.xm = pplayer->base.xm + ( dir ? RUN_SPEED : -RUN_SPEED) * frame_ratio;
756 if (pplayer->base.xm > MAX_RUN_XM)
757 pplayer->base.xm = MAX_RUN_XM;
761 if (pplayer->base.xm < -MAX_RUN_XM)
762 pplayer->base.xm = -MAX_RUN_XM;
767 /* Not facing the direction we're jumping?
770 pplayer->base.xm = pplayer->base.xm + ( dir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio;
774 if (pplayer->base.xm > MAX_WALK_XM / 2)
775 pplayer->base.xm = MAX_WALK_XM / 2;
779 if (pplayer->base.xm < -MAX_WALK_XM / 2)
780 pplayer->base.xm = -MAX_WALK_XM / 2;
788 void player_handle_vertical_input(player_type *pplayer)
790 if(pplayer->input.up == DOWN)
792 if (player_on_ground(pplayer))
794 if(!physic_is_set(&pplayer->vphysic))
796 physic_set_state(&pplayer->vphysic,PH_VT);
797 physic_set_start_vy(&pplayer->vphysic,5.5);
799 pplayer->jumping = YES;
800 if (pplayer->size == SMALL)
801 play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
803 play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
807 else if(pplayer->input.up == UP && pplayer->jumping == YES)
809 if (issolid(pplayer->base.x + 16, pplayer->base.y + pplayer->base.height + 1))
811 physic_init(&pplayer->vphysic);
812 pplayer->jumping == NO;
816 pplayer->jumping = NO;
817 if(physic_is_set(&pplayer->vphysic))
819 if(physic_get_velocity(&pplayer->vphysic) < 0.)
821 physic_set_state(&pplayer->vphysic,PH_VT);
822 physic_set_start_vy(&pplayer->vphysic,0);
827 if(!physic_is_set(&pplayer->vphysic))
829 physic_set_state(&pplayer->vphysic,PH_VT);
837 if (!issolid(pplayer->base.x, pplayer->base.y + 32) ||
838 pplayer->base.ym != 0)
840 /* If they're not on the ground, or are currently moving
841 vertically, don't jump! * /
843 pplayer->jumping = NO;
844 timer_stop(&pplayer->jump_timer);
848 /* Make sure we're not standing back up into a solid! * /
850 if (pplayer->size == SMALL || pplayer->duck == NO ||
851 !issolid(pplayer->base.x, pplayer->base.y))
853 pplayer->jumping = YES;
855 if (pplayer->size == SMALL)
856 play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
858 play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
862 /* Keep jumping for a while: * /
864 if (timer_check(&pplayer->jump_timer))
866 pplayer->base.ym = pplayer->base.ym - JUMP_SPEED * frame_ratio;
867 if (pplayer->base.ym < -YM_FOR_JUMP)
868 pplayer->base.ym = pplayer->base.ym/*-YM_FOR_JUMP* /;
872 void player_input(player_type *pplayer)
874 /* Handle key and joystick state: */
877 if (pplayer->input.right == DOWN && pplayer->input.left == UP)
879 player_handle_horizontal_input(pplayer,RIGHT);
881 else if (pplayer->input.left == DOWN && pplayer->input.right == UP)
883 player_handle_horizontal_input(pplayer,LEFT);
887 if(pplayer->base.xm > 0)
889 pplayer->base.xm = (int)(pplayer->base.xm - frame_ratio);
890 if(pplayer->base.xm < 0)
891 pplayer->base.xm = 0;
893 else if(pplayer->base.xm < 0)
895 pplayer->base.xm = (int)(pplayer->base.xm + frame_ratio);
896 if(pplayer->base.xm > 0)
897 pplayer->base.xm = 0;
903 if ( pplayer->input.up == DOWN || (pplayer->input.up == UP && pplayer->jumping == YES))
905 player_handle_vertical_input(pplayer);
910 if (pplayer->input.fire == DOWN && pplayer->input.old_fire == UP && pplayer->got_coffee)
912 add_bullet(pplayer->base.x, pplayer->base.y, pplayer->base.xm, pplayer->dir);
918 if (pplayer->input.down == DOWN)
920 if (pplayer->size == BIG)
923 pplayer->base.height = 32;
928 if (pplayer->size == BIG && pplayer->duck == YES)
930 /* Make sure we're not standing back up into a solid! */
932 if (!issolid(pplayer->base.x + 16, pplayer->base.y - 16))
935 pplayer->base.height = 64;
946 if(!timer_check(&pplayer->frame_timer))
948 timer_start(&pplayer->frame_timer,25);
949 if (pplayer->input.right == UP && pplayer->input.left == UP)
951 pplayer->frame_main = 1;
956 if ((pplayer->input.fire == DOWN && (frame % 2) == 0) ||
958 pplayer->frame_main = (pplayer->frame_main + 1) % 4;
960 pplayer->frame = pplayer->frame_main;
962 if (pplayer->frame == 3)
969 void player_grabdistros(player_type *pplayer)
974 trygrabdistro(pplayer->base.x, pplayer->base.y, NO_BOUNCE);
975 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y, NO_BOUNCE);
977 trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height, NO_BOUNCE);
978 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height, NO_BOUNCE);
980 if(pplayer->size == BIG)
982 trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE);
983 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE);
989 /* Enough distros for a One-up? */
991 if (distros >= DISTROS_LIFEUP)
993 distros = distros - DISTROS_LIFEUP;
994 if(pplayer->lives < MAX_LIVES)
996 /*We want to hear the sound even, if MAX_LIVES is reached*/
997 play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
1001 void player_draw(player_type* pplayer)
1003 if (!timer_started(&pplayer->safe_timer) || (frame % 2) == 0)
1005 if (pplayer->size == SMALL)
1007 if (timer_started(&pplayer->invincible_timer))
1011 if (pplayer->dir == RIGHT)
1013 texture_draw(&cape_right[frame % 2],
1014 pplayer->base.x- scroll_x, pplayer->base.y,
1019 texture_draw(&cape_left[frame % 2],
1020 pplayer->base.x- scroll_x, pplayer->base.y,
1026 if (!pplayer->got_coffee)
1028 if (pplayer->dir == RIGHT)
1030 texture_draw(&tux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
1034 texture_draw(&tux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
1039 /* Tux got coffee! */
1041 if (pplayer->dir == RIGHT)
1043 texture_draw(&firetux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
1047 texture_draw(&firetux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
1053 if (timer_started(&pplayer->invincible_timer))
1057 if (pplayer->dir == RIGHT)
1059 texture_draw(&bigcape_right[frame % 2],
1060 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1065 texture_draw(&bigcape_left[frame % 2],
1066 pplayer->base.x-scroll_x - 8, pplayer->base.y,
1071 if (!pplayer->got_coffee)
1075 if (!timer_started(&pplayer->skidding_timer))
1077 if (!pplayer->jumping || pplayer->base.ym > 0)
1079 if (pplayer->dir == RIGHT)
1081 texture_draw(&bigtux_right[pplayer->frame],
1082 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1087 texture_draw(&bigtux_left[pplayer->frame],
1088 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1094 if (pplayer->dir == RIGHT)
1096 texture_draw(&bigtux_right_jump,
1097 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1102 texture_draw(&bigtux_left_jump,
1103 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1110 if (pplayer->dir == RIGHT)
1112 texture_draw(&skidtux_right,
1113 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1118 texture_draw(&skidtux_left,
1119 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1126 if (pplayer->dir == RIGHT)
1128 texture_draw(&ducktux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
1133 texture_draw(&ducktux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
1140 /* Tux has coffee! */
1144 if (!timer_started(&pplayer->skidding_timer))
1146 if (!pplayer->jumping || pplayer->base.ym > 0)
1148 if (pplayer->dir == RIGHT)
1150 texture_draw(&bigfiretux_right[pplayer->frame],
1151 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1156 texture_draw(&bigfiretux_left[pplayer->frame],
1157 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1163 if (pplayer->dir == RIGHT)
1165 texture_draw(&bigfiretux_right_jump,
1166 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1171 texture_draw(&bigfiretux_left_jump,
1172 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1179 if (pplayer->dir == RIGHT)
1181 texture_draw(&skidfiretux_right,
1182 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1187 texture_draw(&skidfiretux_left,
1188 pplayer->base.x- scroll_x - 8, pplayer->base.y,
1195 if (pplayer->dir == RIGHT)
1197 texture_draw(&duckfiretux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
1202 texture_draw(&duckfiretux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16,
1211 void player_collision(player_type* pplayer, void* p_c_object, int c_object)
1213 bad_guy_type* pbad_c = NULL;
1218 pbad_c = (bad_guy_type*) p_c_object;
1219 /* Hurt the player if he just touched it: */
1221 if (!pbad_c->dying && !pplayer->dying &&
1222 !timer_started(&pplayer->safe_timer) &&
1223 pbad_c->mode != HELD)
1225 if (pbad_c->mode == FLAT && pplayer->input.fire != DOWN)
1229 pbad_c->mode = KICK;
1230 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1232 if (pplayer->base.x<= pbad_c->base.x)
1234 pbad_c->dir = RIGHT;
1235 pbad_c->base.x = pbad_c->base.x + 16;
1240 pbad_c->base.x = pbad_c->base.x - 16;
1243 timer_start(&pbad_c->timer,5000);
1245 else if (pbad_c->mode == FLAT && pplayer->input.fire == DOWN)
1247 pbad_c->mode = HELD;
1250 else if (pbad_c->mode == KICK)
1252 if (pplayer->base.y < pbad_c->base.y - 16 &&
1253 timer_started(&pbad_c->timer))
1255 /* Step on (stop being kicked) */
1257 pbad_c->mode = FLAT;
1258 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1259 timer_start(&pbad_c->timer, 10000);
1263 /* Hurt if you get hit by kicked laptop: */
1265 if (timer_started(&pbad_c->timer))
1267 if (!timer_started(&pplayer->invincible_timer))
1269 player_kill(pplayer,SHRINK);
1273 pbad_c->dying = FALLING;
1274 physic_set_state(&pplayer->vphysic,PH_VT);
1275 physic_set_start_vy(&pplayer->vphysic,-2.);
1276 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1283 if (!timer_started(&pplayer->invincible_timer ))
1285 player_kill(pplayer,SHRINK);
1289 pbad_c->dying = FALLING;
1290 physic_set_state(&pplayer->vphysic,PH_VT);
1291 physic_set_start_vy(&pplayer->vphysic,-2.);
1292 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1306 void player_kill(player_type* pplayer, int mode)
1308 pplayer->base.ym = -5;
1310 play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
1312 if (pplayer->dir == RIGHT)
1313 pplayer->base.xm = -8;
1314 else if (pplayer->dir == LEFT)
1315 pplayer->base.xm = 8;
1317 if (mode == SHRINK && pplayer->size == BIG)
1319 if (pplayer->got_coffee)
1320 pplayer->got_coffee = NO;
1322 pplayer->size = SMALL;
1323 pplayer->base.height = 32;
1325 timer_start(&pplayer->safe_timer,TUX_SAFE_TIME);
1333 void player_dying(player_type *pplayer)
1335 pplayer->base.ym = pplayer->base.ym + gravity;
1340 player_remove_powerups(pplayer);
1341 pplayer->dying = NO;
1343 player_level_begin(pplayer);
1347 /* Remove Tux's power ups */
1348 void player_remove_powerups(player_type* pplayer)
1350 pplayer->got_coffee = NO;
1351 pplayer->size = SMALL;
1352 pplayer->base.height = 32;
1355 void player_keep_in_bounds(player_type* pplayer)
1357 /* Keep tux in bounds: */
1358 if (pplayer->base.x< 0)
1360 else if(pplayer->base.x< scroll_x)
1361 pplayer->base.x= scroll_x;
1362 else if (pplayer->base.x< 160 + scroll_x && scroll_x > 0 && debug_mode == YES)
1364 scroll_x = pplayer->base.x- 160;
1365 /*pplayer->base.x+= 160;*/
1371 else if (pplayer->base.x> screen->w / 2 + scroll_x && scroll_x < ((current_level.width * 32) - screen->w))
1373 /* Scroll the screen in past center: */
1375 scroll_x = pplayer->base.x- screen->w / 2;
1376 /*pplayer->base.x= 320 + scroll_x;*/
1378 if (scroll_x > ((current_level.width * 32) - screen->w))
1379 scroll_x = ((current_level.width * 32) - screen->w);
1381 else if (pplayer->base.x> 608 + scroll_x)
1383 /* ... unless there's no more to scroll! */
1385 /*pplayer->base.x= 608 + scroll_x;*/
1388 /* Keep in-bounds, vertically: */
1390 if (pplayer->base.y < 0)
1391 pplayer->base.y = 0;
1392 else if (pplayer->base.y > screen->h)
1394 player_kill(&tux,KILL);