- added intro text
[supertux.git] / src / player.cpp
1 //  $Id$
2 //
3 //  SuperTux -  A Jump'n Run
4 //  Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <math.h>
21
22 #include "gameloop.h"
23 #include "globals.h"
24 #include "player.h"
25 #include "defines.h"
26 #include "scene.h"
27 #include "tile.h"
28 #include "sprite.h"
29 #include "screen.h"
30
31 Surface* tux_life;
32 std::vector<Surface*> tux_right;
33 std::vector<Surface*> tux_left;
34
35 Surface* smalltux_jump_left;
36 Surface* smalltux_jump_right;
37 Surface* smalltux_stand_left;
38 Surface* smalltux_stand_right;
39 Sprite*  smalltux_gameover;
40 Sprite*  smalltux_skid_left;
41 Sprite*  smalltux_skid_right;
42 Sprite*  smalltux_kick_left;
43 Sprite*  smalltux_kick_right;
44 Sprite*  smalltux_grab_left;
45 Sprite*  smalltux_grab_right;
46 Sprite*  smalltux_star;
47
48 Sprite* largetux_star;
49 Sprite* largetux_kick_left;
50 Sprite* largetux_kick_right;
51 Sprite* largetux_grab_left;
52 Sprite* largetux_grab_right;
53 Sprite* largetux_stand_left;
54 Sprite* largetux_stand_right;
55 Sprite* bigtux_right;
56 Sprite* bigtux_left;
57 Sprite* bigtux_right_jump;
58 Sprite* bigtux_left_jump;
59 Sprite* ducktux_right;
60 Sprite* ducktux_left;
61
62 Surface* skidtux_right;
63 Surface* skidtux_left;
64 Surface* firetux_right[3];
65 Surface* firetux_left[3];
66
67 Surface* bigfiretux_right[3];
68 Surface* bigfiretux_left[3];
69 Surface* bigfiretux_right_jump;
70 Surface* bigfiretux_left_jump;
71 Surface* duckfiretux_right;
72 Surface* duckfiretux_left;
73 Surface* skidfiretux_right;
74 Surface* skidfiretux_left;
75
76 Surface* cape_right[2];
77 Surface* cape_left[2];
78
79 PlayerKeymap keymap;
80
81 PlayerKeymap::PlayerKeymap()
82 {
83   keymap.jump  = SDLK_UP;
84   keymap.duck  = SDLK_DOWN;
85   keymap.left  = SDLK_LEFT;
86   keymap.right = SDLK_RIGHT;
87   keymap.fire  = SDLK_LCTRL;
88 }
89
90 void player_input_init(player_input_type* pplayer_input)
91 {
92   pplayer_input->down = UP;
93   pplayer_input->fire = UP;
94   pplayer_input->left = UP;
95   pplayer_input->old_fire = UP;
96   pplayer_input->right = UP;
97   pplayer_input->up = UP;
98 }
99
100 void
101 Player::init()
102 {
103   Level* plevel = World::current()->get_level();
104
105   holding_something = false;
106
107   base.width = 32;
108   base.height = 32;
109
110   size = SMALL;
111   got_coffee = false;
112
113   base.x = plevel->start_pos_x;
114   base.y = plevel->start_pos_y;
115   base.xm = 0;
116   base.ym = 0;
117   previous_base = old_base = base;
118   dir = RIGHT;
119   duck = false;
120
121   dying   = DYING_NOT;
122   jumping = false;
123
124   frame_main = 0;
125   frame_ = 0;
126   
127   player_input_init(&input);
128
129   invincible_timer.init(true);
130   skidding_timer.init(true);
131   safe_timer.init(true);
132   frame_timer.init(true);
133
134   physic.reset();
135 }
136
137 int
138 Player::key_event(SDLKey key, int state)
139 {
140   if(key == keymap.right)
141     {
142       input.right = state;
143       return true;
144     }
145   else if(key == keymap.left)
146     {
147       input.left = state;
148       return true;
149     }
150   else if(key == keymap.jump)
151     {
152       input.up = state;
153       return true;
154     }
155   else if(key == keymap.duck)
156     {
157       input.down = state;
158       return true;
159     }
160   else if(key == keymap.fire)
161     {
162       input.fire = state;
163       return true;
164     }
165   else
166     return false;
167 }
168
169 void
170 Player::level_begin()
171 {
172   base.x  = 100;
173   base.y  = 170;
174   base.xm = 0;
175   base.ym = 0;
176   previous_base = old_base = base;
177   duck = false;
178
179   dying = DYING_NOT;
180
181   player_input_init(&input);
182
183   invincible_timer.init(true);
184   skidding_timer.init(true);
185   safe_timer.init(true);
186   frame_timer.init(true);
187
188   physic.reset();
189 }
190
191 void
192 Player::action(double frame_ratio)
193 {
194   bool jumped_in_solid = false;
195
196   if (input.fire == UP)
197     holding_something = false;
198
199   /* Move tux: */
200   previous_base = base;
201
202   /* --- HANDLE TUX! --- */
203   if(dying == DYING_NOT)
204     handle_input();
205
206   physic.apply(frame_ratio, base.x, base.y);
207
208   if(dying == DYING_NOT) 
209     {
210       base_type target = base;
211
212       collision_swept_object_map(&old_base, &base);
213
214       // Don't accelerate Tux if he is running against a wall
215       if (target.x != base.x)
216         {
217           physic.set_velocity_x(0);
218         }
219
220       // special exception for cases where we're stuck under tiles after
221       // being ducked. In this case we drift out
222       if(!duck && on_ground() && old_base.x == base.x && old_base.y == base.y
223          && collision_object_map(base))
224         {
225           base.x += frame_ratio * WALK_SPEED * (dir ? 1 : -1);
226           previous_base = old_base = base;
227         }
228       keep_in_bounds();
229
230       // Land:
231       if (!on_ground())
232         {
233           physic.enable_gravity(true);
234           if(under_solid())
235             {
236               // fall down
237               physic.set_velocity_y(0);
238               jumped_in_solid = true;
239             }
240         }
241       else
242         {
243           /* Land: */
244           if (physic.get_velocity_y() < 0)
245             {
246               base.y = (int)(((int)base.y / 32) * 32);
247               physic.set_velocity_y(0);
248             }
249
250           physic.enable_gravity(false);
251           /* Reset score multiplier (for multi-hits): */
252           player_status.score_multiplier = 1;
253         }
254
255       if(jumped_in_solid)
256         {
257           if (isbrick(base.x, base.y) ||
258               isfullbox(base.x, base.y))
259             {
260               World::current()->trygrabdistro(base.x, base.y - 32,BOUNCE);
261               World::current()->trybumpbadguy(base.x, base.y - 64);
262
263               World::current()->trybreakbrick(base.x, base.y, size == SMALL);
264
265               bumpbrick(base.x, base.y);
266               World::current()->tryemptybox(base.x, base.y, RIGHT);
267             }
268
269           if (isbrick(base.x+ 31, base.y) ||
270               isfullbox(base.x+ 31, base.y))
271             {
272               World::current()->trygrabdistro(base.x+ 31, base.y - 32,BOUNCE);
273               World::current()->trybumpbadguy(base.x+ 31, base.y - 64);
274
275               if(size == BIG)
276                 World::current()->trybreakbrick(base.x+ 31, base.y, size == SMALL);
277
278               bumpbrick(base.x+ 31, base.y);
279               World::current()->tryemptybox(base.x+ 31, base.y, LEFT);
280             }
281         }
282
283       grabdistros();
284
285       if (jumped_in_solid)
286         {
287           ++base.y;
288           ++old_base.y;
289           if(on_ground())
290             {
291               /* Make sure jumping is off. */
292               jumping = false;
293             }
294         }
295     }
296
297   /* ---- DONE HANDLING TUX! --- */
298
299   // check some timers
300   skidding_timer.check();
301   invincible_timer.check();
302   safe_timer.check();
303 }
304
305 bool
306 Player::on_ground()
307 {
308   return ( issolid(base.x + base.width / 2, base.y + base.height) ||
309            issolid(base.x + 1, base.y + base.height) ||
310            issolid(base.x + base.width - 1, base.y + base.height)  );
311 }
312
313 bool
314 Player::under_solid()
315 {
316   return ( issolid(base.x + base.width / 2, base.y) ||
317            issolid(base.x + 1, base.y) ||
318            issolid(base.x + base.width - 1, base.y)  );
319 }
320
321 void
322 Player::handle_horizontal_input()
323 {
324   float vx = physic.get_velocity_x();
325   float vy = physic.get_velocity_y();
326   float ax = physic.get_acceleration_x();
327   float ay = physic.get_acceleration_y();
328
329   float dirsign = 0;
330   if(input.left == DOWN && input.right == UP && (!duck || physic.get_velocity_y() != 0)) {
331       dir = LEFT;
332       dirsign = -1;
333   } else if(input.left == UP && input.right == DOWN && (!duck || physic.get_velocity_y() != 0)) {
334       dir = RIGHT;
335       dirsign = 1;
336   }
337
338   if (input.fire == UP) {
339       ax = dirsign * WALK_ACCELERATION_X;
340       // limit speed
341       if(vx >= MAX_WALK_XM && dirsign > 0) {
342         vx = MAX_WALK_XM;
343         ax = 0;
344       } else if(vx <= -MAX_WALK_XM && dirsign < 0) {
345         vx = -MAX_WALK_XM;
346         ax = 0;
347       }
348   } else {
349       ax = dirsign * RUN_ACCELERATION_X;
350       // limit speed
351       if(vx >= MAX_RUN_XM && dirsign > 0) {
352         vx = MAX_RUN_XM;
353         ax = 0;
354       } else if(vx <= -MAX_RUN_XM && dirsign < 0) {
355         vx = -MAX_RUN_XM;
356         ax = 0;
357       }
358   }
359
360   // we can reach WALK_SPEED without any acceleration
361   if(dirsign != 0 && fabs(vx) < WALK_SPEED) {
362     vx = dirsign * WALK_SPEED;
363   }
364
365   // changing directions?
366   if(on_ground() && ((vx < 0 && dirsign >0) || (vx>0 && dirsign<0))) {
367       if(fabs(vx)>SKID_XM && !skidding_timer.check()) {
368           skidding_timer.start(SKID_TIME);
369           play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
370           ax *= 2.5;
371       } else {
372           ax *= 2;
373       }
374   }
375
376   // we get slower when not pressing any keys
377   if(dirsign == 0) {
378       if(fabs(vx) < WALK_SPEED) {
379           vx = 0;
380           ax = 0;
381       } else if(vx < 0) {
382           ax = WALK_ACCELERATION_X * 1.5;
383       } else {
384           ax = WALK_ACCELERATION_X * -1.5;
385       }
386   }
387
388   // if we're on ice slow down acceleration or deceleration
389   if (isice(base.x, base.y + base.height))
390   {
391     /* the acceleration/deceleration rate on ice is inversely proportional to
392      * the current velocity.
393      */
394
395     // increasing 1 will increase acceleration/deceleration rate
396     // decreasing 1 will decrease acceleration/deceleration rate
397     //  must stay above zero, though
398     if (ax != 0) ax *= 1 / fabs(vx);
399   }
400
401   physic.set_velocity(vx, vy);
402   physic.set_acceleration(ax, ay);
403 }
404
405 void
406 Player::handle_vertical_input()
407 {
408   if(input.up == DOWN)
409     {
410       if (on_ground())
411         {
412           // jump higher if we are running
413           if (physic.get_velocity_x() > MAX_WALK_XM)
414             physic.set_velocity_y(5.8);
415           else
416             physic.set_velocity_y(5.2);
417
418           --base.y;
419           jumping = true;
420           if (size == SMALL)
421             play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
422           else
423             play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
424         }
425     }
426   else if(input.up == UP && jumping)
427     {
428       jumping = false;
429       if(physic.get_velocity_y() > 0) {
430         physic.set_velocity_y(0);
431       }
432     }
433 }
434
435 void
436 Player::handle_input()
437 {
438   /* Handle horizontal movement: */
439     handle_horizontal_input();
440
441   /* Jump/jumping? */
442
443   if ( input.up == DOWN || (input.up == UP && jumping))
444     {
445       handle_vertical_input();
446     }
447
448   /* Shoot! */
449
450   if (input.fire == DOWN && input.old_fire == UP && got_coffee)
451     {
452       World::current()->add_bullet(base.x, base.y, physic.get_velocity_x(), dir);
453     }
454
455   /* tux animations: */
456   if(!frame_timer.check())
457     {
458       frame_timer.start(25);
459       if (input.right == UP && input.left == UP)
460         {
461           frame_main = 1;
462           frame_ = 1;
463         }
464       else
465         {
466           if ((input.fire == DOWN && (global_frame_counter % 2) == 0) ||
467               (global_frame_counter % 4) == 0)
468             frame_main = (frame_main + 1) % 4;
469
470           frame_ = frame_main;
471
472           if (frame_ == 3)
473             frame_ = 1;
474         }
475     }
476
477   /* Duck! */
478   if (input.down == DOWN && size == BIG && !duck && physic.get_velocity_y() == 0)
479     {
480       duck = true;
481       base.height = 32;                             
482       base.y += 32;
483       // changing base size confuses collision otherwise
484       old_base = previous_base = base;
485     }
486   else if(input.down == UP && size == BIG && duck && physic.get_velocity_y() == 0 && on_ground())
487     {
488       duck = false;
489       base.y -= 32;
490       base.height = 64;
491       old_base = previous_base = base;
492     }
493 }
494
495 void
496 Player::grabdistros()
497 {
498   /* Grab distros: */
499   if (!dying)
500     {
501       World::current()->trygrabdistro(base.x, base.y, NO_BOUNCE);
502       World::current()->trygrabdistro(base.x+ 31, base.y, NO_BOUNCE);
503
504       World::current()->trygrabdistro(base.x, base.y + base.height, NO_BOUNCE);
505       World::current()->trygrabdistro(base.x+ 31, base.y + base.height, NO_BOUNCE);
506
507       if(size == BIG)
508         {
509           World::current()->trygrabdistro(base.x, base.y + base.height / 2, NO_BOUNCE);
510           World::current()->trygrabdistro(base.x+ 31, base.y + base.height / 2, NO_BOUNCE);
511         }
512
513     }
514
515   /* Enough distros for a One-up? */
516   if (player_status.distros >= DISTROS_LIFEUP)
517     {
518       player_status.distros = player_status.distros - DISTROS_LIFEUP;
519       if(player_status.lives < MAX_LIVES)
520         ++player_status.lives;
521       /*We want to hear the sound even, if MAX_LIVES is reached*/
522       play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
523     }
524 }
525
526 void
527 Player::draw()
528 {
529   if (!safe_timer.started() || (global_frame_counter % 2) == 0)
530     {
531       if (dying == DYING_SQUISHED)
532         {
533           smalltux_gameover->draw(base.x - scroll_x, base.y);
534         }
535       else
536         {
537           if (size == SMALL)
538             {
539               if (!skidding_timer.started())
540                 {
541                   if (physic.get_velocity_y() != 0)
542                     {
543                       if (dir == RIGHT)
544                         smalltux_jump_right->draw( base.x - scroll_x, base.y - 10);
545                       else
546                         smalltux_jump_left->draw( base.x - scroll_x, base.y - 10);                   
547                     }
548                   else
549                     {
550                       if (fabsf(physic.get_velocity_x()) < 1.0f) // standing
551                         {
552                           if (dir == RIGHT)
553                             smalltux_stand_right->draw( base.x - scroll_x, base.y - 9);
554                           else
555                             smalltux_stand_left->draw( base.x - scroll_x, base.y - 9);
556                         }
557                       else // moving
558                         {
559                           if (dir == RIGHT)
560                             tux_right[(global_frame_counter/2) % tux_right.size()]->draw(base.x - scroll_x, base.y - 9);
561                           else
562                             tux_left[(global_frame_counter/2) % tux_left.size()]->draw(base.x - scroll_x, base.y - 9);
563                         }
564                     }
565                 }
566               else
567                 {
568                   if (dir == RIGHT)
569                     smalltux_skid_right->draw(base.x - scroll_x, base.y);
570                   else
571                     smalltux_skid_left->draw(base.x - scroll_x, base.y); 
572                 }
573
574               if (holding_something && physic.get_velocity_y() == 0)
575                 {
576                   if (dir == RIGHT)
577                     smalltux_grab_right->draw(base.x - scroll_x, base.y);
578                   else
579                     smalltux_grab_left->draw(base.x - scroll_x, base.y);
580                 }
581
582               if (invincible_timer.started())
583                 smalltux_star->draw(base.x - scroll_x, base.y);
584             }
585           else // Large Tux
586             {
587               if (!got_coffee)
588                 {
589                   if (!duck)
590                     {
591                       if (!skidding_timer.started())
592                         {
593                           if (physic.get_velocity_y() == 0)
594                             {
595                               if (fabsf(physic.get_velocity_x()) < 1.0f) // standing
596                                 {
597                                   if (dir == RIGHT)
598                                     largetux_stand_right->draw(base.x - scroll_x, base.y);
599                                   else
600                                     largetux_stand_left->draw(base.x - scroll_x, base.y);
601                                 }
602                               else // walking
603                                 {
604                                   if (dir == RIGHT)
605                                     bigtux_right->draw(base.x - scroll_x, base.y);
606                                   else
607                                     bigtux_left->draw(base.x - scroll_x, base.y);
608                                 }
609                             }
610                           else
611                             {
612                               if (dir == RIGHT)
613                                 bigtux_right_jump->draw(base.x - scroll_x, base.y);
614                               else
615                                 bigtux_left_jump->draw(base.x - scroll_x, base.y);
616                             }
617                         }
618                       else
619                         {
620                           if (dir == RIGHT)
621                             skidtux_right->draw(base.x - scroll_x - 8, base.y);
622                           else
623                             skidtux_left->draw(base.x - scroll_x - 8, base.y);
624                         }
625                     }
626                   else
627                     {
628                       if (dir == RIGHT)
629                         ducktux_right->draw(base.x - scroll_x, base.y);
630                       else
631                         ducktux_left->draw(base.x - scroll_x, base.y);
632                     }
633                 }
634               else
635                 {
636                   /* Tux has coffee! */
637                   if (!duck)
638                     {
639                       if (!skidding_timer.started())
640                         {
641                           if (!jumping || physic.get_velocity_y() > 0)
642                             {
643                               if (dir == RIGHT)
644                                 bigfiretux_right[frame_]->draw(base.x- scroll_x - 8, base.y);
645                               else
646                                 bigfiretux_left[frame_]->draw(base.x- scroll_x - 8, base.y);
647                             }
648                           else
649                             {
650                               if (dir == RIGHT)
651                                 bigfiretux_right_jump->draw(base.x- scroll_x - 8, base.y);
652                               else
653                                 bigfiretux_left_jump->draw(base.x- scroll_x - 8, base.y);
654                             }
655                         }
656                       else
657                         {
658                           if (dir == RIGHT)
659                             skidfiretux_right->draw(base.x- scroll_x - 8, base.y);
660                           else
661                             skidfiretux_left->draw(base.x- scroll_x - 8, base.y);
662                         }
663                     }
664                   else
665                     {
666                       if (dir == RIGHT)
667                         duckfiretux_right->draw( base.x- scroll_x - 8, base.y - 16);
668                       else
669                         duckfiretux_left->draw( base.x- scroll_x - 8, base.y - 16);
670                     }
671                 }
672
673               if (holding_something && !duck && physic.get_velocity_y() == 0)
674                 {
675                   if (dir == RIGHT)
676                     largetux_grab_right->draw(base.x - scroll_x, base.y);
677                   else
678                     largetux_grab_left->draw(base.x - scroll_x, base.y);
679                 }
680
681               if (invincible_timer.started())
682                 largetux_star->draw(base.x - scroll_x, base.y);
683             }
684         }     
685     }
686
687   if (debug_mode)
688     fillrect(base.x - scroll_x, base.y, 32, 32, 75,75,75, 150);
689 }
690
691 void
692 Player::collision(void* p_c_object, int c_object)
693 {
694   BadGuy* pbad_c = NULL;
695
696   switch (c_object)
697     {
698     case CO_BADGUY:
699       pbad_c = (BadGuy*) p_c_object;
700
701      /* Hurt player if he touches a badguy */
702       if (!pbad_c->dying && !dying &&
703           !safe_timer.started() &&
704           pbad_c->mode != BadGuy::HELD)
705         {
706           if (pbad_c->mode == BadGuy::FLAT && input.fire == DOWN)
707             {
708               holding_something = true;
709               pbad_c->mode = BadGuy::HELD;
710               pbad_c->base.y-=8;
711             }
712           else if (pbad_c->mode == BadGuy::FLAT)
713             {
714               // Don't get hurt if we're kicking a flat badguy!
715             }
716           else if (pbad_c->mode == BadGuy::KICK)
717             {
718               /* Hurt if you get hit by kicked laptop: */
719               if (!invincible_timer.started())
720                 {
721                   kill(SHRINK);
722                 }
723               else
724                 {
725                    pbad_c->dying = DYING_FALLING;
726                    play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
727                    World::current()->add_score(pbad_c->base.x - scroll_x,
728                                                pbad_c->base.y,
729                                                25 * player_status.score_multiplier);
730                 }
731             }
732           else
733             {
734               if (!invincible_timer.started())
735                 {
736                   kill(SHRINK);
737                 }
738               else
739                 {
740                   pbad_c->kill_me();
741                 }
742             }
743           player_status.score_multiplier++;
744         }
745       break;
746     default:
747       break;
748     }
749
750 }
751
752 /* Kill Player! */
753
754 void
755 Player::kill(HurtMode mode)
756 {
757   play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
758
759   physic.set_velocity_x(0);
760
761   if (mode == SHRINK && size == BIG)
762     {
763       if (got_coffee)
764         {
765           got_coffee = false;
766         }
767       else
768         {
769           size = SMALL;
770           base.height = 32;
771           duck = false;
772         }
773       safe_timer.start(TUX_SAFE_TIME);
774     }
775   else
776     {
777       physic.enable_gravity(true);
778       physic.set_acceleration(0, 0);
779       physic.set_velocity(0, 7);
780       dying = DYING_SQUISHED;
781     }
782 }
783
784 void
785 Player::is_dying()
786 {
787   remove_powerups();
788   dying = DYING_NOT;
789 }
790
791 bool Player::is_dead()
792 {
793   if(base.y > screen->h)
794     return true;
795   else
796     return false;
797 }
798
799 /* Remove Tux's power ups */
800 void
801 Player::remove_powerups()
802 {
803   got_coffee = false;
804   size = SMALL;
805   base.height = 32;
806 }
807
808 void
809 Player::keep_in_bounds()
810 {
811   Level* plevel = World::current()->get_level();
812
813   /* Keep tux in bounds: */
814   if (base.x < 0)
815     { // Lock Tux to the size of the level, so that he doesn't fall of
816       // on the left side
817       base.x = 0;
818     }
819   else if (base.x < scroll_x)
820     { 
821       base.x = scroll_x;
822     }
823
824   /* Keep in-bounds, vertically: */
825   if (base.y > screen->h)
826     {
827       kill(KILL);
828     }
829
830   int scroll_threshold = screen->w/2 - 80;
831   if (debug_mode)
832     {
833       scroll_x += screen->w/2;
834       // Backscrolling for debug mode
835       if (scroll_x < base.x - 80)
836         scroll_x = base.x - 80;
837       else if (scroll_x > base.x + 80)
838         scroll_x = base.x + 80;
839       scroll_x -= screen->w/2;
840
841       if(scroll_x < 0)
842         scroll_x = 0;
843     }
844   else
845     {
846       if (base.x > scroll_threshold + scroll_x
847           && scroll_x < ((World::current()->get_level()->width * 32) - screen->w))
848         {
849           // FIXME: Scrolling needs to be handled by a seperate View
850           // class, doing it as a player huck is ugly
851           
852           // Scroll the screen in past center:
853           scroll_x = base.x - scroll_threshold;
854           
855           // Lock the scrolling to the levelsize, so that we don't
856           // scroll over the right border
857           if (scroll_x > 32 * plevel->width - screen->w)
858             scroll_x = 32 * plevel->width - screen->w;
859         }
860     }
861 }
862
863 // EOF //
864