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