Huge code merge. This reflects the current status of my rewrite/restructuring. A...
[supertux.git] / src / player.c
1 //
2 // C Implementation: player/tux
3 //
4 // Description:
5 //
6 //
7 // Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12
13 #include "gameloop.h"
14 #include "globals.h"
15 #include "player.h"
16 #include "defines.h"
17 #include "scene.h"
18 #include "screen.h"
19
20 void player_init(player_type* pplayer)
21 {
22   pplayer->it.alive = NULL;
23   pplayer->it.x = &pplayer->x;
24   pplayer->it.y = &pplayer->y;
25   pplayer->it.width = &pplayer->width;
26   pplayer->it.height = &pplayer->height;
27   pplayer->it.updated = &pplayer->updated;
28
29   pplayer->width = 32;
30   pplayer->height = 32;
31
32   pplayer->updated = SDL_GetTicks();
33   pplayer->size = SMALL;
34   pplayer->got_coffee = NO;
35
36   pplayer->x = 0;
37   pplayer->xm = 0;
38   pplayer->y = 240;
39   pplayer->ym = 0;
40   pplayer->dir = RIGHT;
41   pplayer->duck = NO;
42
43   pplayer->dying = NO;
44   pplayer->safe = TUX_SAFE_TIME;
45
46   pplayer->jumping = NO;
47   pplayer->skidding = 0;
48
49   pplayer->frame_main = 0;
50   pplayer->frame = 0;
51   pplayer->lives = 3;
52
53   pplayer->input.down = UP;
54   pplayer->input.fire = UP;
55   pplayer->input.left = UP;
56   pplayer->input.old_fire = UP;
57   pplayer->input.right = UP;
58   pplayer->input.up = UP;
59
60   timer_init(&pplayer->invincible_timer);
61 }
62
63 void player_level_begin(player_type* pplayer)
64 {
65   pplayer->x = 0;
66   pplayer->xm = 0;
67   pplayer->y = 240;
68   pplayer->ym = 0;
69 }
70
71 void player_action(player_type* pplayer)
72 {
73
74   double frame_ratio = get_frame_ratio(&pplayer->it);
75
76   /* --- HANDLE TUX! --- */
77
78   player_input(pplayer);
79
80   /* Move tux: */
81
82   pplayer->x = pplayer->x + pplayer->xm * frame_ratio;
83   pplayer->y = pplayer->y + pplayer->ym * frame_ratio;
84
85   player_keep_in_bounds(pplayer);
86
87   /* Land: */
88
89   if (!pplayer->dying)
90     {
91       if (issolid(pplayer->x, pplayer->y + 31) &&
92           !issolid(pplayer->x - pplayer->xm, pplayer->y + 31))
93         {
94           while (issolid(pplayer->x, pplayer->y + 31))
95             {
96               if (pplayer->xm < 0)
97                 pplayer->x++;
98               else if (pplayer->xm > 0)
99                 pplayer->x--;
100             }
101
102           pplayer->xm = 0;
103         }
104
105       if (issolid(pplayer->x, pplayer->y) &&
106           !issolid(pplayer->x - pplayer->xm, pplayer->y))
107         {
108           while (issolid(pplayer->x, (pplayer->y)))
109             {
110               if (pplayer->xm < 0)
111                 pplayer->x++;
112               else if (pplayer->xm > 0)
113                 pplayer->x--;
114             }
115
116           pplayer->xm = 0;
117         }
118
119       if (issolid(pplayer->x, pplayer->y + 31))
120         {
121           /* Set down properly: */
122
123           int debug_int = 0;
124           while (issolid(pplayer->x, pplayer->y + 31))
125             {
126               ++debug_int;
127               if(debug_int > 32)
128                 DEBUG_MSG("FIXME - UNDER certain circumstances I'm hanging in a loop here!");
129                 
130               if (pplayer->ym < 0)
131                 pplayer->y++;
132               else if (pplayer->ym > 0)
133                 pplayer->y--;
134             }
135
136
137           /* Reset score multiplier (for multi-hits): */
138
139           if (pplayer->ym > 0)
140             score_multiplier = 1;
141
142
143           /* Stop jumping! */
144
145           pplayer->ym = 0;
146           pplayer->jumping = NO;
147         }
148
149
150       /* Bump into things: */
151
152       if (issolid(pplayer->x, pplayer->y) ||
153           (pplayer->size == BIG && !pplayer->duck &&
154            (issolid(pplayer->x, pplayer->y - 32))))
155         {
156           if (!issolid(pplayer->x - pplayer->xm, pplayer->y) &&
157               (pplayer->size == SMALL || pplayer->duck ||
158                !issolid(pplayer->x - pplayer->xm, pplayer->y - 32)))
159             {
160               pplayer->x = pplayer->x - pplayer->xm;
161               pplayer->xm = 0;
162             }
163           else if (!issolid(pplayer->x, pplayer->y - pplayer->ym) &&
164                    (pplayer->size == SMALL || pplayer->duck ||
165                     !issolid(pplayer->x, pplayer->y - 32 - pplayer->ym)))
166             {
167               if (pplayer->ym <= 0)
168                 {
169                   /* Jumping up? */
170
171                   if (pplayer->size == BIG)
172                     {
173                       /* Break bricks and empty boxes: */
174
175                       if (!pplayer->duck)
176                         {
177                           if (isbrick(pplayer->x, pplayer->y - 32) ||
178                               isfullbox(pplayer->x, pplayer->y - 32))
179                             {
180                               trygrabdistro(pplayer->x, pplayer->y - 64, BOUNCE);
181                               trybumpbadguy(pplayer->x, pplayer->y - 96);
182
183                               if (isfullbox(pplayer->x, pplayer->y - 32))
184                                 {
185                                   bumpbrick(pplayer->x, pplayer->y - 32);
186                                 }
187
188                               trybreakbrick(pplayer->x, pplayer->y - 32);
189                               tryemptybox(pplayer->x, pplayer->y - 32);
190                             }
191
192                           if (isbrick(pplayer->x + 31, pplayer->y - 32) ||
193                               isfullbox(pplayer->x + 31, pplayer->y - 32))
194                             {
195                               trygrabdistro(pplayer->x + 31,
196                                             pplayer->y - 64,
197                                             BOUNCE);
198                               trybumpbadguy(pplayer->x + 31,
199                                             pplayer->y - 96);
200
201                               if (isfullbox(pplayer->x + 31, pplayer->y - 32))
202                                 {
203                                   bumpbrick(pplayer->x + 31, pplayer->y - 32);
204                                 }
205
206                               trybreakbrick(pplayer->x + 31,
207                                             pplayer->y - 32);
208                               tryemptybox(pplayer->x + 31,
209                                           pplayer->y - 32);
210                             }
211                         }
212                       else /* ducking */
213                         {
214                           if (isbrick(pplayer->x, pplayer->y) ||
215                               isfullbox(pplayer->x, pplayer->y))
216                             {
217                               trygrabdistro(pplayer->x, pplayer->y - 32,BOUNCE);
218                               trybumpbadguy(pplayer->x, pplayer->y - 64);
219                               if (isfullbox(pplayer->x, pplayer->y))
220                                 bumpbrick(pplayer->x, pplayer->y);
221                               trybreakbrick(pplayer->x, pplayer->y);
222                               tryemptybox(pplayer->x, pplayer->y);
223                             }
224
225                           if (isbrick(pplayer->x + 31, pplayer->y) ||
226                               isfullbox(pplayer->x + 31, pplayer->y))
227                             {
228                               trygrabdistro(pplayer->x + 31,
229                                             pplayer->y - 32,
230                                             BOUNCE);
231                               trybumpbadguy(pplayer->x + 31,
232                                             pplayer->y - 64);
233                               if (isfullbox(pplayer->x + 31, pplayer->y))
234                                 bumpbrick(pplayer->x + 31, pplayer->y);
235                               trybreakbrick(pplayer->x + 31, pplayer->y);
236                               tryemptybox(pplayer->x + 31, pplayer->y);
237                             }
238                         }
239                     }
240                   else
241                     {
242                       /* It's a brick and we're small, make the brick
243                          bounce, and grab any distros above it: */
244
245                       if (isbrick(pplayer->x, pplayer->y) ||
246                           isfullbox(pplayer->x, pplayer->y))
247                         {
248                           trygrabdistro(pplayer->x, pplayer->y - 32,BOUNCE);
249                           trybumpbadguy(pplayer->x, pplayer->y - 64);
250                           bumpbrick(pplayer->x, pplayer->y);
251                           tryemptybox(pplayer->x, pplayer->y);
252                         }
253
254                       if (isbrick(pplayer->x + 31, pplayer->y) ||
255                           isfullbox(pplayer->x + 31, pplayer->y))
256                         {
257                           trygrabdistro(pplayer->x + 31, pplayer->y - 32,BOUNCE);
258                           trybumpbadguy(pplayer->x + 31, pplayer->y - 64);
259                           bumpbrick(pplayer->x + 31, pplayer->y);
260                           tryemptybox(pplayer->x + 31, pplayer->y);
261                         }
262
263
264                       /* Get a distro from a brick? */
265
266                       if (shape(pplayer->x, pplayer->y) == 'x' ||
267                           shape(pplayer->x, pplayer->y) == 'y')
268                         {
269                           add_bouncy_distro(((pplayer->x + 1)
270                                              / 32) * 32,
271                                             (int)(pplayer->y / 32) * 32);
272
273                           if (counting_distros == NO)
274                             {
275                               counting_distros = YES;
276                               distro_counter = 100;
277                             }
278
279                           if (distro_counter <= 0)
280                             level_change(&current_level,pplayer->x, pplayer->y, 'a');
281
282                           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
283                           score = score + SCORE_DISTRO;
284                           distros++;
285                         }
286                       else if (shape(pplayer->x + 31, pplayer->y) == 'x' ||
287                                shape(pplayer->x + 31, pplayer->y) == 'y')
288                         {
289                           add_bouncy_distro(((pplayer->x + 1 + 31)
290                                              / 32) * 32,
291                                             (int)(pplayer->y / 32) * 32);
292
293                           if (counting_distros == NO)
294                             {
295                               counting_distros = YES;
296                               distro_counter = 100;
297                             }
298
299                           if (distro_counter <= 0)
300                             level_change(&current_level,pplayer->x + 31 + scroll_x, pplayer->y, 'a');
301
302                           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
303                           score = score + SCORE_DISTRO;
304                           distros++;
305                         }
306                     }
307
308
309                   /* Bump head: */
310
311                   pplayer->y = (int)(pplayer->y / 32) * 32 + 30;
312                 }
313               else
314                 {
315                   /* Land on feet: */
316
317                   pplayer->y = (int)(pplayer->y / 32) * 32 - 32;
318                 }
319
320               pplayer->ym = 0;
321               pplayer->jumping = NO;
322               /*pplayer->jump_counter = MAX_JUMP_COUNT;*/
323               /*timer_init(&pplayer->jump_timer);*/
324               timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
325             }
326         }
327     }
328
329
330
331   player_grabdistros(pplayer);
332
333
334   /* Slow down horizontally: */
335
336   if (!pplayer->dying)
337     {
338       if (pplayer->input.right == UP && pplayer->input.left == UP)
339         {
340           if (isice(pplayer->x, pplayer->y + 32) ||
341               !issolid(pplayer->x, pplayer->y + 32))
342             {
343               /* Slowly on ice or in air: */
344
345               if (pplayer->xm > 0)
346                 pplayer->xm--;
347               else if (pplayer->xm < 0)
348                 pplayer->xm++;
349             }
350           else
351             {
352               /* Quickly, otherwise: */
353
354               pplayer->xm = pplayer->xm / 2;
355             }
356         }
357
358
359       /* Drop vertically: */
360
361       if (!issolid(pplayer->x, pplayer->y + 32))
362         {
363           pplayer->ym = pplayer->ym + GRAVITY;
364
365           if (pplayer->ym > MAX_YM)
366             pplayer->ym = MAX_YM;
367         }
368     }
369
370
371
372   if (pplayer->safe > 0)
373     pplayer->safe--;
374
375   /* ---- DONE HANDLING TUX! --- */
376
377   /* Handle invincibility timer: */
378
379
380   if (timer_check(&pplayer->invincible_timer))
381     {
382       if (current_music == HERRING_MUSIC)
383         {
384           if (current_level.time_left <= TIME_WARNING)
385             {
386               /* stop the herring_song, prepare to play the correct
387                * fast level_song !
388                */
389               current_music = HURRYUP_MUSIC;
390             }
391           else
392             {
393               current_music = LEVEL_MUSIC;
394             }
395           /* stop the old music if it's being played */
396           if (playing_music())
397             halt_music();
398         }
399     }
400
401   /* Handle skidding: */
402
403   if (pplayer->skidding > 0)
404     {
405       pplayer->skidding--;
406     }
407
408   /* End of level? */
409
410   if (pplayer->x >= endpos && endpos != 0)
411     {
412       next_level = 1;
413     }
414
415 }
416
417 void player_input(player_type *pplayer)
418 {
419   /* Handle key and joystick state: */
420
421
422   if (pplayer->input.right == DOWN && pplayer->input.left == UP)
423     {
424       if (pplayer->jumping == NO)
425         {
426           if (pplayer->xm < -SKID_XM && !pplayer->skidding &&
427               pplayer->dir == LEFT)
428             {
429               pplayer->skidding = SKID_TIME;
430
431               play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
432
433             }
434           pplayer->dir = RIGHT;
435         }
436
437       if (pplayer->xm < 0 && !isice(pplayer->x, pplayer->y + 32) &&
438           !pplayer->skidding)
439         {
440           pplayer->xm = 0;
441         }
442
443       if (!pplayer->duck)
444         {
445           if (pplayer->dir == RIGHT)
446             {
447               /* Facing the direction we're jumping?  Go full-speed: */
448
449               if (pplayer->input.fire == UP)
450                 {
451                   pplayer->xm = pplayer->xm + WALK_SPEED;
452
453                   if (pplayer->xm > MAX_WALK_XM)
454                     pplayer->xm = MAX_WALK_XM;
455                 }
456               else if ( pplayer->input.fire == DOWN)
457                 {
458                   pplayer->xm = pplayer->xm + RUN_SPEED;
459
460                   if (pplayer->xm > MAX_RUN_XM)
461                     pplayer->xm = MAX_RUN_XM;
462                 }
463             }
464           else
465             {
466               /* Not facing the direction we're jumping?
467               Go half-speed: */
468
469               pplayer->xm = pplayer->xm + WALK_SPEED / 2;
470
471               if (pplayer->xm > MAX_WALK_XM / 2)
472                 pplayer->xm = MAX_WALK_XM / 2;
473             }
474         }
475     }
476   else if (pplayer->input.left == DOWN && pplayer->input.right == UP)
477     {
478       if (pplayer->jumping == NO)
479         {
480           if (pplayer->xm > SKID_XM && !pplayer->skidding &&
481               pplayer->dir == RIGHT)
482             {
483               pplayer->skidding = SKID_TIME;
484               play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
485             }
486           pplayer->dir = LEFT;
487         }
488
489       if (pplayer->xm > 0 && !isice(pplayer->x, pplayer->y + 32) &&
490           !pplayer->skidding)
491         {
492           pplayer->xm = 0;
493         }
494
495       if (!pplayer->duck)
496         {
497           if (pplayer->dir == LEFT)
498             {
499               /* Facing the direction we're jumping?  Go full-speed: */
500
501               if (pplayer->input.fire == UP)
502                 {
503                   pplayer->xm = pplayer->xm - WALK_SPEED;
504
505                   if (pplayer->xm < -MAX_WALK_XM)
506                     pplayer->xm = -MAX_WALK_XM;
507                 }
508               else if (pplayer->input.fire == DOWN)
509                 {
510                   pplayer->xm = pplayer->xm - RUN_SPEED;
511
512                   if (pplayer->xm < -MAX_RUN_XM)
513                     pplayer->xm = -MAX_RUN_XM;
514                 }
515             }
516           else
517             {
518               /* Not facing the direction we're jumping?
519               Go half-speed: */
520
521               pplayer->xm = pplayer->xm - WALK_SPEED / 2;
522
523               if (pplayer->xm < -MAX_WALK_XM / 2)
524                 pplayer->xm = -MAX_WALK_XM / 2;
525             }
526         }
527     }
528
529   /* Jump/jumping? */
530
531   if ( pplayer->input.up == DOWN)
532     {
533       if(!timer_started(&pplayer->jump_timer))
534         {
535           timer_start(&pplayer->jump_timer,MAX_JUMP_TIME);
536
537
538           /* Taking off? */
539
540           if (!issolid(pplayer->x, pplayer->y + 32) ||
541               pplayer->ym != 0)
542             {
543               /* If they're not on the ground, or are currently moving
544               vertically, don't jump! */
545
546               pplayer->jumping = NO;
547               timer_stop(&pplayer->jump_timer);
548             }
549           else
550             {
551               /* Make sure we're not standing back up into a solid! */
552
553               if (pplayer->size == SMALL || pplayer->duck == NO ||
554                   !issolid(pplayer->x, pplayer->y))
555                 {
556                   pplayer->jumping = YES;
557
558                   if (pplayer->size == SMALL)
559                     play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
560                   else
561                     play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
562                 }
563             }
564         }
565
566       /* Keep jumping for a while: */
567
568       if (timer_check(&pplayer->jump_timer))
569         {
570           pplayer->ym = pplayer->ym - JUMP_SPEED;
571         }
572     }
573   else
574     timer_stop(&pplayer->jump_timer);
575
576
577   /* Shoot! */
578
579   if (pplayer->input.fire == DOWN && pplayer->input.old_fire == UP && pplayer->got_coffee)
580     {
581       add_bullet(pplayer->x, pplayer->y, pplayer->xm, pplayer->dir);
582     }
583
584
585   /* Duck! */
586
587   if (pplayer->input.down == DOWN)
588     {
589       if (pplayer->size == BIG)
590         pplayer->duck = YES;
591     }
592   else
593     {
594       if (pplayer->size == BIG && pplayer->duck == YES)
595         {
596           /* Make sure we're not standing back up into a solid! */
597
598           if (!issolid(pplayer->x, pplayer->y - 32))
599             pplayer->duck = NO;
600         }
601       else
602         pplayer->duck = NO;
603     }
604
605   /* (Tux): */
606
607   if (pplayer->input.right == UP && pplayer->input.left == UP)
608     {
609       pplayer->frame_main = 1;
610       pplayer->frame = 1;
611     }
612   else
613     {
614       if ((pplayer->input.fire == DOWN && (frame % 2) == 0) ||
615           (frame % 4) == 0)
616         pplayer->frame_main = (pplayer->frame_main + 1) % 4;
617
618       pplayer->frame = pplayer->frame_main;
619
620       if (pplayer->frame == 3)
621         pplayer->frame = 1;
622     }
623
624 }
625
626 void player_grabdistros(player_type *pplayer)
627 {
628   /* Grab distros: */
629   if (!pplayer->dying)
630     {
631       trygrabdistro(pplayer->x , pplayer->y, NO_BOUNCE);
632       trygrabdistro(pplayer->x + 31, pplayer->y, NO_BOUNCE);
633
634       if (pplayer->size == BIG && !pplayer->duck)
635         {
636           trygrabdistro(pplayer->x, pplayer->y - 32, NO_BOUNCE);
637           trygrabdistro(pplayer->x + 31, pplayer->y - 32, NO_BOUNCE);
638         }
639     }
640
641
642   /* Enough distros for a One-up? */
643
644   if (distros >= DISTROS_LIFEUP)
645     {
646       distros = distros - DISTROS_LIFEUP;
647       if(pplayer->lives < MAX_LIVES)
648         pplayer->lives++;
649       /*We want to hear the sound even, if MAX_LIVES is reached*/
650       play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
651     }
652 }
653
654 void player_draw(player_type* pplayer)
655 {
656
657   if (pplayer->safe == 0 || (frame % 2) == 0)
658     {
659       if (pplayer->size == SMALL)
660         {
661           if (timer_started(&pplayer->invincible_timer))
662             {
663               /* Draw cape: */
664
665               if (pplayer->dir == RIGHT)
666                 {
667                   texture_draw(&cape_right[frame % 2],
668                                pplayer->x - scroll_x, pplayer->y,
669                                NO_UPDATE);
670                 }
671               else
672                 {
673                   texture_draw(&cape_left[frame % 2],
674                                pplayer->x - scroll_x, pplayer->y,
675                                NO_UPDATE);
676                 }
677             }
678
679
680           if (!pplayer->got_coffee)
681             {
682               if (pplayer->dir == RIGHT)
683                 {
684                   texture_draw(&tux_right[pplayer->frame], pplayer->x - scroll_x, pplayer->y, NO_UPDATE);
685                 }
686               else
687                 {
688                   texture_draw(&tux_left[pplayer->frame], pplayer->x - scroll_x, pplayer->y, NO_UPDATE);
689                 }
690             }
691           else
692             {
693               /* Tux got coffee! */
694
695               if (pplayer->dir == RIGHT)
696                 {
697                   texture_draw(&firetux_right[pplayer->frame], pplayer->x - scroll_x, pplayer->y, NO_UPDATE);
698                 }
699               else
700                 {
701                   texture_draw(&firetux_left[pplayer->frame], pplayer->x - scroll_x, pplayer->y, NO_UPDATE);
702                 }
703             }
704         }
705       else
706         {
707           if (timer_started(&pplayer->invincible_timer))
708             {
709               /* Draw cape: */
710
711               if (pplayer->dir == RIGHT)
712                 {
713                   texture_draw(&bigcape_right[frame % 2],
714                                pplayer->x - scroll_x - 8 - 16, pplayer->y - 32,
715                                NO_UPDATE);
716                 }
717               else
718                 {
719                   texture_draw(&bigcape_left[frame % 2],
720                                pplayer->x -scroll_x - 8, pplayer->y - 32,
721                                NO_UPDATE);
722                 }
723             }
724
725           if (!pplayer->got_coffee)
726             {
727               if (!pplayer->duck)
728                 {
729                   if (!pplayer->skidding)
730                     {
731                       if (!pplayer->jumping || pplayer->ym > 0)
732                         {
733                           if (pplayer->dir == RIGHT)
734                             {
735                               texture_draw(&bigtux_right[pplayer->frame],
736                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
737                                            NO_UPDATE);
738                             }
739                           else
740                             {
741                               texture_draw(&bigtux_left[pplayer->frame],
742                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
743                                            NO_UPDATE);
744                             }
745                         }
746                       else
747                         {
748                           if (pplayer->dir == RIGHT)
749                             {
750                               texture_draw(&bigtux_right_jump,
751                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
752                                            NO_UPDATE);
753                             }
754                           else
755                             {
756                               texture_draw(&bigtux_left_jump,
757                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
758                                            NO_UPDATE);
759                             }
760                         }
761                     }
762                   else
763                     {
764                       if (pplayer->dir == RIGHT)
765                         {
766                           texture_draw(&skidtux_right,
767                                        pplayer->x - scroll_x - 8, pplayer->y - 32,
768                                        NO_UPDATE);
769                         }
770                       else
771                         {
772                           texture_draw(&skidtux_left,
773                                        pplayer->x - scroll_x - 8, pplayer->y - 32,
774                                        NO_UPDATE);
775                         }
776                     }
777                 }
778               else
779                 {
780                   if (pplayer->dir == RIGHT)
781                     {
782                       texture_draw(&ducktux_right, pplayer->x - scroll_x - 8, pplayer->y - 16,
783                                    NO_UPDATE);
784                     }
785                   else
786                     {
787                       texture_draw(&ducktux_left, pplayer->x - scroll_x - 8, pplayer->y - 16,
788                                    NO_UPDATE);
789                     }
790                 }
791             }
792           else
793             {
794               /* Tux has coffee! */
795
796               if (!pplayer->duck)
797                 {
798                   if (!pplayer->skidding)
799                     {
800                       if (!pplayer->jumping || pplayer->ym > 0)
801                         {
802                           if (pplayer->dir == RIGHT)
803                             {
804                               texture_draw(&bigfiretux_right[pplayer->frame],
805                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
806                                            NO_UPDATE);
807                             }
808                           else
809                             {
810                               texture_draw(&bigfiretux_left[pplayer->frame],
811                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
812                                            NO_UPDATE);
813                             }
814                         }
815                       else
816                         {
817                           if (pplayer->dir == RIGHT)
818                             {
819                               texture_draw(&bigfiretux_right_jump,
820                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
821                                            NO_UPDATE);
822                             }
823                           else
824                             {
825                               texture_draw(&bigfiretux_left_jump,
826                                            pplayer->x - scroll_x - 8, pplayer->y - 32,
827                                            NO_UPDATE);
828                             }
829                         }
830                     }
831                   else
832                     {
833                       if (pplayer->dir == RIGHT)
834                         {
835                           texture_draw(&skidfiretux_right,
836                                        pplayer->x - scroll_x - 8, pplayer->y - 32,
837                                        NO_UPDATE);
838                         }
839                       else
840                         {
841                           texture_draw(&skidfiretux_left,
842                                        pplayer->x - scroll_x - 8, pplayer->y - 32,
843                                        NO_UPDATE);
844                         }
845                     }
846                 }
847               else
848                 {
849                   if (pplayer->dir == RIGHT)
850                     {
851                       texture_draw(&duckfiretux_right, pplayer->x - scroll_x - 8, pplayer->y - 16,
852                                    NO_UPDATE);
853                     }
854                   else
855                     {
856                       texture_draw(&duckfiretux_left, pplayer->x - scroll_x - 8, pplayer->y - 16,
857                                    NO_UPDATE);
858                     }
859                 }
860             }
861         }
862     }
863
864 }
865
866 void player_collision(player_type* pplayer, void* p_c_object, int c_object)
867 {
868   bad_guy_type* pbad_c = NULL;
869
870   switch (c_object)
871     {
872     case CO_BADGUY:
873       pbad_c = p_c_object;
874       /* Hurt the player if he just touched it: */
875
876       if (!pbad_c->dying && !pplayer->dying &&
877           !pplayer->safe &&
878           pbad_c->mode != HELD)
879         {
880           if (pbad_c->mode == FLAT  && pplayer->input.fire != DOWN)
881             {
882               /* Kick: */
883
884               pbad_c->mode = KICK;
885               play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
886
887               if (pplayer->x <= pbad_c->x)
888                 {
889                   pbad_c->dir = RIGHT;
890                   pbad_c->x = pbad_c->x + 16;
891                 }
892               else
893                 {
894                   pbad_c->dir = LEFT;
895                   pbad_c->x = pbad_c->x - 16;
896                 }
897
898               timer_start(&pbad_c->timer,5000);
899             }
900           else if (pbad_c->mode == FLAT && pplayer->input.fire == DOWN)
901             {
902               pbad_c->mode = HELD;
903               pbad_c->y-=8;
904             }
905           else if (pbad_c->mode == KICK)
906             {
907               if (pplayer->y < pbad_c->y - 16 &&
908                   timer_started(&pbad_c->timer))
909                 {
910                   /* Step on (stop being kicked) */
911
912                   pbad_c->mode = FLAT;
913                   play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
914                   timer_start(&pbad_c->timer, 10000);
915                 }
916               else
917                 {
918                   /* Hurt if you get hit by kicked laptop: */
919
920                   if (timer_started(&pbad_c->timer))
921                     {
922                       if (!timer_started(&pplayer->invincible_timer))
923                         {
924                           player_kill(pplayer,SHRINK);
925                         }
926                       else
927                         {
928                           pbad_c->dying = FALLING;
929                           pbad_c->ym = -8;
930                           play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
931                         }
932                     }
933                 }
934             }
935           else
936             {
937               if (!timer_started(&pplayer->invincible_timer ))
938                 {
939                   player_kill(pplayer,SHRINK);
940                 }
941               else
942                 {
943                   pbad_c->dying = FALLING;
944                   pbad_c->ym = -8;
945                   play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
946                 }
947             }
948         }
949       score_multiplier++;
950       break;
951     }
952
953 }
954
955 /* Kill Player! */
956
957 void player_kill(player_type* pplayer, int mode)
958 {
959   pplayer->ym = -5;
960
961   play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
962
963   if (pplayer->dir == RIGHT)
964     pplayer->xm = -8;
965   else if (tux.dir == LEFT)
966     pplayer->xm = 8;
967
968   if (mode == SHRINK && pplayer->size == BIG)
969     {
970       if (pplayer->got_coffee)
971         pplayer->got_coffee = NO;
972
973       pplayer->size = SMALL;
974
975       pplayer->safe = TUX_SAFE_TIME;
976     }
977   else
978     {
979       pplayer->dying = 1;
980     }
981 }
982
983 void player_dying(player_type *pplayer)
984 {
985   pplayer->ym = pplayer->ym + GRAVITY;
986
987   /* He died :^( */
988
989   --pplayer->lives;
990   player_remove_powerups(pplayer);
991   pplayer->dying = 0;
992
993 }
994
995 /* Remove Tux's power ups */
996 void player_remove_powerups(player_type* pplayer)
997 {
998   pplayer->got_coffee = NO;
999   pplayer->size = SMALL;
1000 }
1001
1002 void player_keep_in_bounds(player_type* pplayer)
1003 {
1004   /* Keep tux in bounds: */
1005   if (pplayer->x < 0)
1006     pplayer->x = 0;
1007   else if(pplayer->x < scroll_x)
1008     pplayer->x = scroll_x;
1009   else if (pplayer->x < 160 + scroll_x && scroll_x > 0 && debug_mode == YES)
1010     {
1011       scroll_x = pplayer->x - 160;
1012       /*pplayer->x += 160;*/
1013
1014       if(scroll_x < 0)
1015         scroll_x = 0;
1016
1017     }
1018   else if (pplayer->x > screen->w / 2 + scroll_x && scroll_x < ((current_level.width * 32) - screen->w))
1019     {
1020       /* Scroll the screen in past center: */
1021
1022       scroll_x = pplayer->x - screen->w / 2;
1023       /*pplayer->x = 320 + scroll_x;*/
1024
1025       if (scroll_x > ((current_level.width * 32) - screen->w))
1026         scroll_x = ((current_level.width * 32) - screen->w);
1027     }
1028   else if (pplayer->x > 608 + scroll_x)
1029     {
1030       /* ... unless there's no more to scroll! */
1031
1032       /*pplayer->x = 608 + scroll_x;*/
1033     }
1034
1035   /* Keep in-bounds, vertically: */
1036
1037   if (pplayer->y < 0)
1038     pplayer->y = 0;
1039   else if (pplayer->y > screen->h)
1040     {
1041       player_kill(&tux,KILL);
1042     }
1043 }