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