quick fix for bug introduced by the last commit
[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 = 0;
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 bool issolid(float x, float y)
1419 {
1420   Tile* tile = TileManager::instance()->get
1421                (shape(x,y));
1422   if(tile)
1423     {
1424       if(tile->solid == true)
1425         return true;
1426       else
1427         return false;
1428     }
1429   else
1430     {
1431       return false;
1432     }
1433 }
1434
1435 /* Is it a brick? */
1436
1437 bool isbrick(float x, float y)
1438 {
1439   Tile* tile = TileManager::instance()->get
1440                (shape(x,y));
1441   if(tile)
1442     {
1443       if(tile->brick == true)
1444         return true;
1445       else
1446         return false;
1447     }
1448   else
1449     {
1450       return false;
1451     }
1452 }
1453
1454
1455 /* Is it ice? */
1456
1457 bool isice(float x, float y)
1458 {
1459   Tile* tile = TileManager::instance()->get
1460                (shape(x,y));
1461   if(tile)
1462     {
1463       if(tile->ice == true)
1464         return true;
1465       else
1466         return false;
1467     }
1468   else
1469     {
1470       return false;
1471     }
1472 }
1473
1474 /* Is it a full box? */
1475
1476 bool isfullbox(float x, float y)
1477 {
1478   Tile* tile = TileManager::instance()->get
1479                (shape(x,y));
1480   if(tile)
1481     {
1482       if(tile->fullbox == true)
1483         return true;
1484       else
1485         return false;
1486     }
1487   else
1488     {
1489       return false;
1490     }
1491 }
1492
1493 bool isdistro(float x, float y)
1494 {
1495   Tile* tile = TileManager::instance()->get(shape(x,y));
1496   return tile && tile->distro;
1497 }
1498
1499 /* Break a brick: */
1500
1501 void trybreakbrick(float x, float y)
1502 {
1503   Tile* tile = gettile(x, y);
1504   if (tile->brick)
1505     {
1506       if (tile->data > 0)
1507         {
1508           /* Get a distro from it: */
1509           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1510                             (int)(y / 32) * 32);
1511
1512           if (!counting_distros)
1513             {
1514               counting_distros = true;
1515               distro_counter = 50;
1516             }
1517
1518           if (distro_counter <= 0)
1519             level_change(&current_level,x, y, TM_IA, tile->next_tile2);
1520
1521           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1522           score = score + SCORE_DISTRO;
1523           distros++;
1524         }
1525       else
1526         {
1527           /* Get rid of it: */
1528           level_change(&current_level,x, y, TM_IA, tile->next_tile);
1529         }
1530
1531
1532       /* Replace it with broken bits: */
1533
1534       add_broken_brick(((int)(x + 1) / 32) * 32,
1535                        (int)(y / 32) * 32);
1536
1537
1538       /* Get some score: */
1539
1540       play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1541       score = score + SCORE_BRICK;
1542     }
1543 }
1544
1545
1546 /* Bounce a brick: */
1547
1548 void bumpbrick(float x, float y)
1549 {
1550   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1551                    (int)(y / 32) * 32);
1552
1553   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1554
1555 }
1556
1557
1558 /* Empty a box: */
1559 void tryemptybox(float x, float y, int col_side)
1560 {
1561   Tile* tile = gettile(x,y);
1562   if (!tile->fullbox)
1563     return;
1564
1565   // according to the collision side, set the upgrade direction
1566   if(col_side == LEFT)
1567     col_side = RIGHT;
1568   else
1569     col_side = LEFT;
1570
1571   switch(tile->data)
1572     {
1573     case 1: //'A':      /* Box with a distro! */
1574       add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1575       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1576       score = score + SCORE_DISTRO;
1577       distros++;
1578       break;
1579
1580     case 2: // 'B':      /* Add an upgrade! */
1581       if (tux.size == SMALL)     /* Tux is small, add mints! */
1582         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1583       else     /* Tux is big, add coffee: */
1584         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1585       play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1586       break;
1587
1588     case 3:// '!':     /* Add a golden herring */
1589       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1590       break;
1591     default:
1592       break;
1593     }
1594
1595   /* Empty the box: */
1596   level_change(&current_level,x, y, TM_IA, tile->next_tile);
1597 }
1598
1599 /* Try to grab a distro: */
1600 void trygrabdistro(float x, float y, int bounciness)
1601 {
1602   Tile* tile = gettile(x, y);
1603   if (tile && tile->distro)
1604     {
1605       level_change(&current_level,x, y, TM_IA, tile->next_tile);
1606       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1607
1608       if (bounciness == BOUNCE)
1609         {
1610           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1611                             (int)(y / 32) * 32);
1612         }
1613
1614       score = score + SCORE_DISTRO;
1615       distros++;
1616     }
1617 }
1618
1619 /* Try to bump a bad guy from below: */
1620 void trybumpbadguy(float x, float y)
1621 {
1622   /* Bad guys: */
1623   for (unsigned int i = 0; i < bad_guys.size(); i++)
1624     {
1625       if (bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1626           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1627         {
1628           if (bad_guys[i].kind == BAD_BSOD ||
1629               bad_guys[i].kind == BAD_LAPTOP)
1630             {
1631               bad_guys[i].dying = DYING_FALLING;
1632               bad_guys[i].base.ym = -8;
1633               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1634             }
1635         }
1636     }
1637
1638
1639   /* Upgrades: */
1640   for (unsigned int i = 0; i < upgrades.size(); i++)
1641     {
1642       if (upgrades[i].base.height == 32 &&
1643           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1644           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1645         {
1646           upgrades[i].base.xm = -upgrades[i].base.xm;
1647           upgrades[i].base.ym = -8;
1648           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1649         }
1650     }
1651 }
1652
1653 /* (Status): */
1654 void drawstatus(void)
1655 {
1656   char str[60];
1657
1658   sprintf(str, "%d", score);
1659   text_draw(&white_text, "SCORE", 0, 0, 1);
1660   text_draw(&gold_text, str, 96, 0, 1);
1661
1662   if(st_gl_mode != ST_GL_TEST)
1663     {
1664       sprintf(str, "%d", hs_score);
1665       text_draw(&white_text, "HIGH", 0, 20, 1);
1666       text_draw(&gold_text, str, 96, 20, 1);
1667     }
1668   else
1669     {
1670       text_draw(&white_text,"Press ESC To Return",0,20,1);
1671     }
1672
1673   if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1674     {
1675       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1676       text_draw(&white_text, "TIME", 224, 0, 1);
1677       text_draw(&gold_text, str, 304, 0, 1);
1678     }
1679
1680   sprintf(str, "%d", distros);
1681   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1682   text_draw(&gold_text, str, 608, 0, 1);
1683
1684   text_draw(&white_text, "LIVES", screen->h, 20, 1);
1685
1686   if(show_fps)
1687     {
1688       sprintf(str, "%2.1f", fps_fps);
1689       text_draw(&white_text, "FPS", screen->h, 40, 1);
1690       text_draw(&gold_text, str, screen->h + 60, 40, 1);
1691     }
1692
1693   for(int i=0; i < tux.lives; ++i)
1694     {
1695       texture_draw(&tux_life,565+(18*i),20);
1696     }
1697 }
1698
1699
1700 void drawendscreen(void)
1701 {
1702   char str[80];
1703
1704   clearscreen(0, 0, 0);
1705
1706   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1707
1708   sprintf(str, "SCORE: %d", score);
1709   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1710
1711   sprintf(str, "DISTROS: %d", distros);
1712   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1713
1714   flipscreen();
1715   SDL_Delay(2000);
1716 }
1717
1718 void drawresultscreen(void)
1719 {
1720   char str[80];
1721
1722   clearscreen(0, 0, 0);
1723
1724   text_drawf(&blue_text, "Result:", 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 savegame(int slot)
1737 {
1738   char savefile[1024];
1739   FILE* fi;
1740   unsigned int ui;
1741
1742   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1743
1744   fi = fopen(savefile, "wb");
1745
1746   if (fi == NULL)
1747     {
1748       fprintf(stderr, "Warning: I could not open the slot file ");
1749     }
1750   else
1751     {
1752       fputs(level_subset, fi);
1753       fputs("\n", fi);
1754       fwrite(&level,sizeof(int),1,fi);
1755       fwrite(&score,sizeof(int),1,fi);
1756       fwrite(&distros,sizeof(int),1,fi);
1757       fwrite(&scroll_x,sizeof(float),1,fi);
1758       fwrite(&tux,sizeof(Player),1,fi);
1759       timer_fwrite(&tux.invincible_timer,fi);
1760       timer_fwrite(&tux.skidding_timer,fi);
1761       timer_fwrite(&tux.safe_timer,fi);
1762       timer_fwrite(&tux.frame_timer,fi);
1763       timer_fwrite(&time_left,fi);
1764       ui = st_get_ticks();
1765       fwrite(&ui,sizeof(int),1,fi);
1766     }
1767   fclose(fi);
1768
1769 }
1770
1771 void loadgame(int slot)
1772 {
1773   char savefile[1024];
1774   char str[100];
1775   FILE* fi;
1776   unsigned int ui;
1777
1778   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1779
1780   fi = fopen(savefile, "rb");
1781
1782   if (fi == NULL)
1783     {
1784       fprintf(stderr, "Warning: I could not open the slot file ");
1785
1786     }
1787   else
1788     {
1789       fgets(str, 100, fi);
1790       strcpy(level_subset, str);
1791       level_subset[strlen(level_subset)-1] = '\0';
1792       fread(&level,sizeof(int),1,fi);
1793
1794       set_defaults();
1795       level_free(&current_level);
1796       if(level_load(&current_level,level_subset,level) != 0)
1797         exit(1);
1798       arrays_free();
1799       arrays_init();
1800       activate_bad_guys();
1801       activate_particle_systems();
1802       level_free_gfx();
1803       level_load_gfx(&current_level);
1804       level_free_song();
1805       level_load_song(&current_level);
1806       levelintro();
1807       update_time = st_get_ticks();
1808
1809       fread(&score,sizeof(int),1,fi);
1810       fread(&distros,sizeof(int),1,fi);
1811       fread(&scroll_x,sizeof(float),1,fi);
1812       fread(&tux, sizeof(Player), 1, fi);
1813       timer_fread(&tux.invincible_timer,fi);
1814       timer_fread(&tux.skidding_timer,fi);
1815       timer_fread(&tux.safe_timer,fi);
1816       timer_fread(&tux.frame_timer,fi);
1817       timer_fread(&time_left,fi);
1818       fread(&ui,sizeof(int),1,fi);
1819       tux.hphysic.start_time += st_get_ticks() - ui;
1820       tux.vphysic.start_time += st_get_ticks() - ui;
1821       fclose(fi);
1822     }
1823
1824 }
1825
1826 void slotinfo(char **pinfo, int slot)
1827 {
1828   FILE* fi;
1829   char slotfile[1024];
1830   char tmp[200];
1831   char str[5];
1832   int slot_level;
1833   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1834
1835   fi = fopen(slotfile, "rb");
1836
1837   sprintf(tmp,"Slot %d - ",slot);
1838
1839   if (fi == NULL)
1840     {
1841       strcat(tmp,"Free");
1842     }
1843   else
1844     {
1845       fgets(str, 100, fi);
1846       str[strlen(str)-1] = '\0';
1847       strcat(tmp, str);
1848       strcat(tmp, " / Level:");
1849       fread(&slot_level,sizeof(int),1,fi);
1850       sprintf(str,"%d",slot_level);
1851       strcat(tmp,str);
1852       fclose(fi);
1853     }
1854
1855   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1856   strcpy(*pinfo,tmp);
1857 }
1858