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;
56 pplayer->input.down = UP;
57 pplayer->input.fire = UP;
58 pplayer->input.left = UP;
59 pplayer->input.old_fire = UP;
60 pplayer->input.right = UP;
61 pplayer->input.up = UP;
63 pplayer->keymap.jump = SDLK_UP;
64 pplayer->keymap.duck = SDLK_DOWN;
65 pplayer->keymap.left = SDLK_LEFT;
66 pplayer->keymap.right = SDLK_RIGHT;
67 pplayer->keymap.fire = SDLK_LCTRL;
69 timer_init(&pplayer->invincible_timer);
70 timer_init(&pplayer->skidding_timer);
71 timer_init(&pplayer->safe_timer);
74 int player_keydown_event(player_type* pplayer, SDLKey key)
76 if(key == pplayer->keymap.right)
78 pplayer->input.right = DOWN;
81 else if( key == pplayer->keymap.left)
83 pplayer->input.left = DOWN;
86 else if(key == pplayer->keymap.jump)
88 pplayer->input.up = DOWN;
91 else if(key == pplayer->keymap.duck)
93 pplayer->input.down = DOWN;
96 else if(key == pplayer->keymap.fire)
98 pplayer->input.fire = DOWN;
105 int player_keyup_event(player_type* pplayer, SDLKey key)
107 if(key == pplayer->keymap.right)
109 pplayer->input.right = UP;
112 else if( key == pplayer->keymap.left)
114 pplayer->input.left = UP;
117 else if(key == pplayer->keymap.jump)
119 pplayer->input.up = UP;
122 else if(key == pplayer->keymap.duck)
124 pplayer->input.down = UP;
127 else if(key == pplayer->keymap.fire)
129 pplayer->input.fire = UP;
136 void player_level_begin(player_type* pplayer)
139 pplayer->base.y = 240;
140 pplayer->base.xm = 0;
141 pplayer->base.ym = 0;
143 pplayer->input.down = UP;
144 pplayer->input.fire = UP;
145 pplayer->input.left = UP;
146 pplayer->input.old_fire = UP;
147 pplayer->input.right = UP;
148 pplayer->input.up = UP;
150 timer_init(&pplayer->invincible_timer);
151 timer_init(&pplayer->skidding_timer);
152 timer_init(&pplayer->safe_timer);
155 void player_action(player_type* pplayer)
157 /* --- HANDLE TUX! --- */
159 player_input(pplayer);
163 pplayer->base.x= pplayer->base.x+ pplayer->base.xm * frame_ratio;
164 pplayer->base.y = pplayer->base.y + pplayer->base.ym * frame_ratio;
166 player_keep_in_bounds(pplayer);
172 /* FIXME: this code is COMPLETLY broken!!! */
173 if (issolid(pplayer->base.x, pplayer->base.y + 31) &&
174 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y + 31))
176 while (issolid(pplayer->base.x, pplayer->base.y + 31))
178 if (pplayer->base.xm < 0)
180 else if (pplayer->base.xm > 0)
184 pplayer->base.xm = 0;
187 if (issolid(pplayer->base.x, pplayer->base.y) &&
188 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y))
190 while (issolid(pplayer->base.x, (pplayer->base.y)))
192 if (pplayer->base.xm < 0)
194 else if (pplayer->base.xm > 0)
198 pplayer->base.xm = 0;
201 if (issolid(pplayer->base.x, pplayer->base.y + 31))
203 /* Set down properly: */
206 while (issolid(pplayer->base.x, pplayer->base.y + 31))
211 DEBUG_MSG("FIXME - UNDER certain circumstances I'm hanging in a loop here!");
212 /*the circumstances are:
213 issolid() is true and base.ym == 0
214 use of floating point varibles for base stuff*/
217 if (pplayer->base.ym < 0)
219 else if (pplayer->base.ym > 0)
224 /* Reset score multiplier (for multi-hits): */
226 if (pplayer->base.ym > 0)
227 score_multiplier = 1;
232 pplayer->base.ym = 0;
233 pplayer->jumping = NO;
234 pplayer->input.up = UP;
236 /* FIXME: this code is COMPLETLY broken!!! */
237 /*if (issolid(pplayer->base.x, pplayer->base.y) ||
238 (pplayer->size == BIG && !pplayer->duck &&
239 (issolid(pplayer->base.x, pplayer->base.y - 32))))
241 /*if (!issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y) &&
242 (pplayer->size == SMALL || pplayer->duck ||
243 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32)))*/
245 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))))
246 ||((!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)))))
247 /*(pplayer->size == SMALL || pplayer->duck ||
248 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))*/
250 pplayer->base.y = pplayer->base.y- pplayer->base.ym * frame_ratio;
251 pplayer->base.ym = 0;
254 if ((!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))
255 /*(pplayer->size == SMALL || pplayer->duck ||
256 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))*/) || ( pplayer->size == BIG && (
257 (!issolid(pplayer->base.x - pplayer->base.xm * frame_ratio, pplayer->base.y+32) && (issolid(pplayer->base.x, pplayer->base.y+32) || issolid(pplayer->base.x+32, pplayer->base.y+32))
258 /*(pplayer->size == SMALL || pplayer->duck ||
259 !issolid(pplayer->base.x- pplayer->base.xm, pplayer->base.y - 32))*/))))
261 pplayer->base.x = pplayer->base.x- pplayer->base.xm * frame_ratio;
262 pplayer->base.xm = 0;
265 if (pplayer->base.ym <= 0)
267 if (isbrick(pplayer->base.x, pplayer->base.y) ||
268 isfullbox(pplayer->base.x, pplayer->base.y))
270 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
271 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
272 bumpbrick(pplayer->base.x, pplayer->base.y);
273 tryemptybox(pplayer->base.x, pplayer->base.y);
276 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
277 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
279 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
280 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
281 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
282 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
284 /* Get a distro from a brick? */
286 if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
287 shape(pplayer->base.x, pplayer->base.y) == 'y')
289 add_bouncy_distro(((pplayer->base.x+ 1)
291 (int)(pplayer->base.y / 32) * 32);
293 if (counting_distros == NO)
295 counting_distros = YES;
296 distro_counter = 100;
299 if (distro_counter <= 0)
300 level_change(¤t_level,pplayer->base.x,pplayer->base.y, 'a');
302 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
303 score = score + SCORE_DISTRO;
306 else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
307 shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
309 add_bouncy_distro(((pplayer->base.x+ 1 + 31)
311 (int)(pplayer->base.y / 32) * 32);
313 if (counting_distros == NO)
315 counting_distros = YES;
316 distro_counter = 100;
319 if (distro_counter <= 0)
320 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
322 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
323 score = score + SCORE_DISTRO;
330 pplayer->base.ym = 0;
331 pplayer->jumping = NO;
332 timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
335 /* Bump into things: * /
337 if (issolid(pplayer->base.x, pplayer->base.y) ||
338 (pplayer->size == BIG && !pplayer->duck &&
339 (issolid(pplayer->base.x, pplayer->base.y - 32))))
342 if (!issolid(pplayer->base.x, pplayer->base.y - pplayer->base.ym) &&
343 (pplayer->size == SMALL || pplayer->duck ||
344 !issolid(pplayer->base.x, pplayer->base.y - 32 - pplayer->base.ym)))
346 if (pplayer->base.ym <= 0)
349 /* FIXME: this code is COMPLETLY broken!!! */
350 if (pplayer->size == BIG)
352 /* Break bricks and empty boxes: * /
356 if (isbrick(pplayer->base.x, pplayer->base.y - 32) ||
357 isfullbox(pplayer->base.x, pplayer->base.y - 32))
359 trygrabdistro(pplayer->base.x, pplayer->base.y - 64, BOUNCE);
360 trybumpbadguy(pplayer->base.x, pplayer->base.y - 96);
362 if (isfullbox(pplayer->base.x, pplayer->base.y - 32))
364 bumpbrick(pplayer->base.x, pplayer->base.y - 32);
367 trybreakbrick(pplayer->base.x, pplayer->base.y - 32);
368 tryemptybox(pplayer->base.x, pplayer->base.y - 32);
371 if (isbrick(pplayer->base.x+ 31, pplayer->base.y - 32) ||
372 isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
374 trygrabdistro(pplayer->base.x+ 31,
375 pplayer->base.y - 64,
377 trybumpbadguy(pplayer->base.x+ 31,
378 pplayer->base.y - 96);
380 if (isfullbox(pplayer->base.x+ 31, pplayer->base.y - 32))
382 bumpbrick(pplayer->base.x+ 31, pplayer->base.y - 32);
385 trybreakbrick(pplayer->base.x+ 31,
386 pplayer->base.y - 32);
387 tryemptybox(pplayer->base.x+ 31,
388 pplayer->base.y - 32);
393 if (isbrick(pplayer->base.x, pplayer->base.y) ||
394 isfullbox(pplayer->base.x, pplayer->base.y))
396 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
397 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
398 if (isfullbox(pplayer->base.x, pplayer->base.y))
399 bumpbrick(pplayer->base.x, pplayer->base.y);
400 trybreakbrick(pplayer->base.x, pplayer->base.y);
401 tryemptybox(pplayer->base.x, pplayer->base.y);
404 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
405 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
407 trygrabdistro(pplayer->base.x+ 31,
408 pplayer->base.y - 32,
410 trybumpbadguy(pplayer->base.x+ 31,
411 pplayer->base.y - 64);
412 if (isfullbox(pplayer->base.x+ 31, pplayer->base.y))
413 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
414 trybreakbrick(pplayer->base.x+ 31, pplayer->base.y);
415 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
421 /* It's a brick and we're small, make the brick
422 bounce, and grab any distros above it: * /
424 if (isbrick(pplayer->base.x, pplayer->base.y) ||
425 isfullbox(pplayer->base.x, pplayer->base.y))
427 trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE);
428 trybumpbadguy(pplayer->base.x, pplayer->base.y - 64);
429 bumpbrick(pplayer->base.x, pplayer->base.y);
430 tryemptybox(pplayer->base.x, pplayer->base.y);
433 if (isbrick(pplayer->base.x+ 31, pplayer->base.y) ||
434 isfullbox(pplayer->base.x+ 31, pplayer->base.y))
436 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE);
437 trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64);
438 bumpbrick(pplayer->base.x+ 31, pplayer->base.y);
439 tryemptybox(pplayer->base.x+ 31, pplayer->base.y);
443 /* Get a distro from a brick? * /
445 if (shape(pplayer->base.x, pplayer->base.y) == 'x' ||
446 shape(pplayer->base.x, pplayer->base.y) == 'y')
448 add_bouncy_distro(((pplayer->base.x+ 1)
450 (int)(pplayer->base.y / 32) * 32);
452 if (counting_distros == NO)
454 counting_distros = YES;
455 distro_counter = 100;
458 if (distro_counter <= 0)
459 level_change(¤t_level,pplayer->base.x,pplayer->base.y, 'a');
461 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
462 score = score + SCORE_DISTRO;
465 else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' ||
466 shape(pplayer->base.x+ 31, pplayer->base.y) == 'y')
468 add_bouncy_distro(((pplayer->base.x+ 1 + 31)
470 (int)(pplayer->base.y / 32) * 32);
472 if (counting_distros == NO)
474 counting_distros = YES;
475 distro_counter = 100;
478 if (distro_counter <= 0)
479 level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a');
481 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
482 score = score + SCORE_DISTRO;
490 pplayer->base.y = (int)(pplayer->base.y / 32) * 32 + 30;
496 pplayer->base.y = (int)(pplayer->base.y / 32) * 32 - 32;
499 pplayer->base.ym = 0;
500 pplayer->jumping = NO;
501 timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
508 player_grabdistros(pplayer);
511 /* Slow down horizontally: */
515 if (pplayer->input.right == UP && pplayer->input.left == UP)
517 if (isice(pplayer->base.x, pplayer->base.y + 32) ||
518 !issolid(pplayer->base.x, pplayer->base.y + 32))
520 /* Slowly on ice or in air: */
522 if (pplayer->base.xm > 0)
524 else if (pplayer->base.xm < 0)
529 /* Quickly, otherwise: */
531 pplayer->base.xm = pplayer->base.xm / 2;
536 /* Drop vertically: */
538 if (!issolid(pplayer->base.x, pplayer->base.y + 32))
540 pplayer->base.ym = pplayer->base.ym + GRAVITY;
542 if (pplayer->base.ym > MAX_YM)
543 pplayer->base.ym = MAX_YM;
549 timer_check(&pplayer->safe_timer);
552 /* ---- DONE HANDLING TUX! --- */
554 /* Handle invincibility timer: */
557 if (current_music == HERRING_MUSIC && !timer_check(&pplayer->invincible_timer))
560 no, we are no more invincible
561 or we were not in invincible mode
562 but are we in hurry ?
566 if (timer_get_left(&time_left) < TIME_WARNING)
568 /* yes, we are in hurry
569 stop the herring_song, prepare to play the correct
572 current_music = HURRYUP_MUSIC;
576 current_music = LEVEL_MUSIC;
579 /* stop the old music if it's being played */
584 /* Handle skidding: */
586 timer_check(&pplayer->skidding_timer);
590 if (pplayer->base.x - scroll_x >= endpos && endpos != 0)
597 void player_handle_horizontal_input(player_type *pplayer, int dir)
599 if (pplayer->jumping == NO)
601 if ((dir ? (pplayer->base.xm < -SKID_XM) : (pplayer->base.xm > SKID_XM)) && !timer_started(&pplayer->skidding_timer) &&
602 pplayer->dir == !dir)
604 timer_start(&pplayer->skidding_timer, SKID_TIME);
606 play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
612 if ((dir ? (pplayer->base.xm < 0) : (pplayer->base.xm > 0)) && !isice(pplayer->base.x, pplayer->base.y + 32) &&
613 !timer_started(&pplayer->skidding_timer))
615 pplayer->base.xm = 0;
620 if (pplayer->dir == dir)
622 /* Facing the direction we're jumping? Go full-speed: */
624 if (pplayer->input.fire == UP)
626 pplayer->base.xm = pplayer->base.xm + ( dir ? WALK_SPEED : -WALK_SPEED) * frame_ratio;
630 if (pplayer->base.xm > MAX_WALK_XM)
631 pplayer->base.xm = MAX_WALK_XM;
635 if (pplayer->base.xm < -MAX_WALK_XM)
636 pplayer->base.xm = -MAX_WALK_XM;
639 else if ( pplayer->input.fire == DOWN)
641 pplayer->base.xm = pplayer->base.xm + ( dir ? RUN_SPEED : -RUN_SPEED) * frame_ratio;
645 if (pplayer->base.xm > MAX_RUN_XM)
646 pplayer->base.xm = MAX_RUN_XM;
650 if (pplayer->base.xm < -MAX_RUN_XM)
651 pplayer->base.xm = -MAX_RUN_XM;
656 /* Not facing the direction we're jumping?
659 pplayer->base.xm = pplayer->base.xm + ( dir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio;
663 if (pplayer->base.xm > MAX_WALK_XM / 2)
664 pplayer->base.xm = MAX_WALK_XM / 2;
668 if (pplayer->base.xm < -MAX_WALK_XM / 2)
669 pplayer->base.xm = -MAX_WALK_XM / 2;
677 void player_handle_vertical_input(player_type *pplayer)
679 if(!timer_started(&pplayer->jump_timer))
681 timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
686 if (!issolid(pplayer->base.x, pplayer->base.y + 32) ||
687 pplayer->base.ym != 0)
689 /* If they're not on the ground, or are currently moving
690 vertically, don't jump! */
692 pplayer->jumping = NO;
693 timer_stop(&pplayer->jump_timer);
697 /* Make sure we're not standing back up into a solid! */
699 if (pplayer->size == SMALL || pplayer->duck == NO ||
700 !issolid(pplayer->base.x, pplayer->base.y))
702 pplayer->jumping = YES;
704 if (pplayer->size == SMALL)
705 play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
707 play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
712 /* Keep jumping for a while: */
714 if (timer_check(&pplayer->jump_timer))
716 pplayer->base.ym = pplayer->base.ym - JUMP_SPEED * frame_ratio;
717 if (pplayer->base.ym < -YM_FOR_JUMP)
718 pplayer->base.ym = -YM_FOR_JUMP;
722 void player_input(player_type *pplayer)
724 /* Handle key and joystick state: */
727 if (pplayer->input.right == DOWN && pplayer->input.left == UP)
729 player_handle_horizontal_input(pplayer,RIGHT);
731 else if (pplayer->input.left == DOWN && pplayer->input.right == UP)
733 player_handle_horizontal_input(pplayer,LEFT);
738 if ( pplayer->input.up == DOWN)
740 player_handle_vertical_input(pplayer);
743 timer_stop(&pplayer->jump_timer);
747 if (pplayer->input.fire == DOWN && pplayer->input.old_fire == UP && pplayer->got_coffee)
749 add_bullet(pplayer->base.x, pplayer->base.y, pplayer->base.xm, pplayer->dir);
755 if (pplayer->input.down == DOWN)
757 if (pplayer->size == BIG)
762 if (pplayer->size == BIG && pplayer->duck == YES)
764 /* Make sure we're not standing back up into a solid! */
766 if (!issolid(pplayer->base.x, pplayer->base.y - 32))
775 if (pplayer->input.right == UP && pplayer->input.left == UP)
777 pplayer->frame_main = 1;
782 if ((pplayer->input.fire == DOWN && (frame % 2) == 0) ||
784 pplayer->frame_main = (pplayer->frame_main + 1) % 4;
786 pplayer->frame = pplayer->frame_main;
788 if (pplayer->frame == 3)
794 void player_grabdistros(player_type *pplayer)
799 trygrabdistro(pplayer->base.x, pplayer->base.y, NO_BOUNCE);
800 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y, NO_BOUNCE);
802 if (pplayer->size == BIG && !pplayer->duck)
804 trygrabdistro(pplayer->base.x, pplayer->base.y - 32, NO_BOUNCE);
805 trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32, NO_BOUNCE);
810 /* Enough distros for a One-up? */
812 if (distros >= DISTROS_LIFEUP)
814 distros = distros - DISTROS_LIFEUP;
815 if(pplayer->lives < MAX_LIVES)
817 /*We want to hear the sound even, if MAX_LIVES is reached*/
818 play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
822 void player_draw(player_type* pplayer)
824 if (!timer_started(&pplayer->safe_timer) || (frame % 2) == 0)
826 if (pplayer->size == SMALL)
828 if (timer_started(&pplayer->invincible_timer))
832 if (pplayer->dir == RIGHT)
834 texture_draw(&cape_right[frame % 2],
835 pplayer->base.x- scroll_x, pplayer->base.y,
840 texture_draw(&cape_left[frame % 2],
841 pplayer->base.x- scroll_x, pplayer->base.y,
847 if (!pplayer->got_coffee)
849 if (pplayer->dir == RIGHT)
851 texture_draw(&tux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
855 texture_draw(&tux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
860 /* Tux got coffee! */
862 if (pplayer->dir == RIGHT)
864 texture_draw(&firetux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
868 texture_draw(&firetux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE);
874 if (timer_started(&pplayer->invincible_timer))
878 if (pplayer->dir == RIGHT)
880 texture_draw(&bigcape_right[frame % 2],
881 pplayer->base.x- scroll_x, pplayer->base.y,
886 texture_draw(&bigcape_left[frame % 2],
887 pplayer->base.x-scroll_x, pplayer->base.y,
892 if (!pplayer->got_coffee)
896 if (!timer_started(&pplayer->skidding_timer))
898 if (!pplayer->jumping || pplayer->base.ym > 0)
900 if (pplayer->dir == RIGHT)
902 texture_draw(&bigtux_right[pplayer->frame],
903 pplayer->base.x- scroll_x, pplayer->base.y,
908 texture_draw(&bigtux_left[pplayer->frame],
909 pplayer->base.x- scroll_x, pplayer->base.y,
915 if (pplayer->dir == RIGHT)
917 texture_draw(&bigtux_right_jump,
918 pplayer->base.x- scroll_x, pplayer->base.y,
923 texture_draw(&bigtux_left_jump,
924 pplayer->base.x- scroll_x, pplayer->base.y,
931 if (pplayer->dir == RIGHT)
933 texture_draw(&skidtux_right,
934 pplayer->base.x- scroll_x, pplayer->base.y,
939 texture_draw(&skidtux_left,
940 pplayer->base.x- scroll_x, pplayer->base.y,
947 if (pplayer->dir == RIGHT)
949 texture_draw(&ducktux_right, pplayer->base.x- scroll_x, pplayer->base.y,
954 texture_draw(&ducktux_left, pplayer->base.x- scroll_x, pplayer->base.y,
961 /* Tux has coffee! */
965 if (!timer_started(&pplayer->skidding_timer))
967 if (!pplayer->jumping || pplayer->base.ym > 0)
969 if (pplayer->dir == RIGHT)
971 texture_draw(&bigfiretux_right[pplayer->frame],
972 pplayer->base.x- scroll_x, pplayer->base.y,
977 texture_draw(&bigfiretux_left[pplayer->frame],
978 pplayer->base.x- scroll_x, pplayer->base.y,
984 if (pplayer->dir == RIGHT)
986 texture_draw(&bigfiretux_right_jump,
987 pplayer->base.x- scroll_x, pplayer->base.y,
992 texture_draw(&bigfiretux_left_jump,
993 pplayer->base.x- scroll_x, pplayer->base.y,
1000 if (pplayer->dir == RIGHT)
1002 texture_draw(&skidfiretux_right,
1003 pplayer->base.x- scroll_x, pplayer->base.y,
1008 texture_draw(&skidfiretux_left,
1009 pplayer->base.x- scroll_x, pplayer->base.y,
1016 if (pplayer->dir == RIGHT)
1018 texture_draw(&duckfiretux_right, pplayer->base.x- scroll_x, pplayer->base.y,
1023 texture_draw(&duckfiretux_left, pplayer->base.x- scroll_x, pplayer->base.y,
1032 void player_collision(player_type* pplayer, void* p_c_object, int c_object)
1034 bad_guy_type* pbad_c = NULL;
1039 pbad_c = (bad_guy_type*) p_c_object;
1040 /* Hurt the player if he just touched it: */
1042 if (!pbad_c->dying && !pplayer->dying &&
1043 !timer_started(&pplayer->safe_timer) &&
1044 pbad_c->mode != HELD)
1046 if (pbad_c->mode == FLAT && pplayer->input.fire != DOWN)
1050 pbad_c->mode = KICK;
1051 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1053 if (pplayer->base.x<= pbad_c->base.x)
1055 pbad_c->dir = RIGHT;
1056 pbad_c->base.x = pbad_c->base.x + 16;
1061 pbad_c->base.x = pbad_c->base.x - 16;
1064 timer_start(&pbad_c->timer,5000);
1066 else if (pbad_c->mode == FLAT && pplayer->input.fire == DOWN)
1068 pbad_c->mode = HELD;
1071 else if (pbad_c->mode == KICK)
1073 if (pplayer->base.y < pbad_c->base.y - 16 &&
1074 timer_started(&pbad_c->timer))
1076 /* Step on (stop being kicked) */
1078 pbad_c->mode = FLAT;
1079 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1080 timer_start(&pbad_c->timer, 10000);
1084 /* Hurt if you get hit by kicked laptop: */
1086 if (timer_started(&pbad_c->timer))
1088 if (!timer_started(&pplayer->invincible_timer))
1090 player_kill(pplayer,SHRINK);
1094 pbad_c->dying = FALLING;
1095 pbad_c->base.ym = -8;
1096 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1103 if (!timer_started(&pplayer->invincible_timer ))
1105 player_kill(pplayer,SHRINK);
1109 pbad_c->dying = FALLING;
1110 pbad_c->base.ym = -8;
1111 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1125 void player_kill(player_type* pplayer, int mode)
1127 pplayer->base.ym = -5;
1129 play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
1131 if (pplayer->dir == RIGHT)
1132 pplayer->base.xm = -8;
1133 else if (pplayer->dir == LEFT)
1134 pplayer->base.xm = 8;
1136 if (mode == SHRINK && pplayer->size == BIG)
1138 if (pplayer->got_coffee)
1139 pplayer->got_coffee = NO;
1141 pplayer->size = SMALL;
1142 pplayer->base.height = 32;
1144 timer_start(&pplayer->safe_timer,TUX_SAFE_TIME);
1152 void player_dying(player_type *pplayer)
1154 pplayer->base.ym = pplayer->base.ym + GRAVITY;
1159 player_remove_powerups(pplayer);
1160 pplayer->dying = NO;
1162 player_level_begin(pplayer);
1166 /* Remove Tux's power ups */
1167 void player_remove_powerups(player_type* pplayer)
1169 pplayer->got_coffee = NO;
1170 pplayer->size = SMALL;
1171 pplayer->base.height = 32;
1174 void player_keep_in_bounds(player_type* pplayer)
1176 /* Keep tux in bounds: */
1177 if (pplayer->base.x< 0)
1179 else if(pplayer->base.x< scroll_x)
1180 pplayer->base.x= scroll_x;
1181 else if (pplayer->base.x< 160 + scroll_x && scroll_x > 0 && debug_mode == YES)
1183 scroll_x = pplayer->base.x- 160;
1184 /*pplayer->base.x+= 160;*/
1190 else if (pplayer->base.x> screen->w / 2 + scroll_x && scroll_x < ((current_level.width * 32) - screen->w))
1192 /* Scroll the screen in past center: */
1194 scroll_x = pplayer->base.x- screen->w / 2;
1195 /*pplayer->base.x= 320 + scroll_x;*/
1197 if (scroll_x > ((current_level.width * 32) - screen->w))
1198 scroll_x = ((current_level.width * 32) - screen->w);
1200 else if (pplayer->base.x> 608 + scroll_x)
1202 /* ... unless there's no more to scroll! */
1204 /*pplayer->base.x= 608 + scroll_x;*/
1207 /* Keep in-bounds, vertically: */
1209 if (pplayer->base.y < 0)
1210 pplayer->base.y = 0;
1211 else if (pplayer->base.y > screen->h)
1213 player_kill(&tux,KILL);