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