- made TileManager::get() always return a valid tile
[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   if (c != 0)
1322     {
1323       Tile* ptile = TileManager::instance()->get(c);
1324       if(ptile)
1325         {
1326           if(ptile->images.size() > 1)
1327             {
1328               texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y);
1329             }
1330           else if (ptile->images.size() == 1)
1331             {
1332               texture_draw(&ptile->images[0],x,y);
1333             }
1334           else
1335             {
1336               printf("Tile not dravable %u\n", c);
1337             }
1338         }
1339     }
1340
1341   /*
1342   if (c == 'X' || c == 'x')
1343     texture_draw(&img_brick[0], x, y);
1344   else if (c == 'Y' || c == 'y')
1345     texture_draw(&img_brick[1], x, y);
1346   else if (c == 'A' || c =='B' || c == '!')
1347     texture_draw(&img_box_full, x, y);
1348   else if (c == 'a')
1349     texture_draw(&img_box_empty, x, y);
1350   else if (c >= 'C' && c <= 'F')
1351     texture_draw(&img_cloud[0][c - 'C'], x, y);
1352   else if (c >= 'c' && c <= 'f')
1353     texture_draw(&img_cloud[1][c - 'c'], x, y);
1354   else if (c >= 'G' && c <= 'J')
1355     texture_draw(&img_bkgd_tile[0][c - 'G'], x, y);
1356   else if (c >= 'g' && c <= 'j')
1357     texture_draw(&img_bkgd_tile[1][c - 'g'], x, y);
1358   else if (c == '#')
1359     texture_draw(&img_solid[0], x, y);
1360   else if (c == '[')
1361     texture_draw(&img_solid[1], x, y);
1362   else if (c == '=')
1363     texture_draw(&img_solid[2], x, y);
1364   else if (c == ']')
1365     texture_draw(&img_solid[3], x, y);
1366   else if (c == '$')
1367     {
1368       z = (global_frame_counter / 2) % 6;
1369
1370       if (z < 4)
1371         texture_draw(&img_distro[z], x, y);
1372       else if (z == 4)
1373         texture_draw(&img_distro[2], x, y);
1374       else if (z == 5)
1375         texture_draw(&img_distro[1], x, y);
1376     }
1377   else if (c == '^')
1378     {
1379       z = (global_frame_counter / 3) % 3;
1380
1381       texture_draw(&img_waves[z], x, y);
1382     }
1383   else if (c == '*')
1384     texture_draw(&img_poletop, x, y);
1385   else if (c == '|')
1386     {
1387       texture_draw(&img_pole, x, y);
1388
1389     }
1390   else if (c == '\\')
1391     {
1392       z = (global_frame_counter / 3) % 2;
1393
1394       texture_draw(&img_flag[z], x + 16, y);
1395     }
1396   else if (c == '&')
1397     texture_draw(&img_water, x, y);*/
1398
1399 }
1400
1401
1402 /* What shape is at some position? */
1403 unsigned int shape(float x, float y)
1404 {
1405
1406   int xx, yy;
1407   unsigned int c;
1408
1409   yy = ((int)y / 32);
1410   xx = ((int)x / 32);
1411
1412   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1413     {
1414       c = current_level.ia_tiles[yy][xx];
1415     }
1416   else
1417     c = '.';
1418
1419   return(c);
1420 }
1421
1422 Tile* gettile(float x, float y)
1423 {
1424   return TileManager::instance()->get(shape(x, y));
1425 }
1426
1427 /* Is is ground? */
1428
1429
1430 bool issolid(float x, float y)
1431 {
1432   Tile* tile = TileManager::instance()->get
1433                (shape(x,y));
1434   if(tile)
1435     {
1436       if(tile->solid == true)
1437         return true;
1438       else
1439         return false;
1440     }
1441   else
1442     {
1443       return false;
1444     }
1445 }
1446
1447 /* Is it a brick? */
1448
1449 bool isbrick(float x, float y)
1450 {
1451   Tile* tile = TileManager::instance()->get
1452                (shape(x,y));
1453   if(tile)
1454     {
1455       if(tile->brick == true)
1456         return true;
1457       else
1458         return false;
1459     }
1460   else
1461     {
1462       return false;
1463     }
1464 }
1465
1466
1467 /* Is it ice? */
1468
1469 bool isice(float x, float y)
1470 {
1471   Tile* tile = TileManager::instance()->get
1472                (shape(x,y));
1473   if(tile)
1474     {
1475       if(tile->ice == true)
1476         return true;
1477       else
1478         return false;
1479     }
1480   else
1481     {
1482       return false;
1483     }
1484 }
1485
1486 /* Is it a full box? */
1487
1488 bool isfullbox(float x, float y)
1489 {
1490   Tile* tile = TileManager::instance()->get
1491                (shape(x,y));
1492   if(tile)
1493     {
1494       if(tile->fullbox == true)
1495         return true;
1496       else
1497         return false;
1498     }
1499   else
1500     {
1501       return false;
1502     }
1503 }
1504
1505 bool isdistro(float x, float y)
1506 {
1507   Tile* tile = TileManager::instance()->get(shape(x,y));
1508   return tile && tile->distro;
1509 }
1510
1511 /* Break a brick: */
1512
1513 void trybreakbrick(float x, float y)
1514 {
1515   Tile* tile = gettile(x, y);
1516   if (tile->brick)
1517     {
1518       if (tile->data > 0)
1519         {
1520           /* Get a distro from it: */
1521           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1522                             (int)(y / 32) * 32);
1523
1524           if (!counting_distros)
1525             {
1526               counting_distros = true;
1527               distro_counter = 50;
1528             }
1529
1530           if (distro_counter <= 0)
1531             level_change(&current_level,x, y, TM_IA, tile->next_tile2);
1532
1533           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1534           score = score + SCORE_DISTRO;
1535           distros++;
1536         }
1537       else
1538         {
1539           /* Get rid of it: */
1540           level_change(&current_level,x, y, TM_IA, tile->next_tile);
1541         }
1542
1543
1544       /* Replace it with broken bits: */
1545
1546       add_broken_brick(((int)(x + 1) / 32) * 32,
1547                        (int)(y / 32) * 32);
1548
1549
1550       /* Get some score: */
1551
1552       play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1553       score = score + SCORE_BRICK;
1554     }
1555 }
1556
1557
1558 /* Bounce a brick: */
1559
1560 void bumpbrick(float x, float y)
1561 {
1562   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1563                    (int)(y / 32) * 32);
1564
1565   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1566
1567 }
1568
1569
1570 /* Empty a box: */
1571
1572 void tryemptybox(float x, float y, int col_side)
1573 {
1574   Tile* tile = gettile(x,y);
1575   if (!tile->fullbox)
1576     return;
1577
1578   // according to the collision side, set the upgrade direction
1579
1580   if(col_side == LEFT)
1581     col_side = RIGHT;
1582   else
1583     col_side = LEFT;
1584
1585   // FIXME: Content of boxes must be handled otherwise
1586   switch(tile->data)
1587     {
1588     case 1: //'A':      /* Box with a distro! */
1589       add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1590       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1591       score = score + SCORE_DISTRO;
1592       distros++;
1593       break;
1594     case 2: // 'B':      /* Add an upgrade! */
1595       if (tux.size == SMALL)     /* Tux is small, add mints! */
1596         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1597       else     /* Tux is big, add coffee: */
1598         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1599       play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1600       break;
1601     case 3:// '!':     /* Add a golden herring */
1602       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1603       break;
1604     default:
1605       break;
1606     }
1607
1608   /* Empty the box: */
1609   level_change(&current_level,x, y, TM_IA, tile->next_tile);
1610 }
1611
1612
1613 /* Try to grab a distro: */
1614
1615 void trygrabdistro(float x, float y, int bounciness)
1616 {
1617   Tile* tile = gettile(x, y);
1618   if (tile && tile->distro)
1619     {
1620       level_change(&current_level,x, y, TM_IA, tile->next_tile);
1621       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1622
1623       if (bounciness == BOUNCE)
1624         {
1625           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1626                             (int)(y / 32) * 32);
1627         }
1628
1629       score = score + SCORE_DISTRO;
1630       distros++;
1631     }
1632 }
1633
1634 /* Try to bump a bad guy from below: */
1635
1636 void trybumpbadguy(float x, float y)
1637 {
1638   unsigned int i;
1639
1640   /* Bad guys: */
1641   for (i = 0; i < bad_guys.size(); i++)
1642     {
1643       if (bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1644           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1645         {
1646           if (bad_guys[i].kind == BAD_BSOD ||
1647               bad_guys[i].kind == BAD_LAPTOP)
1648             {
1649               bad_guys[i].dying = DYING_FALLING;
1650               bad_guys[i].base.ym = -8;
1651               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1652             }
1653         }
1654     }
1655
1656
1657   /* Upgrades: */
1658   for (i = 0; i < upgrades.size(); i++)
1659     {
1660       if (upgrades[i].base.height == 32 &&
1661           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1662           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1663         {
1664           upgrades[i].base.xm = -upgrades[i].base.xm;
1665           upgrades[i].base.ym = -8;
1666           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1667         }
1668     }
1669 }
1670
1671 /* (Status): */
1672 void drawstatus(void)
1673 {
1674   char str[60];
1675
1676   sprintf(str, "%d", score);
1677   text_draw(&white_text, "SCORE", 0, 0, 1);
1678   text_draw(&gold_text, str, 96, 0, 1);
1679
1680   if(st_gl_mode != ST_GL_TEST)
1681     {
1682       sprintf(str, "%d", hs_score);
1683       text_draw(&white_text, "HIGH", 0, 20, 1);
1684       text_draw(&gold_text, str, 96, 20, 1);
1685     }
1686   else
1687     {
1688       text_draw(&white_text,"Press ESC To Return",0,20,1);
1689     }
1690
1691   if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1692     {
1693       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1694       text_draw(&white_text, "TIME", 224, 0, 1);
1695       text_draw(&gold_text, str, 304, 0, 1);
1696     }
1697
1698   sprintf(str, "%d", distros);
1699   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1700   text_draw(&gold_text, str, 608, 0, 1);
1701
1702   text_draw(&white_text, "LIVES", screen->h, 20, 1);
1703
1704   if(show_fps)
1705     {
1706       sprintf(str, "%2.1f", fps_fps);
1707       text_draw(&white_text, "FPS", screen->h, 40, 1);
1708       text_draw(&gold_text, str, screen->h + 60, 40, 1);
1709     }
1710
1711   for(int i=0; i < tux.lives; ++i)
1712     {
1713       texture_draw(&tux_life,565+(18*i),20);
1714     }
1715 }
1716
1717
1718 void drawendscreen(void)
1719 {
1720   char str[80];
1721
1722   clearscreen(0, 0, 0);
1723
1724   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1725
1726   sprintf(str, "SCORE: %d", score);
1727   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1728
1729   sprintf(str, "DISTROS: %d", distros);
1730   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1731
1732   flipscreen();
1733   SDL_Delay(2000);
1734 }
1735
1736 void drawresultscreen(void)
1737 {
1738   char str[80];
1739
1740   clearscreen(0, 0, 0);
1741
1742   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1743
1744   sprintf(str, "SCORE: %d", score);
1745   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1746
1747   sprintf(str, "DISTROS: %d", distros);
1748   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1749
1750   flipscreen();
1751   SDL_Delay(2000);
1752 }
1753
1754 void savegame(int slot)
1755 {
1756   char savefile[1024];
1757   FILE* fi;
1758   unsigned int ui;
1759
1760   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1761
1762   fi = fopen(savefile, "wb");
1763
1764   if (fi == NULL)
1765     {
1766       fprintf(stderr, "Warning: I could not open the slot file ");
1767
1768     }
1769   else
1770     {
1771       fputs(level_subset, fi);
1772       fputs("\n", fi);
1773       fwrite(&level,sizeof(int),1,fi);
1774       fwrite(&score,sizeof(int),1,fi);
1775       fwrite(&distros,sizeof(int),1,fi);
1776       fwrite(&scroll_x,sizeof(float),1,fi);
1777       fwrite(&tux,sizeof(Player),1,fi);
1778       timer_fwrite(&tux.invincible_timer,fi);
1779       timer_fwrite(&tux.skidding_timer,fi);
1780       timer_fwrite(&tux.safe_timer,fi);
1781       timer_fwrite(&tux.frame_timer,fi);
1782       timer_fwrite(&time_left,fi);
1783       ui = st_get_ticks();
1784       fwrite(&ui,sizeof(int),1,fi);
1785     }
1786   fclose(fi);
1787
1788 }
1789
1790 void loadgame(int slot)
1791 {
1792   char savefile[1024];
1793   char str[100];
1794   FILE* fi;
1795   unsigned int ui;
1796
1797   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1798
1799   fi = fopen(savefile, "rb");
1800
1801   if (fi == NULL)
1802     {
1803       fprintf(stderr, "Warning: I could not open the slot file ");
1804
1805     }
1806   else
1807     {
1808       fgets(str, 100, fi);
1809       strcpy(level_subset, str);
1810       level_subset[strlen(level_subset)-1] = '\0';
1811       fread(&level,sizeof(int),1,fi);
1812
1813       set_defaults();
1814       level_free(&current_level);
1815       if(level_load(&current_level,level_subset,level) != 0)
1816         exit(1);
1817       arrays_free();
1818       arrays_init();
1819       activate_bad_guys();
1820       activate_particle_systems();
1821       level_free_gfx();
1822       level_load_gfx(&current_level);
1823       level_free_song();
1824       level_load_song(&current_level);
1825       levelintro();
1826       update_time = st_get_ticks();
1827
1828       fread(&score,sizeof(int),1,fi);
1829       fread(&distros,sizeof(int),1,fi);
1830       fread(&scroll_x,sizeof(float),1,fi);
1831       fread(&tux, sizeof(Player), 1, fi);
1832       timer_fread(&tux.invincible_timer,fi);
1833       timer_fread(&tux.skidding_timer,fi);
1834       timer_fread(&tux.safe_timer,fi);
1835       timer_fread(&tux.frame_timer,fi);
1836       timer_fread(&time_left,fi);
1837       fread(&ui,sizeof(int),1,fi);
1838       tux.hphysic.start_time += st_get_ticks() - ui;
1839       tux.vphysic.start_time += st_get_ticks() - ui;
1840       fclose(fi);
1841     }
1842
1843 }
1844
1845 void slotinfo(char **pinfo, int slot)
1846 {
1847   FILE* fi;
1848   char slotfile[1024];
1849   char tmp[200];
1850   char str[5];
1851   int slot_level;
1852   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1853
1854   fi = fopen(slotfile, "rb");
1855
1856   sprintf(tmp,"Slot %d - ",slot);
1857
1858   if (fi == NULL)
1859     {
1860       strcat(tmp,"Free");
1861     }
1862   else
1863     {
1864       fgets(str, 100, fi);
1865       str[strlen(str)-1] = '\0';
1866       strcat(tmp, str);
1867       strcat(tmp, " / Level:");
1868       fread(&slot_level,sizeof(int),1,fi);
1869       sprintf(str,"%d",slot_level);
1870       strcat(tmp,str);
1871       fclose(fi);
1872     }
1873
1874   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1875   strcpy(*pinfo,tmp);
1876 }
1877