f5ab55bb586f4f3c46c2736a6b025d922c00f56a
[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 /* 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 void tryemptybox(float x, float y, int col_side)
1563 {
1564   Tile* tile = gettile(x,y);
1565   if (!tile->fullbox)
1566     return;
1567
1568   // according to the collision side, set the upgrade direction
1569   if(col_side == LEFT)
1570     col_side = RIGHT;
1571   else
1572     col_side = LEFT;
1573
1574   switch(tile->data)
1575     {
1576     case 1: //'A':      /* Box with a distro! */
1577       add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1578       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1579       score = score + SCORE_DISTRO;
1580       distros++;
1581       break;
1582
1583     case 2: // 'B':      /* Add an upgrade! */
1584       if (tux.size == SMALL)     /* Tux is small, add mints! */
1585         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1586       else     /* Tux is big, add coffee: */
1587         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1588       play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1589       break;
1590
1591     case 3:// '!':     /* Add a golden herring */
1592       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1593       break;
1594     default:
1595       break;
1596     }
1597
1598   /* Empty the box: */
1599   level_change(&current_level,x, y, TM_IA, tile->next_tile);
1600 }
1601
1602 /* Try to grab a distro: */
1603 void trygrabdistro(float x, float y, int bounciness)
1604 {
1605   Tile* tile = gettile(x, y);
1606   if (tile && tile->distro)
1607     {
1608       level_change(&current_level,x, y, TM_IA, tile->next_tile);
1609       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1610
1611       if (bounciness == BOUNCE)
1612         {
1613           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1614                             (int)(y / 32) * 32);
1615         }
1616
1617       score = score + SCORE_DISTRO;
1618       distros++;
1619     }
1620 }
1621
1622 /* Try to bump a bad guy from below: */
1623 void trybumpbadguy(float x, float y)
1624 {
1625   /* Bad guys: */
1626   for (unsigned int i; i = 0; i < bad_guys.size(); i++)
1627     {
1628       if (bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1629           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1630         {
1631           if (bad_guys[i].kind == BAD_BSOD ||
1632               bad_guys[i].kind == BAD_LAPTOP)
1633             {
1634               bad_guys[i].dying = DYING_FALLING;
1635               bad_guys[i].base.ym = -8;
1636               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1637             }
1638         }
1639     }
1640
1641
1642   /* Upgrades: */
1643   for (unsigned int i = 0; i < upgrades.size(); i++)
1644     {
1645       if (upgrades[i].base.height == 32 &&
1646           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1647           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1648         {
1649           upgrades[i].base.xm = -upgrades[i].base.xm;
1650           upgrades[i].base.ym = -8;
1651           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1652         }
1653     }
1654 }
1655
1656 /* (Status): */
1657 void drawstatus(void)
1658 {
1659   char str[60];
1660
1661   sprintf(str, "%d", score);
1662   text_draw(&white_text, "SCORE", 0, 0, 1);
1663   text_draw(&gold_text, str, 96, 0, 1);
1664
1665   if(st_gl_mode != ST_GL_TEST)
1666     {
1667       sprintf(str, "%d", hs_score);
1668       text_draw(&white_text, "HIGH", 0, 20, 1);
1669       text_draw(&gold_text, str, 96, 20, 1);
1670     }
1671   else
1672     {
1673       text_draw(&white_text,"Press ESC To Return",0,20,1);
1674     }
1675
1676   if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1677     {
1678       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1679       text_draw(&white_text, "TIME", 224, 0, 1);
1680       text_draw(&gold_text, str, 304, 0, 1);
1681     }
1682
1683   sprintf(str, "%d", distros);
1684   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1685   text_draw(&gold_text, str, 608, 0, 1);
1686
1687   text_draw(&white_text, "LIVES", screen->h, 20, 1);
1688
1689   if(show_fps)
1690     {
1691       sprintf(str, "%2.1f", fps_fps);
1692       text_draw(&white_text, "FPS", screen->h, 40, 1);
1693       text_draw(&gold_text, str, screen->h + 60, 40, 1);
1694     }
1695
1696   for(int i=0; i < tux.lives; ++i)
1697     {
1698       texture_draw(&tux_life,565+(18*i),20);
1699     }
1700 }
1701
1702
1703 void drawendscreen(void)
1704 {
1705   char str[80];
1706
1707   clearscreen(0, 0, 0);
1708
1709   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1710
1711   sprintf(str, "SCORE: %d", score);
1712   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1713
1714   sprintf(str, "DISTROS: %d", distros);
1715   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1716
1717   flipscreen();
1718   SDL_Delay(2000);
1719 }
1720
1721 void drawresultscreen(void)
1722 {
1723   char str[80];
1724
1725   clearscreen(0, 0, 0);
1726
1727   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1728
1729   sprintf(str, "SCORE: %d", score);
1730   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1731
1732   sprintf(str, "DISTROS: %d", distros);
1733   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1734
1735   flipscreen();
1736   SDL_Delay(2000);
1737 }
1738
1739 void savegame(int slot)
1740 {
1741   char savefile[1024];
1742   FILE* fi;
1743   unsigned int ui;
1744
1745   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1746
1747   fi = fopen(savefile, "wb");
1748
1749   if (fi == NULL)
1750     {
1751       fprintf(stderr, "Warning: I could not open the slot file ");
1752     }
1753   else
1754     {
1755       fputs(level_subset, fi);
1756       fputs("\n", fi);
1757       fwrite(&level,sizeof(int),1,fi);
1758       fwrite(&score,sizeof(int),1,fi);
1759       fwrite(&distros,sizeof(int),1,fi);
1760       fwrite(&scroll_x,sizeof(float),1,fi);
1761       fwrite(&tux,sizeof(Player),1,fi);
1762       timer_fwrite(&tux.invincible_timer,fi);
1763       timer_fwrite(&tux.skidding_timer,fi);
1764       timer_fwrite(&tux.safe_timer,fi);
1765       timer_fwrite(&tux.frame_timer,fi);
1766       timer_fwrite(&time_left,fi);
1767       ui = st_get_ticks();
1768       fwrite(&ui,sizeof(int),1,fi);
1769     }
1770   fclose(fi);
1771
1772 }
1773
1774 void loadgame(int slot)
1775 {
1776   char savefile[1024];
1777   char str[100];
1778   FILE* fi;
1779   unsigned int ui;
1780
1781   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1782
1783   fi = fopen(savefile, "rb");
1784
1785   if (fi == NULL)
1786     {
1787       fprintf(stderr, "Warning: I could not open the slot file ");
1788
1789     }
1790   else
1791     {
1792       fgets(str, 100, fi);
1793       strcpy(level_subset, str);
1794       level_subset[strlen(level_subset)-1] = '\0';
1795       fread(&level,sizeof(int),1,fi);
1796
1797       set_defaults();
1798       level_free(&current_level);
1799       if(level_load(&current_level,level_subset,level) != 0)
1800         exit(1);
1801       arrays_free();
1802       arrays_init();
1803       activate_bad_guys();
1804       activate_particle_systems();
1805       level_free_gfx();
1806       level_load_gfx(&current_level);
1807       level_free_song();
1808       level_load_song(&current_level);
1809       levelintro();
1810       update_time = st_get_ticks();
1811
1812       fread(&score,sizeof(int),1,fi);
1813       fread(&distros,sizeof(int),1,fi);
1814       fread(&scroll_x,sizeof(float),1,fi);
1815       fread(&tux, sizeof(Player), 1, fi);
1816       timer_fread(&tux.invincible_timer,fi);
1817       timer_fread(&tux.skidding_timer,fi);
1818       timer_fread(&tux.safe_timer,fi);
1819       timer_fread(&tux.frame_timer,fi);
1820       timer_fread(&time_left,fi);
1821       fread(&ui,sizeof(int),1,fi);
1822       tux.hphysic.start_time += st_get_ticks() - ui;
1823       tux.vphysic.start_time += st_get_ticks() - ui;
1824       fclose(fi);
1825     }
1826
1827 }
1828
1829 void slotinfo(char **pinfo, int slot)
1830 {
1831   FILE* fi;
1832   char slotfile[1024];
1833   char tmp[200];
1834   char str[5];
1835   int slot_level;
1836   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1837
1838   fi = fopen(slotfile, "rb");
1839
1840   sprintf(tmp,"Slot %d - ",slot);
1841
1842   if (fi == NULL)
1843     {
1844       strcat(tmp,"Free");
1845     }
1846   else
1847     {
1848       fgets(str, 100, fi);
1849       str[strlen(str)-1] = '\0';
1850       strcat(tmp, str);
1851       strcat(tmp, " / Level:");
1852       fread(&slot_level,sizeof(int),1,fi);
1853       sprintf(str,"%d",slot_level);
1854       strcat(tmp,str);
1855       fclose(fi);
1856     }
1857
1858   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1859   strcpy(*pinfo,tmp);
1860 }
1861