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