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