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