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