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