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