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