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