- added new smalltux
[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   physic.reset();
103 }
104
105 int
106 Player::key_event(SDLKey key, int state)
107 {
108   if(key == keymap.right)
109     {
110       input.right = state;
111       return true;
112     }
113   else if(key == keymap.left)
114     {
115       input.left = state;
116       return true;
117     }
118   else if(key == keymap.jump)
119     {
120       input.up = state;
121       return true;
122     }
123   else if(key == keymap.duck)
124     {
125       input.down = state;
126       return true;
127     }
128   else if(key == keymap.fire)
129     {
130       input.fire = state;
131       return true;
132     }
133   else
134     return false;
135 }
136
137 void
138 Player::level_begin()
139 {
140   base.x  = 100;
141   base.y  = 240;
142   base.xm = 0;
143   base.ym = 0;
144   old_base = base;
145   previous_base = base;
146
147   dying = DYING_NOT;
148
149   player_input_init(&input);
150
151   timer_init(&invincible_timer,true);
152   timer_init(&skidding_timer,true);
153   timer_init(&safe_timer,true);
154   timer_init(&frame_timer,true);
155   physic.reset();
156 }
157
158 void
159 Player::action()
160 {
161   bool jumped_in_solid = false;
162
163   /* --- HANDLE TUX! --- */
164
165   if(!dying)
166     handle_input();
167
168   /* Move tux: */
169   previous_base = base;
170
171   physic.apply(base.x, base.y);
172
173   if (!dying)
174     {
175
176       collision_swept_object_map(&old_base,&base);
177       keep_in_bounds();
178
179       /* Land: */
180
181
182       if( !on_ground())
183         {
184           physic.enable_gravity(true);
185           if(under_solid())
186             {
187               // fall down
188               physic.set_velocity(physic.get_velocity_x(), 0);
189               jumped_in_solid = true;
190             }
191         }
192       else
193         {
194           /* Land: */
195           if (physic.get_velocity_y() < 0)
196             {
197               base.y = (int)(((int)base.y / 32) * 32);
198               physic.set_velocity(physic.get_velocity_x(), 0);
199             }
200
201           physic.enable_gravity(false);
202           /* Reset score multiplier (for multi-hits): */
203           score_multiplier = 1;
204         }
205
206       if(jumped_in_solid)
207         {
208           if (isbrick(base.x, base.y) ||
209               isfullbox(base.x, base.y))
210             {
211               trygrabdistro(base.x, base.y - 32,BOUNCE);
212               trybumpbadguy(base.x, base.y - 64);
213
214               trybreakbrick(base.x, base.y, size == SMALL);
215
216               bumpbrick(base.x, base.y);
217               tryemptybox(base.x, base.y, RIGHT);
218             }
219
220           if (isbrick(base.x+ 31, base.y) ||
221               isfullbox(base.x+ 31, base.y))
222             {
223               trygrabdistro(base.x+ 31, base.y - 32,BOUNCE);
224               trybumpbadguy(base.x+ 31, base.y - 64);
225
226               if(size == BIG)
227                 trybreakbrick(base.x+ 31, base.y, size == SMALL);
228
229               bumpbrick(base.x+ 31, base.y);
230               tryemptybox(base.x+ 31, base.y, LEFT);
231             }
232         }
233
234       grabdistros();
235
236       if (jumped_in_solid)
237         {
238           ++base.y;
239           ++old_base.y;
240           if(on_ground())
241             {
242               /* Make sure jumping is off. */
243               jumping = false;
244             }
245         }
246
247     }
248
249   timer_check(&safe_timer);
250
251
252   /* ---- DONE HANDLING TUX! --- */
253
254   /* Handle invincibility timer: */
255
256
257   if (get_current_music() == HERRING_MUSIC && !timer_check(&invincible_timer))
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
266       if (timer_get_left(&time_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
289   if (base.x >= endpos && endpos != 0)
290     {
291       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           && !timer_started(&skidding_timer))
325     {
326       timer_start(&skidding_timer, 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       !timer_started(&skidding_timer))
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       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(!timer_check(&frame_timer))
526     {
527       timer_start(&frame_timer,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       trygrabdistro(base.x, base.y, NO_BOUNCE);
555       trygrabdistro(base.x+ 31, base.y, NO_BOUNCE);
556
557       trygrabdistro(base.x, base.y + base.height, NO_BOUNCE);
558       trygrabdistro(base.x+ 31, base.y + base.height, NO_BOUNCE);
559
560       if(size == BIG)
561         {
562           trygrabdistro(base.x, base.y + base.height / 2, NO_BOUNCE);
563           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 (!timer_started(&safe_timer) || (global_frame_counter % 2) == 0)
583     {
584       if (size == SMALL)
585         {
586           if (timer_started(&invincible_timer))
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 (timer_started(&invincible_timer))
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 (!timer_started(&skidding_timer))
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
726               if (!duck)
727                 {
728                   if (!timer_started(&skidding_timer))
729                     {
730                       if (!jumping || physic.get_velocity_y() > 0)
731                         {
732                           if (dir == RIGHT)
733                             {
734                               texture_draw(&bigfiretux_right[frame_],
735                                            base.x- scroll_x - 8, base.y);
736                             }
737                           else
738                             {
739                               texture_draw(&bigfiretux_left[frame_],
740                                            base.x- scroll_x - 8, base.y);
741                             }
742                         }
743                       else
744                         {
745                           if (dir == RIGHT)
746                             {
747                               texture_draw(&bigfiretux_right_jump,
748                                            base.x- scroll_x - 8, base.y);
749                             }
750                           else
751                             {
752                               texture_draw(&bigfiretux_left_jump,
753                                            base.x- scroll_x - 8, base.y);
754                             }
755                         }
756                     }
757                   else
758                     {
759                       if (dir == RIGHT)
760                         {
761                           texture_draw(&skidfiretux_right,
762                                        base.x- scroll_x - 8, base.y);
763                         }
764                       else
765                         {
766                           texture_draw(&skidfiretux_left,
767                                        base.x- scroll_x - 8, base.y);
768                         }
769                     }
770                 }
771               else
772                 {
773                   if (dir == RIGHT)
774                     {
775                       texture_draw(&duckfiretux_right, base.x- scroll_x - 8, base.y - 16);
776                     }
777                   else
778                     {
779                       texture_draw(&duckfiretux_left, base.x- scroll_x - 8, base.y - 16);
780                     }
781                 }
782             }
783         }
784     }
785
786   if(dying)
787     text_drawf(&gold_text,"Penguins can fly !:",0,0,A_HMIDDLE,A_VMIDDLE,1);
788 }
789
790 void
791 Player::collision(void* p_c_object, int c_object)
792 {
793   BadGuy* pbad_c = NULL;
794
795   switch (c_object)
796     {
797     case CO_BADGUY:
798       pbad_c = (BadGuy*) p_c_object;
799       /* Hurt the player if he just touched it: */
800
801       if (!pbad_c->dying && !dying &&
802           !timer_started(&safe_timer) &&
803           pbad_c->mode != HELD)
804         {
805           if (pbad_c->mode == FLAT && input.fire == DOWN)
806             {
807               pbad_c->mode = HELD;
808               pbad_c->base.y-=8;
809             }
810           else if (pbad_c->mode == KICK)
811             {
812               if (base.y < pbad_c->base.y - 16)
813                 {
814                   /* Step on (stop being kicked) */
815
816                   pbad_c->mode = FLAT;
817                   play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
818                 }
819               else
820                 {
821                   /* Hurt if you get hit by kicked laptop: */
822                   if (!timer_started(&invincible_timer))
823                     {
824                       kill(SHRINK);
825                     }
826                   else
827                     {
828                       pbad_c->dying = DYING_FALLING;
829                       play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
830                       add_score(pbad_c->base.x - scroll_x,
831                                 pbad_c->base.y,
832                                 25 * score_multiplier);
833                     }
834                 }
835             }
836           else
837             {
838               if (!timer_started(&invincible_timer ))
839                 {
840                   kill(SHRINK);
841                 }
842               else
843                 {
844                   pbad_c->kill_me();
845                 }
846             }
847           score_multiplier++;
848         }
849       break;
850     default:
851       break;
852     }
853
854 }
855
856 /* Kill Player! */
857
858 void
859 Player::kill(int mode)
860 {
861   play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
862
863   physic.set_velocity(0, physic.get_velocity_y());
864
865   if (mode == SHRINK && size == BIG)
866     {
867       if (got_coffee)
868         got_coffee = false;
869
870       size = SMALL;
871       base.height = 32;
872
873       timer_start(&safe_timer,TUX_SAFE_TIME);
874     }
875   else
876     {
877       if(size == BIG)
878         duck = true;
879
880       physic.enable_gravity(true);
881       physic.set_acceleration(0, 0);
882       physic.set_velocity(0, 7);
883       dying = DYING_SQUISHED;
884     }
885 }
886
887 void
888 Player::is_dying()
889 {
890   /* He died :^( */
891
892   --lives;
893   remove_powerups();
894   dying = DYING_NOT;
895 }
896
897 bool Player::is_dead()
898 {
899   if(base.y > screen->h)
900     return true;
901   else
902     return false;
903 }
904
905 /* Remove Tux's power ups */
906 void
907 Player::remove_powerups()
908 {
909   got_coffee = false;
910   size = SMALL;
911   base.height = 32;
912 }
913
914 void
915 Player::keep_in_bounds()
916 {
917   /* Keep tux in bounds: */
918   if (base.x< 0)
919     base.x= 0;
920   else if(base.x< scroll_x)
921     base.x= scroll_x;
922   else if (base.x< 160 + scroll_x && scroll_x > 0 && debug_mode)
923     {
924       scroll_x = base.x- 160;
925       /*base.x+= 160;*/
926
927       if(scroll_x < 0)
928         scroll_x = 0;
929
930     }
931   else if (base.x> screen->w / 2 + scroll_x && scroll_x < ((current_level.width * 32) - screen->w))
932     {
933       /* Scroll the screen in past center: */
934
935       scroll_x = base.x- screen->w / 2;
936       /*base.x= 320 + scroll_x;*/
937
938       if (scroll_x > ((current_level.width * 32) - screen->w))
939         scroll_x = ((current_level.width * 32) - screen->w);
940     }
941   else if (base.x> 608 + scroll_x)
942     {
943       /* ... unless there's no more to scroll! */
944
945       /*base.x= 608 + scroll_x;*/
946     }
947
948   /* Keep in-bounds, vertically: */
949
950   if (base.y > screen->h)
951     {
952       kill(KILL);
953     }
954 }