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