- moved some global variables into a seperate class
[supertux.git] / src / player.cpp
1 //
2 // C Implementation: player/tux
3 //
4 // Description:
5 //
6 //
7 // Author: Tobias Glaesser <tobi.web@gmx.de> & Bill Kendrick, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12 #include <math.h>
13
14 #include "gameloop.h"
15 #include "globals.h"
16 #include "player.h"
17 #include "defines.h"
18 #include "scene.h"
19 #include "tile.h"
20 #include "screen.h"
21
22 texture_type tux_life;
23 std::vector<texture_type> tux_right;
24 std::vector<texture_type> tux_left;
25 texture_type smalltux_jump_left;
26 texture_type smalltux_jump_right;
27 texture_type smalltux_stand_left;
28 texture_type smalltux_stand_right;
29
30 texture_type bigtux_right[3];
31 texture_type bigtux_left[3];
32 texture_type bigtux_right_jump;
33 texture_type bigtux_left_jump;
34 texture_type ducktux_right;
35 texture_type ducktux_left;
36 texture_type skidtux_right;
37 texture_type skidtux_left;
38 texture_type firetux_right[3];
39 texture_type firetux_left[3];
40 texture_type bigfiretux_right[3];
41 texture_type bigfiretux_left[3];
42 texture_type bigfiretux_right_jump;
43 texture_type bigfiretux_left_jump;
44 texture_type duckfiretux_right;
45 texture_type duckfiretux_left;
46 texture_type skidfiretux_right;
47 texture_type skidfiretux_left;
48 texture_type cape_right[2];
49 texture_type cape_left[2];
50 texture_type bigcape_right[2];
51 texture_type bigcape_left[2];
52
53 void player_input_init(player_input_type* pplayer_input)
54 {
55   pplayer_input->down = UP;
56   pplayer_input->fire = UP;
57   pplayer_input->left = UP;
58   pplayer_input->old_fire = UP;
59   pplayer_input->right = UP;
60   pplayer_input->up = UP;
61 }
62
63 void
64 Player::init()
65 {
66   base.width = 32;
67   base.height = 32;
68
69   size = SMALL;
70   got_coffee = false;
71
72   // FIXME: Make the start position configurable via the levelfile
73   base.x = 100;
74   base.y = 240;
75   base.xm = 0;
76   base.ym = 0;
77   old_base = base;
78   dir = RIGHT;
79   duck = false;
80
81   dying   = DYING_NOT;
82   jumping = false;
83
84   frame_main = 0;
85   frame_ = 0;
86   lives = 3;
87   score = 0;
88   distros = 0;
89
90   player_input_init(&input);
91
92   keymap.jump  = SDLK_UP;
93   keymap.duck  = SDLK_DOWN;
94   keymap.left  = SDLK_LEFT;
95   keymap.right = SDLK_RIGHT;
96   keymap.fire  = SDLK_LCTRL;
97
98   timer_init(&invincible_timer,true);
99   timer_init(&skidding_timer,true);
100   timer_init(&safe_timer,true);
101   timer_init(&frame_timer,true);
102
103   physic.reset();
104 }
105
106 int
107 Player::key_event(SDLKey key, int state)
108 {
109   if(key == keymap.right)
110     {
111       input.right = state;
112       return true;
113     }
114   else if(key == keymap.left)
115     {
116       input.left = state;
117       return true;
118     }
119   else if(key == keymap.jump)
120     {
121       input.up = state;
122       return true;
123     }
124   else if(key == keymap.duck)
125     {
126       input.down = state;
127       return true;
128     }
129   else if(key == keymap.fire)
130     {
131       input.fire = state;
132       return true;
133     }
134   else
135     return false;
136 }
137
138 void
139 Player::level_begin()
140 {
141   base.x  = 100;
142   base.y  = 240;
143   base.xm = 0;
144   base.ym = 0;
145   old_base = base;
146   previous_base = base;
147
148   dying = DYING_NOT;
149
150   player_input_init(&input);
151
152   timer_init(&invincible_timer,true);
153   timer_init(&skidding_timer,true);
154   timer_init(&safe_timer,true);
155   timer_init(&frame_timer,true);
156   physic.reset();
157 }
158
159 void
160 Player::action()
161 {
162   bool jumped_in_solid = false;
163
164   /* --- HANDLE TUX! --- */
165
166   if(!dying)
167     handle_input();
168
169   /* Move tux: */
170   previous_base = base;
171
172   physic.apply(base.x, base.y);
173
174   if (!dying)
175     {
176
177       collision_swept_object_map(&old_base,&base);
178       keep_in_bounds();
179
180       /* Land: */
181
182
183       if( !on_ground())
184         {
185           physic.enable_gravity(true);
186           if(under_solid())
187             {
188               // fall down
189               physic.set_velocity(physic.get_velocity_x(), 0);
190               jumped_in_solid = true;
191             }
192         }
193       else
194         {
195           /* Land: */
196           if (physic.get_velocity_y() < 0)
197             {
198               base.y = (int)(((int)base.y / 32) * 32);
199               physic.set_velocity(physic.get_velocity_x(), 0);
200             }
201
202           physic.enable_gravity(false);
203           /* Reset score multiplier (for multi-hits): */
204           player_status.score_multiplier = 1;
205         }
206
207       if(jumped_in_solid)
208         {
209           if (isbrick(base.x, base.y) ||
210               isfullbox(base.x, base.y))
211             {
212               World::current()->trygrabdistro(base.x, base.y - 32,BOUNCE);
213               World::current()->trybumpbadguy(base.x, base.y - 64);
214
215               World::current()->trybreakbrick(base.x, base.y, size == SMALL);
216
217               bumpbrick(base.x, base.y);
218               World::current()->tryemptybox(base.x, base.y, RIGHT);
219             }
220
221           if (isbrick(base.x+ 31, base.y) ||
222               isfullbox(base.x+ 31, base.y))
223             {
224               World::current()->trygrabdistro(base.x+ 31, base.y - 32,BOUNCE);
225               World::current()->trybumpbadguy(base.x+ 31, base.y - 64);
226
227               if(size == BIG)
228                 World::current()->trybreakbrick(base.x+ 31, base.y, size == SMALL);
229
230               bumpbrick(base.x+ 31, base.y);
231               World::current()->tryemptybox(base.x+ 31, base.y, LEFT);
232             }
233         }
234
235       grabdistros();
236
237       if (jumped_in_solid)
238         {
239           ++base.y;
240           ++old_base.y;
241           if(on_ground())
242             {
243               /* Make sure jumping is off. */
244               jumping = false;
245             }
246         }
247
248     }
249
250   timer_check(&safe_timer);
251
252
253   /* ---- DONE HANDLING TUX! --- */
254
255   /* Handle invincibility timer: */
256
257
258   if (get_current_music() == HERRING_MUSIC && !timer_check(&invincible_timer))
259     {
260       /*
261          no, we are no more invincible
262          or we were not in invincible mode
263          but are we in hurry ?
264        */
265
266
267       if (timer_get_left(&time_left) < TIME_WARNING)
268         {
269           /* yes, we are in hurry
270              stop the herring_song, prepare to play the correct
271              fast level_song !
272            */
273           set_current_music(HURRYUP_MUSIC);
274         }
275       else
276         {
277           set_current_music(LEVEL_MUSIC);
278         }
279
280       /* start playing it */
281       play_current_music();
282     }
283
284   /* Handle skidding: */
285
286   // timer_check(&skidding_timer); // disabled
287
288   /* End of level? */
289   if (base.x >= World::current()->get_level()->endpos
290       && World::current()->get_level()->endpos != 0)
291     {
292       player_status.next_level = 1;
293     }
294
295 }
296
297 bool
298 Player::on_ground()
299 {
300   return ( issolid(base.x + base.width / 2, base.y + base.height) ||
301            issolid(base.x + 1, base.y + base.height) ||
302            issolid(base.x + base.width - 1, base.y + base.height)  );
303 }
304
305 bool
306 Player::under_solid()
307 {
308   return ( issolid(base.x + base.width / 2, base.y) ||
309            issolid(base.x + 1, base.y) ||
310            issolid(base.x + base.width - 1, base.y)  );
311 }
312
313 void
314 Player::handle_horizontal_input(int newdir)
315 {
316   if(duck)
317     return;
318
319   float vx = physic.get_velocity_x();
320   float vy = physic.get_velocity_y();
321   dir = newdir;
322
323   // skid if we're too fast
324   if(dir != newdir && on_ground() && fabs(physic.get_velocity_x()) > SKID_XM 
325           && !timer_started(&skidding_timer))
326     {
327       timer_start(&skidding_timer, SKID_TIME);
328       play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
329       return;
330     }
331
332   if ((newdir ? (vx < 0) : (vx > 0)) && !isice(base.x, base.y + base.height) &&
333       !timer_started(&skidding_timer))
334     {
335       //vx = 0;
336     }
337
338   /* Facing the direction we're jumping?  Go full-speed: */
339   if (input.fire == UP)
340     {
341       if(vx >= MAX_WALK_XM) {
342         vx = MAX_WALK_XM;
343         physic.set_acceleration(0, 0); // enough speedup
344       } else if(vx <= -MAX_WALK_XM) {
345         vx = -MAX_WALK_XM;
346         physic.set_acceleration(0, 0);
347       }
348       physic.set_acceleration(newdir ? 0.02 : -0.02, 0);
349       if(fabs(vx) < 1) // set some basic run speed
350         vx = newdir ? 1 : -1;
351 #if 0
352       vx += ( newdir ? WALK_SPEED : -WALK_SPEED) * frame_ratio;
353
354       if(newdir)
355         {
356           if (vx > MAX_WALK_XM)
357             vx = MAX_WALK_XM;
358         }
359       else
360         {
361           if (vx < -MAX_WALK_XM)
362             vx = -MAX_WALK_XM;
363         }
364 #endif
365     }
366   else if ( input.fire == DOWN)
367     {
368       if(vx >= MAX_RUN_XM) {
369         vx = MAX_RUN_XM;
370         physic.set_acceleration(0, 0); // enough speedup      
371       } else if(vx <= -MAX_RUN_XM) {
372         vx = -MAX_RUN_XM;
373         physic.set_acceleration(0, 0);
374       }
375       physic.set_acceleration(newdir ? 0.03 : -0.03, 0);
376       if(fabs(vx) < 1) // set some basic run speed
377         vx = newdir ? 1 : -1;
378
379 #if 0
380       vx = vx + ( newdir ? RUN_SPEED : -RUN_SPEED) * frame_ratio;
381
382       if(newdir)
383         {
384           if (vx > MAX_RUN_XM)
385             vx = MAX_RUN_XM;
386         }
387       else
388         {
389           if (vx < -MAX_RUN_XM)
390             vx = -MAX_RUN_XM;
391         }
392 #endif
393     }
394   else
395     {
396 #if 0
397       /* Not facing the direction we're jumping?
398          Go half-speed: */
399       vx = vx + ( newdir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio;
400
401       if(newdir)
402         {
403           if (vx > MAX_WALK_XM / 2)
404             vx = MAX_WALK_XM / 2;
405         }
406       else
407         {
408           if (vx < -MAX_WALK_XM / 2)
409             vx = -MAX_WALK_XM / 2;
410         }
411 #endif
412     }
413   
414   physic.set_velocity(vx, vy);
415 }
416
417 void
418 Player::handle_vertical_input()
419 {
420   if(input.up == DOWN)
421     {
422       if (on_ground())
423         {
424           // jump
425           physic.set_velocity(physic.get_velocity_x(), 5.5);
426           --base.y;
427           jumping = true;
428           if (size == SMALL)
429             play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
430           else
431             play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
432         }
433     }
434   else if(input.up == UP && jumping)
435     {
436       jumping = false;
437       if(physic.get_velocity_y() > 0) {
438         physic.set_velocity(physic.get_velocity_x(), 0);
439       }
440     }
441 }
442
443 void
444 Player::handle_input()
445 {
446   /* Handle key and joystick state: */
447   if(duck == false)
448     {
449       if (input.right == DOWN && input.left == UP)
450         {
451           handle_horizontal_input(RIGHT);
452         }
453       else if (input.left == DOWN && input.right == UP)
454         {
455           handle_horizontal_input(LEFT);
456         }
457       else
458         {
459           float vx = physic.get_velocity_x();
460           if(fabs(vx) < 0.01) {
461             physic.set_velocity(0, physic.get_velocity_y());
462             physic.set_acceleration(0, 0);
463           } else if(vx < 0) {
464             physic.set_acceleration(0.1, 0);
465           } else {
466             physic.set_acceleration(-0.1, 0);
467           }
468         }
469     }
470
471   /* Jump/jumping? */
472
473   if ( input.up == DOWN || (input.up == UP && jumping))
474     {
475       handle_vertical_input();
476     }
477
478   /* Shoot! */
479
480   if (input.fire == DOWN && input.old_fire == UP && got_coffee)
481     {
482       World::current()->add_bullet(base.x, base.y, physic.get_velocity_x(), dir);
483     }
484
485
486   /* Duck! */
487
488   if (input.down == DOWN)
489     {
490       if (size == BIG && duck != true)
491         {
492           duck = true;
493           base.height = 32;
494           base.y += 32;
495         }
496     }
497   else
498     {
499       if (size == BIG && duck)
500         {
501           /* Make sure we're not standing back up into a solid! */
502           base.height = 64;
503           base.y -= 32;
504
505           if (!collision_object_map(&base) /*issolid(base.x + 16, base.y - 16)*/)
506             {
507               duck = false;
508               base.height = 64;
509               old_base.y -= 32;
510               old_base.height = 64;
511             }
512           else
513             {
514               base.height = 32;
515               base.y += 32;
516             }
517         }
518       else
519         {
520           duck = false;
521         }
522     }
523
524   /* (Tux): */
525
526   if(!timer_check(&frame_timer))
527     {
528       timer_start(&frame_timer,25);
529       if (input.right == UP && input.left == UP)
530         {
531           frame_main = 1;
532           frame_ = 1;
533         }
534       else
535         {
536           if ((input.fire == DOWN && (global_frame_counter % 2) == 0) ||
537               (global_frame_counter % 4) == 0)
538             frame_main = (frame_main + 1) % 4;
539
540           frame_ = frame_main;
541
542           if (frame_ == 3)
543             frame_ = 1;
544         }
545     }
546
547 }
548
549 void
550 Player::grabdistros()
551 {
552   /* Grab distros: */
553   if (!dying)
554     {
555       World::current()->trygrabdistro(base.x, base.y, NO_BOUNCE);
556       World::current()->trygrabdistro(base.x+ 31, base.y, NO_BOUNCE);
557
558       World::current()->trygrabdistro(base.x, base.y + base.height, NO_BOUNCE);
559       World::current()->trygrabdistro(base.x+ 31, base.y + base.height, NO_BOUNCE);
560
561       if(size == BIG)
562         {
563           World::current()->trygrabdistro(base.x, base.y + base.height / 2, NO_BOUNCE);
564           World::current()->trygrabdistro(base.x+ 31, base.y + base.height / 2, NO_BOUNCE);
565         }
566
567     }
568
569   /* Enough distros for a One-up? */
570   if (distros >= DISTROS_LIFEUP)
571     {
572       distros = distros - DISTROS_LIFEUP;
573       if(lives < MAX_LIVES)
574         lives++;
575       /*We want to hear the sound even, if MAX_LIVES is reached*/
576       play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
577     }
578 }
579
580 void
581 Player::draw()
582 {
583   if (!timer_started(&safe_timer) || (global_frame_counter % 2) == 0)
584     {
585       if (size == SMALL)
586         {
587           if (timer_started(&invincible_timer))
588             {
589               /* Draw cape: */
590
591               if (dir == RIGHT)
592                 {
593                   texture_draw(&cape_right[global_frame_counter % 2],
594                                base.x- scroll_x, base.y);
595                 }
596               else
597                 {
598                   texture_draw(&cape_left[global_frame_counter % 2],
599                                base.x- scroll_x, base.y);
600                 }
601             }
602
603
604           if (!got_coffee)
605             {
606               if (physic.get_velocity_y() != 0)
607                 {
608                   if (dir == RIGHT)
609                     texture_draw(&smalltux_jump_right, base.x - scroll_x, base.y - 10);
610                   else
611                     texture_draw(&smalltux_jump_left, base.x - scroll_x, base.y - 10);                   
612                 }
613               else
614                 {
615                   if (fabsf(physic.get_velocity_x()) < 1.0f) // standing
616                     {
617                       if (dir == RIGHT)
618                         texture_draw(&smalltux_stand_right, base.x - scroll_x, base.y - 9);
619                       else
620                         texture_draw(&smalltux_stand_left, base.x - scroll_x, base.y - 9);
621                     }
622                   else // moving
623                     {
624                       if (dir == RIGHT)
625                         texture_draw(&tux_right[(global_frame_counter/2) % tux_right.size()], 
626                                      base.x - scroll_x, base.y - 9);
627                       else
628                         texture_draw(&tux_left[(global_frame_counter/2) % tux_left.size()], 
629                                      base.x - scroll_x, base.y - 9);
630                     }
631                 }
632             }
633           else
634             {
635               /* Tux got coffee! */
636
637               if (dir == RIGHT)
638                 {
639                   texture_draw(&firetux_right[frame_], base.x- scroll_x, base.y);
640                 }
641               else
642                 {
643                   texture_draw(&firetux_left[frame_], base.x- scroll_x, base.y);
644                 }
645             }
646         }
647       else
648         {
649           if (timer_started(&invincible_timer))
650             {
651               /* Draw cape: */
652               if (dir == RIGHT)
653                 {
654                   texture_draw(&bigcape_right[global_frame_counter % 2],
655                                base.x- scroll_x - 8, base.y);
656                 }
657               else
658                 {
659                   texture_draw(&bigcape_left[global_frame_counter % 2],
660                                base.x-scroll_x - 8, base.y);
661                 }
662             }
663
664           if (!got_coffee)
665             {
666               if (!duck)
667                 {
668                   if (!timer_started(&skidding_timer))
669                     {
670                       if (!jumping || physic.get_velocity_y() > 0)
671                         {
672                           if (dir == RIGHT)
673                             {
674                               texture_draw(&bigtux_right[frame_],
675                                            base.x- scroll_x - 8, base.y);
676                             }
677                           else
678                             {
679                               texture_draw(&bigtux_left[frame_],
680                                            base.x- scroll_x - 8, base.y);
681                             }
682                         }
683                       else
684                         {
685                           if (dir == RIGHT)
686                             {
687                               texture_draw(&bigtux_right_jump,
688                                            base.x- scroll_x - 8, base.y);
689                             }
690                           else
691                             {
692                               texture_draw(&bigtux_left_jump,
693                                            base.x- scroll_x - 8, base.y);
694                             }
695                         }
696                     }
697                   else
698                     {
699                       if (dir == RIGHT)
700                         {
701                           texture_draw(&skidtux_right,
702                                        base.x- scroll_x - 8, base.y);
703                         }
704                       else
705                         {
706                           texture_draw(&skidtux_left,
707                                        base.x- scroll_x - 8, base.y);
708                         }
709                     }
710                 }
711               else
712                 {
713                   if (dir == RIGHT)
714                     {
715                       texture_draw(&ducktux_right, base.x- scroll_x - 8, base.y - 16);
716                     }
717                   else
718                     {
719                       texture_draw(&ducktux_left, base.x- scroll_x - 8, base.y - 16);
720                     }
721                 }
722             }
723           else
724             {
725               /* Tux has coffee! */
726
727               if (!duck)
728                 {
729                   if (!timer_started(&skidding_timer))
730                     {
731                       if (!jumping || physic.get_velocity_y() > 0)
732                         {
733                           if (dir == RIGHT)
734                             {
735                               texture_draw(&bigfiretux_right[frame_],
736                                            base.x- scroll_x - 8, base.y);
737                             }
738                           else
739                             {
740                               texture_draw(&bigfiretux_left[frame_],
741                                            base.x- scroll_x - 8, base.y);
742                             }
743                         }
744                       else
745                         {
746                           if (dir == RIGHT)
747                             {
748                               texture_draw(&bigfiretux_right_jump,
749                                            base.x- scroll_x - 8, base.y);
750                             }
751                           else
752                             {
753                               texture_draw(&bigfiretux_left_jump,
754                                            base.x- scroll_x - 8, base.y);
755                             }
756                         }
757                     }
758                   else
759                     {
760                       if (dir == RIGHT)
761                         {
762                           texture_draw(&skidfiretux_right,
763                                        base.x- scroll_x - 8, base.y);
764                         }
765                       else
766                         {
767                           texture_draw(&skidfiretux_left,
768                                        base.x- scroll_x - 8, base.y);
769                         }
770                     }
771                 }
772               else
773                 {
774                   if (dir == RIGHT)
775                     {
776                       texture_draw(&duckfiretux_right, base.x- scroll_x - 8, base.y - 16);
777                     }
778                   else
779                     {
780                       texture_draw(&duckfiretux_left, base.x- scroll_x - 8, base.y - 16);
781                     }
782                 }
783             }
784         }
785     }
786
787   if(dying)
788     text_drawf(&gold_text,"Penguins can fly !:",0,0,A_HMIDDLE,A_VMIDDLE,1);
789 }
790
791 void
792 Player::collision(void* p_c_object, int c_object)
793 {
794   BadGuy* pbad_c = NULL;
795
796   switch (c_object)
797     {
798     case CO_BADGUY:
799       pbad_c = (BadGuy*) p_c_object;
800       /* Hurt the player if he just touched it: */
801
802       if (!pbad_c->dying && !dying &&
803           !timer_started(&safe_timer) &&
804           pbad_c->mode != HELD)
805         {
806           if (pbad_c->mode == FLAT && input.fire == DOWN)
807             {
808               pbad_c->mode = HELD;
809               pbad_c->base.y-=8;
810             }
811           else if (pbad_c->mode == KICK)
812             {
813               if (base.y < pbad_c->base.y - 16)
814                 {
815                   /* Step on (stop being kicked) */
816
817                   pbad_c->mode = FLAT;
818                   play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
819                 }
820               else
821                 {
822                   /* Hurt if you get hit by kicked laptop: */
823                   if (!timer_started(&invincible_timer))
824                     {
825                       kill(SHRINK);
826                     }
827                   else
828                     {
829                       pbad_c->dying = DYING_FALLING;
830                       play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
831                       World::current()->add_score(pbad_c->base.x - scroll_x,
832                                                   pbad_c->base.y,
833                                                   25 * player_status.score_multiplier);
834                     }
835                 }
836             }
837           else
838             {
839               if (!timer_started(&invincible_timer ))
840                 {
841                   kill(SHRINK);
842                 }
843               else
844                 {
845                   pbad_c->kill_me();
846                 }
847             }
848           player_status.score_multiplier++;
849         }
850       break;
851     default:
852       break;
853     }
854
855 }
856
857 /* Kill Player! */
858
859 void
860 Player::kill(int mode)
861 {
862   play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
863
864   physic.set_velocity(0, physic.get_velocity_y());
865
866   if (mode == SHRINK && size == BIG)
867     {
868       if (got_coffee)
869         got_coffee = false;
870
871       size = SMALL;
872       base.height = 32;
873
874       timer_start(&safe_timer,TUX_SAFE_TIME);
875     }
876   else
877     {
878       if(size == BIG)
879         duck = true;
880
881       physic.enable_gravity(true);
882       physic.set_acceleration(0, 0);
883       physic.set_velocity(0, 7);
884       dying = DYING_SQUISHED;
885     }
886 }
887
888 void
889 Player::is_dying()
890 {
891   /* He died :^( */
892
893   --lives;
894   remove_powerups();
895   dying = DYING_NOT;
896 }
897
898 bool Player::is_dead()
899 {
900   if(base.y > screen->h)
901     return true;
902   else
903     return false;
904 }
905
906 /* Remove Tux's power ups */
907 void
908 Player::remove_powerups()
909 {
910   got_coffee = false;
911   size = SMALL;
912   base.height = 32;
913 }
914
915 void
916 Player::keep_in_bounds()
917 {
918   Level* plevel = World::current()->get_level();
919
920   /* Keep tux in bounds: */
921   if (base.x< 0)
922     base.x= 0;
923   else if(base.x< scroll_x)
924     base.x= scroll_x;
925   else if (base.x< 160 + scroll_x && scroll_x > 0 && debug_mode)
926     {
927       scroll_x = base.x- 160;
928       /*base.x+= 160;*/
929
930       if(scroll_x < 0)
931         scroll_x = 0;
932
933     }
934   else if (base.x > screen->w / 2 + scroll_x
935            && scroll_x < ((World::current()->get_level()->width * 32) - screen->w))
936     {
937       // FIXME: Scrolling needs to be handled by a seperate View
938       // class, doing it as a player huck is ugly
939
940       // Scroll the screen in past center:
941       scroll_x = base.x - screen->w / 2;
942
943       if (scroll_x > ((plevel->width * 32) - screen->w))
944         scroll_x = ((plevel->width * 32) - screen->w);
945     }
946   else if (base.x> 608 + scroll_x)
947     {
948       /* ... unless there's no more to scroll! */
949
950       /*base.x= 608 + scroll_x;*/
951     }
952
953   /* Keep in-bounds, vertically: */
954
955   if (base.y > screen->h)
956     {
957       kill(KILL);
958     }
959 }