- renamed *.c to *.cxx
[supertux.git] / src / gameloop.cpp
1 /*
2   gameloop.c
3   
4   Super Tux - Game Loop!
5   
6   by Bill Kendrick & Tobias Glaesser
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - March 15, 2004
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <time.h>
19 #include <SDL.h>
20
21 #ifdef LINUX
22 #include <pwd.h>
23 #include <sys/types.h>
24 #include <ctype.h>
25 #endif
26
27 #include "defines.h"
28 #include "globals.h"
29 #include "gameloop.h"
30 #include "screen.h"
31 #include "setup.h"
32 #include "high_scores.h"
33 #include "menu.h"
34 #include "badguy.h"
35 #include "world.h"
36 #include "special.h"
37 #include "player.h"
38 #include "level.h"
39 #include "scene.h"
40 #include "collision.h"
41
42 /* extern variables */
43
44 st_level current_level;
45 int game_started = NO;
46
47 /* Local variables: */
48
49 static texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2];
50 static texture_type img_cloud[2][4];
51 static SDL_Event event;
52 static SDLKey key;
53 static char level_subset[100];
54 static char str[60];
55 static float fps_fps;
56 static int st_gl_mode;
57 static unsigned int last_update_time;
58 static unsigned int update_time;
59 static int pause_menu_frame;
60 static int debug_fps;
61
62 /* Local function prototypes: */
63
64 void levelintro(void);
65 void loadshared(void);
66 void unloadshared(void);
67 void drawstatus(void);
68 void drawendscreen(void);
69 void drawresultscreen(void);
70
71 #define JOYSTICK_DEAD_ZONE 4096
72
73 void levelintro(void)
74 {
75   /* Level Intro: */
76
77   clearscreen(0, 0, 0);
78
79   sprintf(str, "LEVEL %d", level);
80   text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
81
82   sprintf(str, "%s", current_level.name);
83   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
84
85   sprintf(str, "TUX x %d", tux.lives);
86   text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
87
88   flipscreen();
89
90   SDL_Delay(1000);
91 }
92
93 /* Reset Timers */
94 void start_timers(void)
95 {
96   timer_start(&time_left,current_level.time_left*1000);
97   st_pause_ticks_init();
98   update_time = st_get_ticks();
99 }
100
101 void activate_bad_guys(void)
102 {
103   int x,y;
104
105   /* Activate bad guys: */
106
107   for (y = 0; y < 15; y++)
108     {
109       for (x = 0; x < current_level.width; x++)
110         {
111           if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
112             {
113               add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
114               current_level.tiles[y][x] = '.';
115             }
116         }
117     }
118
119 }
120
121 /* --- GAME EVENT! --- */
122
123 void game_event(void)
124 {
125   while (SDL_PollEvent(&event))
126     {
127       switch(event.type)
128         {
129         case SDL_QUIT:        /* Quit event - quit: */
130           quit = 1;
131           break;
132         case SDL_KEYDOWN:     /* A keypress! */
133           key = event.key.keysym.sym;
134
135           /* Check for menu-events, if the menu is shown */
136           if(show_menu)
137             menu_event(&event.key.keysym);
138
139           if(player_key_event(&tux,key,DOWN))
140             break;
141
142           switch(key)
143             {
144             case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
145               if(!game_pause)
146                 {
147                   if(st_gl_mode == ST_GL_TEST)
148                     quit = 1;
149                   else if(show_menu)
150                     {
151                       menu_set_current(&game_menu);
152                       show_menu = 0;
153                       st_pause_ticks_stop();
154                     }
155                   else
156                     {
157                       menu_set_current(&game_menu);
158                       show_menu = 1;
159                       st_pause_ticks_start();
160                     }
161                 }
162               break;
163             default:
164               break;
165             }
166           break;
167         case SDL_KEYUP:      /* A keyrelease! */
168           key = event.key.keysym.sym;
169
170           if(player_key_event(&tux,key,UP))
171             break;
172
173           switch(key)
174             {
175             case SDLK_p:
176               if(!show_menu)
177                 {
178                   if(game_pause)
179                     {
180                       game_pause = 0;
181                       st_pause_ticks_stop();
182                     }
183                   else
184                     {
185                       game_pause = 1;
186                       st_pause_ticks_start();
187                     }
188                 }
189               break;
190             case SDLK_TAB:
191               if(debug_mode == YES)
192                 {
193                   tux.size = !tux.size;
194                   if(tux.size == BIG)
195                     {
196                       tux.base.height = 64;
197                     }
198                   else
199                     tux.base.height = 32;
200                 }
201               break;
202             case SDLK_END:
203               if(debug_mode == YES)
204                 distros += 50;
205               break;
206             case SDLK_SPACE:
207               if(debug_mode == YES)
208                 next_level = 1;
209               break;
210             case SDLK_DELETE:
211               if(debug_mode == YES)
212                 tux.got_coffee = 1;
213               break;
214             case SDLK_INSERT:
215               if(debug_mode == YES)
216                 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
217               break;
218             case SDLK_l:
219               if(debug_mode == YES)
220                 --tux.lives;
221               break;
222             case SDLK_s:
223               if(debug_mode == YES)
224                 score += 1000;
225             case SDLK_f:
226               if(debug_fps == YES)
227               debug_fps = NO;
228               else
229               debug_fps = YES;
230               break;          
231             default:
232               break;
233             }
234           break;
235 #ifdef JOY_YES
236
237         case SDL_JOYAXISMOTION:
238           switch(event.jaxis.axis)
239             {
240             case JOY_X:
241               if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
242                 tux.input.left = DOWN;
243               else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
244                 tux.input.left = UP;
245
246               if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
247                 tux.input.right = DOWN;
248               else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
249                 tux.input.right = UP;
250               break;
251             case JOY_Y:
252               if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
253                 tux.input.down = DOWN;
254               else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
255                 tux.input.down = UP;
256
257               /* Handle joystick for the menu */
258               if(show_menu)
259                 {
260                   if(tux.input.down == DOWN)
261                     menuaction = MN_DOWN;
262                   else
263                     menuaction = MN_UP;
264                 }
265               break;
266             default:
267               break;
268             }
269           break;
270         case SDL_JOYBUTTONDOWN:
271           if (event.jbutton.button == JOY_A)
272             tux.input.up = DOWN;
273           else if (event.jbutton.button == JOY_B)
274             tux.input.fire = DOWN;
275           break;
276         case SDL_JOYBUTTONUP:
277           if (event.jbutton.button == JOY_A)
278             tux.input.up = UP;
279           else if (event.jbutton.button == JOY_B)
280             tux.input.fire = UP;
281
282           if(show_menu)
283             menuaction = MN_HIT;
284           break;
285
286 #endif
287         default:
288           break;
289
290         }  /* switch */
291
292     } /* while */
293
294 }
295
296 /* --- GAME ACTION! --- */
297
298 int game_action(void)
299 {
300   int i;
301
302   /* (tux_dying || next_level) */
303   if (tux.dying || next_level)
304     {
305       /* Tux either died, or reached the end of a level! */
306
307       halt_music();
308
309
310       if (next_level)
311         {
312           /* End of a level! */
313           level++;
314           next_level = 0;
315           if(st_gl_mode != ST_GL_TEST)
316             {
317               drawresultscreen();
318             }
319           else
320             {
321               level_free_gfx();
322               level_free(&current_level);
323               level_free_song();
324               unloadshared();
325               arrays_free();
326               return(0);
327             }
328           player_level_begin(&tux);
329         }
330       else
331         {
332           player_dying(&tux);
333
334           /* No more lives!? */
335
336           if (tux.lives < 0)
337             {
338               if(st_gl_mode != ST_GL_TEST)
339                 drawendscreen();
340
341               if(st_gl_mode != ST_GL_TEST)
342                 {
343                   if (score > hs_score)
344                     save_hs(score);
345                 }
346               level_free_gfx();
347               level_free(&current_level);
348               level_free_song();
349               unloadshared();
350               arrays_free();
351               return(0);
352             } /* if (lives < 0) */
353         }
354
355       /* Either way, (re-)load the (next) level... */
356
357       player_level_begin(&tux);
358       set_defaults();
359       level_free(&current_level);
360       if(level_load(&current_level,level_subset,level) != 0)
361         return 0;
362       arrays_free();
363       arrays_init();
364       activate_bad_guys();
365       level_free_gfx();
366       level_load_gfx(&current_level);
367       level_free_song();
368       level_load_song(&current_level);
369       if(st_gl_mode != ST_GL_TEST)
370         levelintro();
371       start_timers();
372       /* Play music: */
373       play_current_music();
374     }
375
376   player_action(&tux);
377
378   /* Handle bouncy distros: */
379
380   for (i = 0; i < num_bouncy_distros; i++)
381     {
382       bouncy_distro_action(&bouncy_distros[i]);
383     }
384
385
386   /* Handle broken bricks: */
387
388   for (i = 0; i < num_broken_bricks; i++)
389     {
390       broken_brick_action(&broken_bricks[i]);
391     }
392
393
394   /* Handle distro counting: */
395
396   if (counting_distros == YES)
397     {
398       distro_counter--;
399
400       if (distro_counter <= 0)
401         counting_distros = -1;
402     }
403
404
405   /* Handle bouncy bricks: */
406
407   for (i = 0; i < num_bouncy_bricks; i++)
408     {
409       bouncy_brick_action(&bouncy_bricks[i]);
410     }
411
412
413   /* Handle floating scores: */
414
415   for (i = 0; i < num_floating_scores; i++)
416     {
417       floating_score_action(&floating_scores[i]);
418     }
419
420
421   /* Handle bullets: */
422
423   for (i = 0; i < num_bullets; ++i)
424     {
425       bullet_action(&bullets[i]);
426     }
427
428   /* Handle upgrades: */
429
430   for (i = 0; i < num_upgrades; i++)
431     {
432       upgrade_action(&upgrades[i]);
433     }
434
435
436   /* Handle bad guys: */
437
438   for (i = 0; i < num_bad_guys; i++)
439     {
440       badguy_action(&bad_guys[i]);
441     }
442
443   /* Handle all possible collisions. */
444   collision_handler();
445
446   return -1;
447 }
448
449 /* --- GAME DRAW! --- */
450
451 void game_draw(void)
452 {
453   int  x, y, i, s;
454
455   /* Draw screen: */
456
457   if (tux.dying && (frame % 4) == 0)
458     clearscreen(255, 255, 255);
459   else if(timer_check(&super_bkgd_timer))
460     texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
461   else
462     {
463       /* Draw the real background */
464       if(current_level.bkgd_image[0] != '\0')
465         {
466           s = (int)scroll_x / 30;
467           texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
468           texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
469         }
470       else
471         {
472           clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
473         }
474     }
475
476   /* Draw background: */
477
478   for (y = 0; y < 15; ++y)
479     {
480       for (x = 0; x < 21; ++x)
481         {
482           drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
483                     current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
484         }
485     }
486
487
488   /* (Bouncy bricks): */
489
490   for (i = 0; i < num_bouncy_bricks; ++i)
491     {
492       bouncy_brick_draw(&bouncy_bricks[i]);
493     }
494
495
496   /* (Bad guys): */
497
498   for (i = 0; i < num_bad_guys; ++i)
499     {
500       badguy_draw(&bad_guys[i]);
501     }
502
503   /* (Tux): */
504
505   player_draw(&tux);
506
507   /* (Bullets): */
508
509   for (i = 0; i < num_bullets; ++i)
510     {
511       bullet_draw(&bullets[i]);
512     }
513
514   /* (Floating scores): */
515
516   for (i = 0; i < num_floating_scores; ++i)
517     {
518       floating_score_draw(&floating_scores[i]);
519     }
520
521
522   /* (Upgrades): */
523
524   for (i = 0; i < num_upgrades; ++i)
525     {
526       upgrade_draw(&upgrades[i]);
527     }
528
529
530   /* (Bouncy distros): */
531
532   for (i = 0; i < num_bouncy_distros; ++i)
533     {
534       bouncy_distro_draw(&bouncy_distros[i]);
535     }
536
537
538   /* (Broken bricks): */
539
540   for (i = 0; i < num_broken_bricks; ++i)
541     {
542       broken_brick_draw(&broken_bricks[i]);
543     }
544
545   drawstatus();
546
547
548   if(game_pause)
549     {
550       x = screen->h / 20;
551       for(i = 0; i < x; ++i)
552         {
553           fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1);
554         }
555       fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
556       text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
557     }
558
559   if(show_menu)
560     menu_process_current();
561
562   /* (Update it all!) */
563
564   updatescreen();
565
566
567 }
568
569 /* --- GAME LOOP! --- */
570
571 int gameloop(char * subset, int levelnb, int mode)
572 {
573   int fps_cnt, jump, done;
574   timer_type fps_timer, frame_timer;
575   timer_init(&fps_timer, YES);
576   timer_init(&frame_timer, YES);
577
578   game_started = YES;
579
580   st_gl_mode = mode;
581   level = levelnb;
582   strcpy(level_subset,subset);
583
584   /* Init the game: */
585   arrays_init();
586   set_defaults();
587
588   if(level_load(&current_level,level_subset,level) != 0)
589     exit(1);
590   level_load_gfx(&current_level);
591   activate_bad_guys();
592   level_load_song(&current_level);
593
594   player_init(&tux);
595
596   if(st_gl_mode != ST_GL_TEST)
597     load_hs();
598
599   loadshared();
600
601   if(st_gl_mode == ST_GL_PLAY)
602     levelintro();
603
604
605   timer_init(&time_left,YES);
606   start_timers();
607
608   if(st_gl_mode == ST_GL_LOAD_GAME)
609     loadgame(levelnb);
610
611
612   /* --- MAIN GAME LOOP!!! --- */
613
614   jump = NO;
615   done = 0;
616   quit = 0;
617   frame = 0;
618   game_pause = 0;
619   timer_init(&fps_timer,YES);
620   timer_init(&frame_timer,YES);
621   fps_cnt = 0;
622
623   /* Clear screen: */
624
625   clearscreen(0, 0, 0);
626   updatescreen();
627
628   /* Play music: */
629   play_current_music();
630
631
632   while (SDL_PollEvent(&event))
633   {}
634
635   game_draw();
636   do
637     {
638       jump = NO;
639
640       /* Calculate the movement-factor */
641       frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
642       if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
643       frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
644       
645       if(!timer_check(&frame_timer))
646         {
647           timer_start(&frame_timer,25);
648           ++frame;
649         }
650
651       /* Handle events: */
652
653       tux.input.old_fire = tux.input.fire;
654
655       game_event();
656
657       if(show_menu)
658         {
659           if(current_menu == &game_menu)
660             {
661               switch (menu_check(&game_menu))
662                 {
663                 case 2:
664                   st_pause_ticks_stop();
665                   break;
666                 case 3:
667                   update_load_save_game_menu(&save_game_menu, NO);
668                   break;
669                 case 4:
670                   update_load_save_game_menu(&load_game_menu, YES);
671                   break;
672                 case 7:
673                   st_pause_ticks_stop();
674                   done = 1;
675                   break;
676                 }
677             }
678           else if(current_menu == &options_menu)
679             {
680               process_options_menu();
681             }
682           else if(current_menu == &save_game_menu )
683             {
684               process_save_load_game_menu(YES);
685             }
686           else if(current_menu == &load_game_menu )
687             {
688               process_save_load_game_menu(NO);
689             }
690         }
691
692
693       /* Handle actions: */
694
695       if(!game_pause && !show_menu)
696         {
697         /*float z = frame_ratio;
698         frame_ratio = 1;
699         while(z >= 1)
700         {*/
701           if (game_action() == 0)
702             {
703               /* == 0: no more lives */
704               /* == -1: continues */
705               return 0;
706             }
707           /*  --z;
708             }*/
709         }
710       else
711         {
712           ++pause_menu_frame;
713           SDL_Delay(50);
714         }
715
716       if(debug_mode && debug_fps == YES)
717         SDL_Delay(60);
718
719       /*Draw the current scene to the screen */
720       /*If the machine running the game is too slow
721         skip the drawing of the frame (so the calculations are more precise and
722       the FPS aren't affected).*/
723       /*if( ! fps_fps < 50.0 )
724       game_draw();
725       else
726       jump = YES;*/ /*FIXME: Implement this tweak right.*/
727       game_draw();
728
729       /* Time stops in pause mode */
730       if(game_pause || show_menu )
731         {
732           continue;
733         }
734
735       /* Set the time of the last update and the time of the current update */
736       last_update_time = update_time;
737       update_time = st_get_ticks();
738
739
740       /* Pause till next frame, if the machine running the game is too fast: */
741       /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
742                 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
743       if(last_update_time >= update_time - 12 && jump != YES )
744         SDL_Delay(10);
745       /*if((update_time - last_update_time) < 10)
746           SDL_Delay((11 - (update_time - last_update_time))/2);*/
747
748
749
750       /* Handle time: */
751
752       if (timer_check(&time_left))
753         {
754           /* are we low on time ? */
755           if ((timer_get_left(&time_left) < TIME_WARNING)
756               && (get_current_music() != HURRYUP_MUSIC))     /* play the fast music */
757              {
758               set_current_music(HURRYUP_MUSIC);
759               play_current_music();
760              }
761
762         }
763       else
764         player_kill(&tux,KILL);
765
766
767       /* Calculate frames per second */
768       if(show_fps)
769         {
770           ++fps_cnt;
771           fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
772
773           if(!timer_check(&fps_timer))
774             {
775               timer_start(&fps_timer,1000);
776               fps_cnt = 0;
777             }
778         }
779
780     }
781   while (!done && !quit);
782
783   halt_music();
784
785   level_free_gfx();
786   level_free(&current_level);
787   level_free_song();
788   unloadshared();
789   arrays_free();
790
791   game_started = NO;
792
793   return(quit);
794 }
795
796
797 /* Load graphics/sounds shared between all levels: */
798
799 void loadshared(void)
800 {
801   int i;
802   char * herring_song_path; /* for loading herring song*/
803
804   /* Tuxes: */
805
806   texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
807   texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
808   texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
809
810   texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
811   texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
812   texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
813
814   texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
815   texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
816   texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
817
818   texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
819   texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
820   texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
821
822
823   texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
824                USE_ALPHA);
825
826   texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
827                USE_ALPHA);
828
829   texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
830                USE_ALPHA);
831
832   texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
833                USE_ALPHA);
834
835   texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
836                USE_ALPHA);
837
838   texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
839                USE_ALPHA);
840
841   texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
842                USE_ALPHA);
843
844   texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
845
846   texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
847                USE_ALPHA);
848
849   texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
850                USE_ALPHA);
851
852   texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
853                USE_ALPHA);
854
855   texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
856
857   texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
858                USE_ALPHA);
859
860   texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
861                USE_ALPHA);
862
863   texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
864                USE_ALPHA);
865
866   texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
867                USE_ALPHA);
868
869   texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
870                USE_ALPHA);
871
872   texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
873                USE_ALPHA);
874
875   texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
876                USE_ALPHA);
877
878   texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
879
880   texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
881                USE_ALPHA);
882
883   texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
884                USE_ALPHA);
885
886   texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
887                USE_ALPHA);
888
889   texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
890
891   texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
892                USE_ALPHA);
893
894   texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
895                USE_ALPHA);
896
897   texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
898                USE_ALPHA);
899
900   texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
901                USE_ALPHA);
902
903
904   texture_load(&ducktux_right ,DATA_PREFIX
905                "/images/shared/ducktux-right.png",
906                USE_ALPHA);
907
908   texture_load(&ducktux_left ,DATA_PREFIX
909                "/images/shared/ducktux-left.png",
910                USE_ALPHA);
911
912   texture_load(&skidtux_right ,DATA_PREFIX
913                "/images/shared/skidtux-right.png",
914                USE_ALPHA);
915
916   texture_load(&skidtux_left ,DATA_PREFIX
917                "/images/shared/skidtux-left.png",
918                USE_ALPHA);
919
920   texture_load(&duckfiretux_right ,DATA_PREFIX
921                "/images/shared/duckfiretux-right.png",
922                USE_ALPHA);
923
924   texture_load(&duckfiretux_left ,DATA_PREFIX
925                "/images/shared/duckfiretux-left.png",
926                USE_ALPHA);
927
928   texture_load(&skidfiretux_right ,DATA_PREFIX
929                "/images/shared/skidfiretux-right.png",
930                USE_ALPHA);
931
932   texture_load(&skidfiretux_left ,DATA_PREFIX
933                "/images/shared/skidfiretux-left.png",
934                USE_ALPHA);
935
936
937   /* Boxes: */
938
939   texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
940                IGNORE_ALPHA);
941   texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
942                IGNORE_ALPHA);
943
944
945   /* Water: */
946
947
948   texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
949
950   texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
951                USE_ALPHA);
952
953   texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
954                USE_ALPHA);
955
956   texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
957                USE_ALPHA);
958
959
960   /* Pole: */
961
962   texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
963   texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
964                USE_ALPHA);
965
966
967   /* Flag: */
968
969   texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
970                USE_ALPHA);
971   texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
972                USE_ALPHA);
973
974
975   /* Cloud: */
976
977   texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
978                USE_ALPHA);
979
980   texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
981                USE_ALPHA);
982
983   texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
984                USE_ALPHA);
985
986   texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
987                USE_ALPHA);
988
989
990   texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
991                USE_ALPHA);
992
993   texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
994                USE_ALPHA);
995
996   texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
997                USE_ALPHA);
998
999   texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
1000                USE_ALPHA);
1001
1002
1003   /* Bad guys: */
1004
1005   /* (BSOD) */
1006
1007   texture_load(&img_bsod_left[0] ,DATA_PREFIX
1008                "/images/shared/bsod-left-0.png",
1009                USE_ALPHA);
1010
1011   texture_load(&img_bsod_left[1] ,DATA_PREFIX
1012                "/images/shared/bsod-left-1.png",
1013                USE_ALPHA);
1014
1015   texture_load(&img_bsod_left[2] ,DATA_PREFIX
1016                "/images/shared/bsod-left-2.png",
1017                USE_ALPHA);
1018
1019   texture_load(&img_bsod_left[3] ,DATA_PREFIX
1020                "/images/shared/bsod-left-3.png",
1021                USE_ALPHA);
1022
1023   texture_load(&img_bsod_right[0] ,DATA_PREFIX
1024                "/images/shared/bsod-right-0.png",
1025                USE_ALPHA);
1026
1027   texture_load(&img_bsod_right[1] ,DATA_PREFIX
1028                "/images/shared/bsod-right-1.png",
1029                USE_ALPHA);
1030
1031   texture_load(&img_bsod_right[2] ,DATA_PREFIX
1032                "/images/shared/bsod-right-2.png",
1033                USE_ALPHA);
1034
1035   texture_load(&img_bsod_right[3] ,DATA_PREFIX
1036                "/images/shared/bsod-right-3.png",
1037                USE_ALPHA);
1038
1039   texture_load(&img_bsod_squished_left ,DATA_PREFIX
1040                "/images/shared/bsod-squished-left.png",
1041                USE_ALPHA);
1042
1043   texture_load(&img_bsod_squished_right ,DATA_PREFIX
1044                "/images/shared/bsod-squished-right.png",
1045                USE_ALPHA);
1046
1047   texture_load(&img_bsod_falling_left ,DATA_PREFIX
1048                "/images/shared/bsod-falling-left.png",
1049                USE_ALPHA);
1050
1051   texture_load(&img_bsod_falling_right ,DATA_PREFIX
1052                "/images/shared/bsod-falling-right.png",
1053                USE_ALPHA);
1054
1055
1056   /* (Laptop) */
1057
1058   texture_load(&img_laptop_left[0] ,DATA_PREFIX
1059                "/images/shared/laptop-left-0.png",
1060                USE_ALPHA);
1061
1062   texture_load(&img_laptop_left[1] ,DATA_PREFIX
1063                "/images/shared/laptop-left-1.png",
1064                USE_ALPHA);
1065
1066   texture_load(&img_laptop_left[2] ,DATA_PREFIX
1067                "/images/shared/laptop-left-2.png",
1068                USE_ALPHA);
1069
1070   texture_load(&img_laptop_right[0] ,DATA_PREFIX
1071                "/images/shared/laptop-right-0.png",
1072                USE_ALPHA);
1073
1074   texture_load(&img_laptop_right[1] ,DATA_PREFIX
1075                "/images/shared/laptop-right-1.png",
1076                USE_ALPHA);
1077
1078   texture_load(&img_laptop_right[2] ,DATA_PREFIX
1079                "/images/shared/laptop-right-2.png",
1080                USE_ALPHA);
1081
1082   texture_load(&img_laptop_flat_left ,DATA_PREFIX
1083                "/images/shared/laptop-flat-left.png",
1084                USE_ALPHA);
1085
1086   texture_load(&img_laptop_flat_right ,DATA_PREFIX
1087                "/images/shared/laptop-flat-right.png",
1088                USE_ALPHA);
1089
1090   texture_load(&img_laptop_falling_left ,DATA_PREFIX
1091                "/images/shared/laptop-falling-left.png",
1092                USE_ALPHA);
1093
1094   texture_load(&img_laptop_falling_right ,DATA_PREFIX
1095                "/images/shared/laptop-falling-right.png",
1096                USE_ALPHA);
1097
1098
1099   /* (Money) */
1100
1101   texture_load(&img_money_left[0] ,DATA_PREFIX
1102                "/images/shared/bag-left-0.png",
1103                USE_ALPHA);
1104
1105   texture_load(&img_money_left[1] ,DATA_PREFIX
1106                "/images/shared/bag-left-1.png",
1107                USE_ALPHA);
1108
1109   texture_load(&img_money_right[0] ,DATA_PREFIX
1110                "/images/shared/bag-right-0.png",
1111                USE_ALPHA);
1112
1113   texture_load(&img_money_right[1] ,DATA_PREFIX
1114                "/images/shared/bag-right-1.png",
1115                USE_ALPHA);
1116
1117
1118
1119   /* Upgrades: */
1120
1121   texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1122   texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1123
1124
1125   /* Weapons: */
1126
1127   texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1128
1129   texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1130                USE_ALPHA);
1131
1132
1133
1134   /* Distros: */
1135
1136   texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1137                USE_ALPHA);
1138
1139   texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1140                USE_ALPHA);
1141
1142   texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1143                USE_ALPHA);
1144
1145   texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1146                USE_ALPHA);
1147
1148
1149   /* Tux life: */
1150
1151   texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1152                USE_ALPHA);
1153
1154   /* Herring: */
1155
1156   texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1157                USE_ALPHA);
1158
1159
1160   /* Super background: */
1161
1162   texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1163                IGNORE_ALPHA);
1164
1165
1166   /* Sound effects: */
1167
1168   /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1169                     // initialize sounds[i] with the correct pointer's value:
1170                     // NULL or something else. And it will be dangerous to
1171                     // play with not-initialized pointers.
1172                     // This is also true with if (use_music)
1173      Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1174   */
1175   for (i = 0; i < NUM_SOUNDS; i++)
1176     sounds[i] = load_sound(soundfilenames[i]);
1177
1178   /* Herring song */
1179   herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1180                                       strlen("SALCON.MOD") + 8));
1181
1182   sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1183
1184   herring_song = load_song(herring_song_path);
1185
1186   free(herring_song_path);
1187
1188 }
1189
1190
1191 /* Free shared data: */
1192
1193 void unloadshared(void)
1194 {
1195   int i;
1196
1197   for (i = 0; i < 3; i++)
1198     {
1199       texture_free(&tux_right[i]);
1200       texture_free(&tux_left[i]);
1201       texture_free(&bigtux_right[i]);
1202       texture_free(&bigtux_left[i]);
1203     }
1204
1205   texture_free(&bigtux_right_jump);
1206   texture_free(&bigtux_left_jump);
1207
1208   for (i = 0; i < 2; i++)
1209     {
1210       texture_free(&cape_right[i]);
1211       texture_free(&cape_left[i]);
1212       texture_free(&bigcape_right[i]);
1213       texture_free(&bigcape_left[i]);
1214     }
1215
1216   texture_free(&ducktux_left);
1217   texture_free(&ducktux_right);
1218
1219   texture_free(&skidtux_left);
1220   texture_free(&skidtux_right);
1221
1222   for (i = 0; i < 4; i++)
1223     {
1224       texture_free(&img_bsod_left[i]);
1225       texture_free(&img_bsod_right[i]);
1226     }
1227
1228   texture_free(&img_bsod_squished_left);
1229   texture_free(&img_bsod_squished_right);
1230
1231   texture_free(&img_bsod_falling_left);
1232   texture_free(&img_bsod_falling_right);
1233
1234   for (i = 0; i < 3; i++)
1235     {
1236       texture_free(&img_laptop_left[i]);
1237       texture_free(&img_laptop_right[i]);
1238     }
1239
1240   texture_free(&img_laptop_flat_left);
1241   texture_free(&img_laptop_flat_right);
1242
1243   texture_free(&img_laptop_falling_left);
1244   texture_free(&img_laptop_falling_right);
1245
1246   for (i = 0; i < 2; i++)
1247     {
1248       texture_free(&img_money_left[i]);
1249       texture_free(&img_money_right[i]);
1250     }
1251
1252   texture_free(&img_box_full);
1253   texture_free(&img_box_empty);
1254
1255   texture_free(&img_water);
1256   for (i = 0; i < 3; i++)
1257     texture_free(&img_waves[i]);
1258
1259   texture_free(&img_pole);
1260   texture_free(&img_poletop);
1261
1262   for (i = 0; i < 2; i++)
1263     texture_free(&img_flag[i]);
1264
1265   texture_free(&img_mints);
1266   texture_free(&img_coffee);
1267
1268   for (i = 0; i < 4; i++)
1269     {
1270       texture_free(&img_distro[i]);
1271       texture_free(&img_cloud[0][i]);
1272       texture_free(&img_cloud[1][i]);
1273     }
1274
1275   texture_free(&img_golden_herring);
1276
1277   for (i = 0; i < NUM_SOUNDS; i++)
1278     free_chunk(sounds[i]);
1279
1280   /* free the herring song */
1281   free_music( herring_song );
1282 }
1283
1284
1285 /* Draw a tile on the screen: */
1286
1287 void drawshape(float x, float y, unsigned char c)
1288 {
1289   int z;
1290
1291   if (c == 'X' || c == 'x')
1292     texture_draw(&img_brick[0], x, y, NO_UPDATE);
1293   else if (c == 'Y' || c == 'y')
1294     texture_draw(&img_brick[1], x, y, NO_UPDATE);
1295   else if (c == 'A' || c =='B' || c == '!')
1296     texture_draw(&img_box_full, x, y, NO_UPDATE);
1297   else if (c == 'a')
1298     texture_draw(&img_box_empty, x, y, NO_UPDATE);
1299   else if (c >= 'C' && c <= 'F')
1300     texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1301   else if (c >= 'c' && c <= 'f')
1302     texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1303   else if (c >= 'G' && c <= 'J')
1304     texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1305   else if (c >= 'g' && c <= 'j')
1306     texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1307   else if (c == '#')
1308     texture_draw(&img_solid[0], x, y, NO_UPDATE);
1309   else if (c == '[')
1310     texture_draw(&img_solid[1], x, y, NO_UPDATE);
1311   else if (c == '=')
1312     texture_draw(&img_solid[2], x, y, NO_UPDATE);
1313   else if (c == ']')
1314     texture_draw(&img_solid[3], x, y, NO_UPDATE);
1315   else if (c == '$')
1316     {
1317
1318       z = (frame / 2) % 6;
1319
1320       if (z < 4)
1321         texture_draw(&img_distro[z], x, y, NO_UPDATE);
1322       else if (z == 4)
1323         texture_draw(&img_distro[2], x, y, NO_UPDATE);
1324       else if (z == 5)
1325         texture_draw(&img_distro[1], x, y, NO_UPDATE);
1326     }
1327   else if (c == '^')
1328     {
1329       z = (frame / 3) % 3;
1330
1331       texture_draw(&img_waves[z], x, y, NO_UPDATE);
1332     }
1333   else if (c == '*')
1334     texture_draw(&img_poletop, x, y, NO_UPDATE);
1335   else if (c == '|')
1336     {
1337       texture_draw(&img_pole, x, y, NO_UPDATE);
1338
1339     }
1340   else if (c == '\\')
1341     {
1342       z = (frame / 3) % 2;
1343
1344       texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1345     }
1346   else if (c == '&')
1347     texture_draw(&img_water, x, y, NO_UPDATE);
1348 }
1349
1350
1351 /* What shape is at some position? */
1352
1353 unsigned char shape(float x, float y)
1354 {
1355
1356   int xx, yy;
1357   unsigned char c;
1358
1359   yy = ((int)y / 32);
1360   xx = ((int)x / 32);
1361
1362   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1363     {
1364       c = current_level.tiles[yy][xx];
1365     }
1366   else
1367     c = '.';
1368
1369   return(c);
1370 }
1371
1372 /* Is is ground? */
1373
1374
1375 int issolid(float x, float y)
1376 {
1377   if (isbrick(x, y) ||
1378       isice(x, y) ||
1379       (shape(x, y) == '[') ||
1380       (shape(x, y) == '=') ||
1381       (shape(x, y) == ']') ||
1382       (shape(x, y) == 'A') ||
1383       (shape(x, y) == 'B') ||
1384       (shape(x, y) == '!') ||
1385       (shape(x, y) == 'a'))
1386     {
1387       return YES;
1388     }
1389
1390   return NO;
1391 }
1392
1393
1394 /* Is it a brick? */
1395
1396 int isbrick(float x, float y)
1397 {
1398   if (shape(x, y) == 'X' ||
1399       shape(x, y) == 'x' ||
1400       shape(x, y) == 'Y' ||
1401       shape(x, y) == 'y')
1402     {
1403       return YES;
1404     }
1405
1406   return NO;
1407 }
1408
1409
1410 /* Is it ice? */
1411
1412 int isice(float x, float y)
1413 {
1414   if (shape(x, y) == '#')
1415     {
1416       return YES;
1417     }
1418
1419   return NO;
1420 }
1421
1422
1423 /* Is it a full box? */
1424
1425 int isfullbox(float x, float y)
1426 {
1427   if (shape(x, y) == 'A' ||
1428       shape(x, y) == 'B' ||
1429       shape(x, y) == '!')
1430     {
1431       return YES;
1432     }
1433
1434   return NO;
1435 }
1436
1437 /* Break a brick: */
1438
1439 void trybreakbrick(float x, float y)
1440 {
1441   if (isbrick(x, y))
1442     {
1443       if (shape(x, y) == 'x' || shape(x, y) == 'y')
1444         {
1445           /* Get a distro from it: */
1446
1447           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1448                             (int)(y / 32) * 32);
1449
1450           if (counting_distros == NO)
1451             {
1452               counting_distros = YES;
1453               distro_counter = 50;
1454             }
1455
1456           if (distro_counter <= 0)
1457             level_change(&current_level,x, y, 'a');
1458
1459           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1460           score = score + SCORE_DISTRO;
1461           distros++;
1462         }
1463       else
1464         {
1465           /* Get rid of it: */
1466
1467           level_change(&current_level,x, y,'.');
1468         }
1469
1470
1471       /* Replace it with broken bits: */
1472
1473       add_broken_brick(((int)(x + 1) / 32) * 32,
1474                        (int)(y / 32) * 32);
1475
1476
1477       /* Get some score: */
1478
1479       play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1480       score = score + SCORE_BRICK;
1481     }
1482 }
1483
1484
1485 /* Bounce a brick: */
1486
1487 void bumpbrick(float x, float y)
1488 {
1489   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1490                    (int)(y / 32) * 32);
1491
1492   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1493
1494 }
1495
1496
1497 /* Empty a box: */
1498
1499 void tryemptybox(float x, float y, int col_side)
1500 {
1501 if (!isfullbox(x, y))
1502   return;
1503
1504 // according to the collision side, set the upgrade direction
1505
1506 if(col_side == LEFT)
1507   col_side = RIGHT;
1508 else
1509   col_side = LEFT;
1510
1511 switch(shape(x,y))
1512   {
1513   case 'A':      /* Box with a distro! */
1514     add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1515     play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1516     score = score + SCORE_DISTRO;
1517     distros++;
1518     break;
1519   case 'B':      /* Add an upgrade! */
1520     if (tux.size == SMALL)     /* Tux is small, add mints! */
1521       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1522     else     /* Tux is big, add coffee: */
1523       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1524     play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1525     break;
1526   case '!':     /* Add a golden herring */
1527     add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1528     break;
1529   default:
1530     break;
1531   }
1532
1533 /* Empty the box: */
1534 level_change(&current_level,x, y, 'a');
1535 }
1536
1537
1538 /* Try to grab a distro: */
1539
1540 void trygrabdistro(float x, float y, int bounciness)
1541 {
1542   if (shape(x, y) == '$')
1543     {
1544       level_change(&current_level,x, y, '.');
1545       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1546
1547       if (bounciness == BOUNCE)
1548         {
1549           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1550                             (int)(y / 32) * 32);
1551         }
1552
1553       score = score + SCORE_DISTRO;
1554       distros++;
1555     }
1556 }
1557
1558 /* Try to bump a bad guy from below: */
1559
1560 void trybumpbadguy(float x, float y)
1561 {
1562   int i;
1563
1564
1565   /* Bad guys: */
1566
1567   for (i = 0; i < num_bad_guys; i++)
1568     {
1569       if (bad_guys[i].base.alive &&
1570           bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1571           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1572         {
1573           if (bad_guys[i].kind == BAD_BSOD ||
1574               bad_guys[i].kind == BAD_LAPTOP)
1575             {
1576               bad_guys[i].dying = FALLING;
1577               bad_guys[i].base.ym = -8;
1578               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1579             }
1580         }
1581     }
1582
1583
1584   /* Upgrades: */
1585
1586   for (i = 0; i < num_upgrades; i++)
1587     {
1588       if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1589           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1590           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1591         {
1592           upgrades[i].base.xm = -upgrades[i].base.xm;
1593           upgrades[i].base.ym = -8;
1594           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1595         }
1596     }
1597 }
1598
1599 /* (Status): */
1600 void drawstatus(void)
1601 {
1602   int i;
1603
1604   sprintf(str, "%d", score);
1605   text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1606   text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1607
1608   if(st_gl_mode != ST_GL_TEST)
1609     {
1610       sprintf(str, "%d", hs_score);
1611       text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1612       text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1613     }
1614   else
1615     {
1616       text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1617     }
1618
1619   if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1620     {
1621       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1622       text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1623       text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1624     }
1625
1626   sprintf(str, "%d", distros);
1627   text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1628   text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1629
1630   text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1631
1632   if(show_fps)
1633     {
1634       sprintf(str, "%2.1f", fps_fps);
1635       text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1636       text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1637     }
1638
1639   for(i=0; i < tux.lives; ++i)
1640     {
1641       texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1642     }
1643 }
1644
1645
1646 void drawendscreen(void)
1647 {
1648   char str[80];
1649
1650   clearscreen(0, 0, 0);
1651
1652   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1653
1654   sprintf(str, "SCORE: %d", score);
1655   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1656
1657   sprintf(str, "DISTROS: %d", distros);
1658   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1659
1660   flipscreen();
1661   SDL_Delay(2000);
1662 }
1663
1664 void drawresultscreen(void)
1665 {
1666   char str[80];
1667
1668   clearscreen(0, 0, 0);
1669
1670   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1671
1672   sprintf(str, "SCORE: %d", score);
1673   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1674
1675   sprintf(str, "DISTROS: %d", distros);
1676   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1677
1678   flipscreen();
1679   SDL_Delay(2000);
1680 }
1681
1682 void savegame(int slot)
1683 {
1684   char savefile[1024];
1685   FILE* fi;
1686   unsigned int ui;
1687
1688   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1689
1690   fi = fopen(savefile, "wb");
1691
1692   if (fi == NULL)
1693     {
1694       fprintf(stderr, "Warning: I could not open the slot file ");
1695
1696     }
1697   else
1698     {
1699       fputs(level_subset, fi);
1700       fputs("\n", fi);
1701       fwrite(&level,sizeof(int),1,fi);
1702       fwrite(&score,sizeof(int),1,fi);
1703       fwrite(&distros,sizeof(int),1,fi);
1704       fwrite(&scroll_x,sizeof(float),1,fi);
1705       fwrite(&tux,sizeof(player_type),1,fi);
1706       timer_fwrite(&tux.invincible_timer,fi);
1707       timer_fwrite(&tux.skidding_timer,fi);
1708       timer_fwrite(&tux.safe_timer,fi);
1709       timer_fwrite(&tux.frame_timer,fi);
1710       timer_fwrite(&time_left,fi);
1711       ui = st_get_ticks();
1712       fwrite(&ui,sizeof(int),1,fi);
1713     }
1714   fclose(fi);
1715
1716 }
1717
1718 void loadgame(int slot)
1719 {
1720   char savefile[1024];
1721   char str[100];
1722   FILE* fi;
1723   unsigned int ui;
1724
1725   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1726
1727   fi = fopen(savefile, "rb");
1728
1729   if (fi == NULL)
1730     {
1731       fprintf(stderr, "Warning: I could not open the slot file ");
1732
1733     }
1734   else
1735     {
1736
1737
1738       fgets(str, 100, fi);
1739       strcpy(level_subset, str);
1740       level_subset[strlen(level_subset)-1] = '\0';
1741       fread(&level,sizeof(int),1,fi);
1742
1743       set_defaults();
1744       level_free(&current_level);
1745       if(level_load(&current_level,level_subset,level) != 0)
1746         exit(1);
1747       arrays_free();
1748       arrays_init();
1749       activate_bad_guys();
1750       level_free_gfx();
1751       level_load_gfx(&current_level);
1752       level_free_song();
1753       level_load_song(&current_level);
1754       levelintro();
1755       update_time = st_get_ticks();
1756
1757       fread(&score,sizeof(int),1,fi);
1758       fread(&distros,sizeof(int),1,fi);
1759       fread(&scroll_x,sizeof(float),1,fi);
1760       fread(&tux,sizeof(player_type),1,fi);
1761       timer_fread(&tux.invincible_timer,fi);
1762       timer_fread(&tux.skidding_timer,fi);
1763       timer_fread(&tux.safe_timer,fi);
1764       timer_fread(&tux.frame_timer,fi);
1765       timer_fread(&time_left,fi);
1766       fread(&ui,sizeof(int),1,fi);
1767       tux.hphysic.start_time += st_get_ticks() - ui;
1768       tux.vphysic.start_time += st_get_ticks() - ui;
1769       fclose(fi);
1770     }
1771
1772 }
1773
1774 void slotinfo(char **pinfo, int slot)
1775 {
1776   FILE* fi;
1777   char slotfile[1024];
1778   char tmp[200];
1779   char str[5];
1780   int slot_level;
1781   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1782
1783   fi = fopen(slotfile, "rb");
1784
1785   sprintf(tmp,"Slot %d - ",slot);
1786
1787   if (fi == NULL)
1788     {
1789       strcat(tmp,"Free");
1790     }
1791   else
1792     {
1793       fgets(str, 100, fi);
1794       str[strlen(str)-1] = '\0';
1795       strcat(tmp, str);
1796       strcat(tmp, " / Level:");
1797       fread(&slot_level,sizeof(int),1,fi);
1798       sprintf(str,"%d",slot_level);
1799       strcat(tmp,str);
1800       fclose(fi);
1801     }
1802
1803   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1804   strcpy(*pinfo,tmp);
1805
1806 }
1807