f2e454e2722618ccb7a761171ab2dd6297996ea9
[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   for (y = 0; y < 15; ++y)
522     {
523       for (x = 0; x < 21; ++x)
524         {
525           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
526                     current_level.ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
527         }
528     }
529
530   /* (Bouncy bricks): */
531   for (unsigned int i = 0; i < bouncy_bricks.size(); ++i)
532     bouncy_brick_draw(&bouncy_bricks[i]);
533
534   for (unsigned int i = 0; i < bad_guys.size(); ++i)
535     bad_guys[i].draw();
536
537   tux.draw();
538
539   for (unsigned int i = 0; i < bullets.size(); ++i)
540     bullet_draw(&bullets[i]);
541
542   for (unsigned int i = 0; i < floating_scores.size(); ++i)
543     floating_score_draw(&floating_scores[i]);
544
545   for (unsigned int i = 0; i < upgrades.size(); ++i)
546     upgrade_draw(&upgrades[i]);
547
548   for (unsigned int i = 0; i < bouncy_distros.size(); ++i)
549     bouncy_distro_draw(&bouncy_distros[i]);
550
551   for (unsigned int i = 0; i < broken_bricks.size(); ++i)
552     broken_brick_draw(&broken_bricks[i]);
553
554   /* Draw foreground: */
555   for (y = 0; y < 15; ++y)
556     {
557       for (x = 0; x < 21; ++x)
558         {
559           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
560                     current_level.fg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
561         }
562     }
563
564   /* Draw particle systems (foreground) */
565   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
566     {
567       (*p)->draw(scroll_x, 0, 1);
568     }
569
570   drawstatus();
571
572   if(game_pause)
573     {
574       int x = screen->h / 20;
575       for(int i = 0; i < x; ++i)
576         {
577           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);
578         }
579       fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
580       text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1);
581     }
582
583   if(show_menu)
584     menu_process_current();
585
586   /* (Update it all!) */
587   updatescreen();
588 }
589
590 /* --- GAME LOOP! --- */
591
592 int gameloop(const char * subset, int levelnb, int mode)
593 {
594   int fps_cnt, jump, done;
595   timer_type fps_timer, frame_timer;
596   timer_init(&fps_timer, true);
597   timer_init(&frame_timer, true);
598
599   game_started = true;
600
601   st_gl_mode = mode;
602   level = levelnb;
603
604   /* Init the game: */
605   arrays_init();
606   set_defaults();
607
608   strcpy(level_subset,subset);
609
610   if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
611     {
612       if (level_load(&current_level, level_subset))
613         exit(1);
614     }
615   else
616     {
617       if(level_load(&current_level, level_subset, level) != 0)
618         exit(1);
619     }
620
621   level_load_gfx(&current_level);
622   activate_bad_guys();
623   activate_particle_systems();
624   level_load_song(&current_level);
625
626   tux.init();
627
628   if(st_gl_mode != ST_GL_TEST)
629     load_hs();
630
631   loadshared();
632
633   if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
634     levelintro();
635
636   timer_init(&time_left,true);
637   start_timers();
638
639   if(st_gl_mode == ST_GL_LOAD_GAME)
640     loadgame(levelnb);
641
642   /* --- MAIN GAME LOOP!!! --- */
643
644   jump = false;
645   done = 0;
646   quit = 0;
647   global_frame_counter = 0;
648   game_pause = 0;
649   timer_init(&fps_timer,true);
650   timer_init(&frame_timer,true);
651   fps_cnt = 0;
652
653   /* Clear screen: */
654
655   clearscreen(0, 0, 0);
656   updatescreen();
657
658   /* Play music: */
659   play_current_music();
660
661
662   while (SDL_PollEvent(&event))
663   {}
664
665   game_draw();
666   do
667     {
668       jump = false;
669
670       /* Calculate the movement-factor */
671       frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
672       if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
673         frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
674
675       if(!timer_check(&frame_timer))
676         {
677           timer_start(&frame_timer,25);
678           ++global_frame_counter;
679         }
680
681       /* Handle events: */
682
683       tux.input.old_fire = tux.input.fire;
684
685       game_event();
686
687       if(show_menu)
688         {
689           if(current_menu == game_menu)
690             {
691               switch (game_menu->check())
692                 {
693                 case 2:
694                   st_pause_ticks_stop();
695                   break;
696                 case 3:
697                   update_load_save_game_menu(save_game_menu, false);
698                   break;
699                 case 4:
700                   update_load_save_game_menu(load_game_menu, true);
701                   break;
702                 case 7:
703                   st_pause_ticks_stop();
704                   done = 1;
705                   break;
706                 }
707             }
708           else if(current_menu == options_menu)
709             {
710               process_options_menu();
711             }
712           else if(current_menu == save_game_menu )
713             {
714               process_save_load_game_menu(true);
715             }
716           else if(current_menu == load_game_menu )
717             {
718               process_save_load_game_menu(false);
719             }
720         }
721
722
723       /* Handle actions: */
724
725       if(!game_pause && !show_menu)
726         {
727           /*float z = frame_ratio;
728             frame_ratio = 1;
729             while(z >= 1)
730             {*/
731           if (game_action() == 0)
732             {
733               /* == 0: no more lives */
734               /* == -1: continues */
735               return 0;
736             }
737           /*  --z;
738                      }*/
739         }
740       else
741         {
742           ++pause_menu_frame;
743           SDL_Delay(50);
744         }
745
746       if(debug_mode && debug_fps)
747         SDL_Delay(60);
748
749       /*Draw the current scene to the screen */
750       /*If the machine running the game is too slow
751         skip the drawing of the frame (so the calculations are more precise and
752         the FPS aren't affected).*/
753       /*if( ! fps_fps < 50.0 )
754         game_draw();
755         else
756         jump = true;*/ /*FIXME: Implement this tweak right.*/
757       game_draw();
758
759       /* Time stops in pause mode */
760       if(game_pause || show_menu )
761         {
762           continue;
763         }
764
765       /* Set the time of the last update and the time of the current update */
766       last_update_time = update_time;
767       update_time = st_get_ticks();
768
769       /* Pause till next frame, if the machine running the game is too fast: */
770       /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
771          the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
772       if(last_update_time >= update_time - 12 && !jump)
773         SDL_Delay(10);
774       /*if((update_time - last_update_time) < 10)
775         SDL_Delay((11 - (update_time - last_update_time))/2);*/
776
777
778
779       /* Handle time: */
780
781       if (timer_check(&time_left))
782         {
783           /* are we low on time ? */
784           if ((timer_get_left(&time_left) < TIME_WARNING)
785               && (get_current_music() != HURRYUP_MUSIC))     /* play the fast music */
786             {
787               set_current_music(HURRYUP_MUSIC);
788               play_current_music();
789             }
790
791         }
792       else
793         tux.kill(KILL);
794
795
796       /* Calculate frames per second */
797       if(show_fps)
798         {
799           ++fps_cnt;
800           fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
801
802           if(!timer_check(&fps_timer))
803             {
804               timer_start(&fps_timer,1000);
805               fps_cnt = 0;
806             }
807         }
808
809     }
810   while (!done && !quit);
811
812   halt_music();
813
814   level_free_gfx();
815   level_free(&current_level);
816   level_free_song();
817   unloadshared();
818   arrays_free();
819
820   game_started = false;
821
822   return(quit);
823 }
824
825
826 /* Load graphics/sounds shared between all levels: */
827
828 void loadshared(void)
829 {
830   int i;
831
832   /* Tuxes: */
833   texture_load(&tux_right[0], datadir + "/images/shared/tux-right-0.png", USE_ALPHA);
834   texture_load(&tux_right[1], datadir + "/images/shared/tux-right-1.png", USE_ALPHA);
835   texture_load(&tux_right[2], datadir + "/images/shared/tux-right-2.png", USE_ALPHA);
836
837   texture_load(&tux_left[0], datadir + "/images/shared/tux-left-0.png", USE_ALPHA);
838   texture_load(&tux_left[1], datadir + "/images/shared/tux-left-1.png", USE_ALPHA);
839   texture_load(&tux_left[2], datadir + "/images/shared/tux-left-2.png", USE_ALPHA);
840
841   texture_load(&firetux_right[0], datadir + "/images/shared/firetux-right-0.png", USE_ALPHA);
842   texture_load(&firetux_right[1], datadir + "/images/shared/firetux-right-1.png", USE_ALPHA);
843   texture_load(&firetux_right[2], datadir + "/images/shared/firetux-right-2.png", USE_ALPHA);
844
845   texture_load(&firetux_left[0], datadir + "/images/shared/firetux-left-0.png", USE_ALPHA);
846   texture_load(&firetux_left[1], datadir + "/images/shared/firetux-left-1.png", USE_ALPHA);
847   texture_load(&firetux_left[2], datadir + "/images/shared/firetux-left-2.png", USE_ALPHA);
848
849
850   texture_load(&cape_right[0], datadir + "/images/shared/cape-right-0.png",
851                USE_ALPHA);
852
853   texture_load(&cape_right[1], datadir + "/images/shared/cape-right-1.png",
854                USE_ALPHA);
855
856   texture_load(&cape_left[0], datadir + "/images/shared/cape-left-0.png",
857                USE_ALPHA);
858
859   texture_load(&cape_left[1], datadir + "/images/shared/cape-left-1.png",
860                USE_ALPHA);
861
862   texture_load(&bigtux_right[0], datadir + "/images/shared/bigtux-right-0.png",
863                USE_ALPHA);
864
865   texture_load(&bigtux_right[1], datadir + "/images/shared/bigtux-right-1.png",
866                USE_ALPHA);
867
868   texture_load(&bigtux_right[2], datadir + "/images/shared/bigtux-right-2.png",
869                USE_ALPHA);
870
871   texture_load(&bigtux_right_jump, datadir + "/images/shared/bigtux-right-jump.png", USE_ALPHA);
872
873   texture_load(&bigtux_left[0], datadir + "/images/shared/bigtux-left-0.png",
874                USE_ALPHA);
875
876   texture_load(&bigtux_left[1], datadir + "/images/shared/bigtux-left-1.png",
877                USE_ALPHA);
878
879   texture_load(&bigtux_left[2], datadir + "/images/shared/bigtux-left-2.png",
880                USE_ALPHA);
881
882   texture_load(&bigtux_left_jump, datadir + "/images/shared/bigtux-left-jump.png", USE_ALPHA);
883
884   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
885                USE_ALPHA);
886
887   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
888                USE_ALPHA);
889
890   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
891                USE_ALPHA);
892
893   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
894                USE_ALPHA);
895
896   texture_load(&bigfiretux_right[0], datadir + "/images/shared/bigfiretux-right-0.png",
897                USE_ALPHA);
898
899   texture_load(&bigfiretux_right[1], datadir + "/images/shared/bigfiretux-right-1.png",
900                USE_ALPHA);
901
902   texture_load(&bigfiretux_right[2], datadir + "/images/shared/bigfiretux-right-2.png",
903                USE_ALPHA);
904
905   texture_load(&bigfiretux_right_jump, datadir + "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
906
907   texture_load(&bigfiretux_left[0], datadir + "/images/shared/bigfiretux-left-0.png",
908                USE_ALPHA);
909
910   texture_load(&bigfiretux_left[1], datadir + "/images/shared/bigfiretux-left-1.png",
911                USE_ALPHA);
912
913   texture_load(&bigfiretux_left[2], datadir + "/images/shared/bigfiretux-left-2.png",
914                USE_ALPHA);
915
916   texture_load(&bigfiretux_left_jump, datadir + "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
917
918   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
919                USE_ALPHA);
920
921   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
922                USE_ALPHA);
923
924   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
925                USE_ALPHA);
926
927   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
928                USE_ALPHA);
929
930
931   texture_load(&ducktux_right, datadir +
932                "/images/shared/ducktux-right.png",
933                USE_ALPHA);
934
935   texture_load(&ducktux_left, datadir +
936                "/images/shared/ducktux-left.png",
937                USE_ALPHA);
938
939   texture_load(&skidtux_right, datadir +
940                "/images/shared/skidtux-right.png",
941                USE_ALPHA);
942
943   texture_load(&skidtux_left, datadir +
944                "/images/shared/skidtux-left.png",
945                USE_ALPHA);
946
947   texture_load(&duckfiretux_right, datadir +
948                "/images/shared/duckfiretux-right.png",
949                USE_ALPHA);
950
951   texture_load(&duckfiretux_left, datadir +
952                "/images/shared/duckfiretux-left.png",
953                USE_ALPHA);
954
955   texture_load(&skidfiretux_right, datadir +
956                "/images/shared/skidfiretux-right.png",
957                USE_ALPHA);
958
959   texture_load(&skidfiretux_left, datadir +
960                "/images/shared/skidfiretux-left.png",
961                USE_ALPHA);
962
963
964   /* Boxes: */
965
966   texture_load(&img_box_full, datadir + "/images/shared/box-full.png",
967                IGNORE_ALPHA);
968   texture_load(&img_box_empty, datadir + "/images/shared/box-empty.png",
969                IGNORE_ALPHA);
970
971
972   /* Water: */
973
974
975   texture_load(&img_water, datadir + "/images/shared/water.png", IGNORE_ALPHA);
976
977   texture_load(&img_waves[0], datadir + "/images/shared/waves-0.png",
978                USE_ALPHA);
979
980   texture_load(&img_waves[1], datadir + "/images/shared/waves-1.png",
981                USE_ALPHA);
982
983   texture_load(&img_waves[2], datadir + "/images/shared/waves-2.png",
984                USE_ALPHA);
985
986
987   /* Pole: */
988
989   texture_load(&img_pole, datadir + "/images/shared/pole.png", USE_ALPHA);
990   texture_load(&img_poletop, datadir + "/images/shared/poletop.png",
991                USE_ALPHA);
992
993
994   /* Flag: */
995
996   texture_load(&img_flag[0], datadir + "/images/shared/flag-0.png",
997                USE_ALPHA);
998   texture_load(&img_flag[1], datadir + "/images/shared/flag-1.png",
999                USE_ALPHA);
1000
1001
1002   /* Cloud: */
1003
1004   texture_load(&img_cloud[0][0], datadir + "/images/shared/cloud-00.png",
1005                USE_ALPHA);
1006
1007   texture_load(&img_cloud[0][1], datadir + "/images/shared/cloud-01.png",
1008                USE_ALPHA);
1009
1010   texture_load(&img_cloud[0][2], datadir + "/images/shared/cloud-02.png",
1011                USE_ALPHA);
1012
1013   texture_load(&img_cloud[0][3], datadir + "/images/shared/cloud-03.png",
1014                USE_ALPHA);
1015
1016
1017   texture_load(&img_cloud[1][0], datadir + "/images/shared/cloud-10.png",
1018                USE_ALPHA);
1019
1020   texture_load(&img_cloud[1][1], datadir + "/images/shared/cloud-11.png",
1021                USE_ALPHA);
1022
1023   texture_load(&img_cloud[1][2], datadir + "/images/shared/cloud-12.png",
1024                USE_ALPHA);
1025
1026   texture_load(&img_cloud[1][3], datadir + "/images/shared/cloud-13.png",
1027                USE_ALPHA);
1028
1029
1030   /* Bad guys: */
1031
1032   /* (BSOD) */
1033
1034   texture_load(&img_bsod_left[0], datadir +
1035                "/images/shared/bsod-left-0.png",
1036                USE_ALPHA);
1037
1038   texture_load(&img_bsod_left[1], datadir +
1039                "/images/shared/bsod-left-1.png",
1040                USE_ALPHA);
1041
1042   texture_load(&img_bsod_left[2], datadir +
1043                "/images/shared/bsod-left-2.png",
1044                USE_ALPHA);
1045
1046   texture_load(&img_bsod_left[3], datadir +
1047                "/images/shared/bsod-left-3.png",
1048                USE_ALPHA);
1049
1050   texture_load(&img_bsod_right[0], datadir +
1051                "/images/shared/bsod-right-0.png",
1052                USE_ALPHA);
1053
1054   texture_load(&img_bsod_right[1], datadir +
1055                "/images/shared/bsod-right-1.png",
1056                USE_ALPHA);
1057
1058   texture_load(&img_bsod_right[2], datadir +
1059                "/images/shared/bsod-right-2.png",
1060                USE_ALPHA);
1061
1062   texture_load(&img_bsod_right[3], datadir +
1063                "/images/shared/bsod-right-3.png",
1064                USE_ALPHA);
1065
1066   texture_load(&img_bsod_squished_left, datadir +
1067                "/images/shared/bsod-squished-left.png",
1068                USE_ALPHA);
1069
1070   texture_load(&img_bsod_squished_right, datadir +
1071                "/images/shared/bsod-squished-right.png",
1072                USE_ALPHA);
1073
1074   texture_load(&img_bsod_falling_left, datadir +
1075                "/images/shared/bsod-falling-left.png",
1076                USE_ALPHA);
1077
1078   texture_load(&img_bsod_falling_right, datadir +
1079                "/images/shared/bsod-falling-right.png",
1080                USE_ALPHA);
1081
1082
1083   /* (Laptop) */
1084
1085   texture_load(&img_laptop_left[0], datadir +
1086                "/images/shared/laptop-left-0.png",
1087                USE_ALPHA);
1088
1089   texture_load(&img_laptop_left[1], datadir +
1090                "/images/shared/laptop-left-1.png",
1091                USE_ALPHA);
1092
1093   texture_load(&img_laptop_left[2], datadir +
1094                "/images/shared/laptop-left-2.png",
1095                USE_ALPHA);
1096
1097   texture_load(&img_laptop_right[0], datadir +
1098                "/images/shared/laptop-right-0.png",
1099                USE_ALPHA);
1100
1101   texture_load(&img_laptop_right[1], datadir +
1102                "/images/shared/laptop-right-1.png",
1103                USE_ALPHA);
1104
1105   texture_load(&img_laptop_right[2], datadir +
1106                "/images/shared/laptop-right-2.png",
1107                USE_ALPHA);
1108
1109   texture_load(&img_laptop_flat_left, datadir +
1110                "/images/shared/laptop-flat-left.png",
1111                USE_ALPHA);
1112
1113   texture_load(&img_laptop_flat_right, datadir +
1114                "/images/shared/laptop-flat-right.png",
1115                USE_ALPHA);
1116
1117   texture_load(&img_laptop_falling_left, datadir +
1118                "/images/shared/laptop-falling-left.png",
1119                USE_ALPHA);
1120
1121   texture_load(&img_laptop_falling_right, datadir +
1122                "/images/shared/laptop-falling-right.png",
1123                USE_ALPHA);
1124
1125
1126   /* (Money) */
1127
1128   texture_load(&img_money_left[0], datadir +
1129                "/images/shared/bag-left-0.png",
1130                USE_ALPHA);
1131
1132   texture_load(&img_money_left[1], datadir +
1133                "/images/shared/bag-left-1.png",
1134                USE_ALPHA);
1135
1136   texture_load(&img_money_right[0], datadir +
1137                "/images/shared/bag-right-0.png",
1138                USE_ALPHA);
1139
1140   texture_load(&img_money_right[1], datadir +
1141                "/images/shared/bag-right-1.png",
1142                USE_ALPHA);
1143
1144   /* Mr. Bomb */
1145   for(int i=0; i<4; ++i) {
1146       char num[4];
1147       snprintf(num, 4, "%d", i);
1148       texture_load(&img_mrbomb_left[i],
1149               datadir + "/images/shared/mrbomb-left-" + num + ".png", USE_ALPHA);
1150       texture_load(&img_mrbomb_right[i],
1151               datadir + "/images/shared/mrbomb-right-" + num + ".png", USE_ALPHA);
1152   }
1153
1154   /* stalactite */
1155   texture_load(&img_stalactite, 
1156           datadir + "/images/shared/stalactite.png", USE_ALPHA);
1157   texture_load(&img_stalactite_broken,
1158           datadir + "/images/shared/stalactite-broken.png", USE_ALPHA);
1159
1160   /* Upgrades: */
1161
1162   texture_load(&img_mints, datadir + "/images/shared/mints.png", USE_ALPHA);
1163   texture_load(&img_coffee, datadir + "/images/shared/coffee.png", USE_ALPHA);
1164
1165
1166   /* Weapons: */
1167
1168   texture_load(&img_bullet, datadir + "/images/shared/bullet.png", USE_ALPHA);
1169
1170   texture_load(&img_red_glow, datadir + "/images/shared/red-glow.png",
1171                USE_ALPHA);
1172
1173
1174
1175   /* Distros: */
1176
1177   texture_load(&img_distro[0], datadir + "/images/shared/distro-0.png",
1178                USE_ALPHA);
1179
1180   texture_load(&img_distro[1], datadir + "/images/shared/distro-1.png",
1181                USE_ALPHA);
1182
1183   texture_load(&img_distro[2], datadir + "/images/shared/distro-2.png",
1184                USE_ALPHA);
1185
1186   texture_load(&img_distro[3], datadir + "/images/shared/distro-3.png",
1187                USE_ALPHA);
1188
1189
1190   /* Tux life: */
1191
1192   texture_load(&tux_life, datadir + "/images/shared/tux-life.png",
1193                USE_ALPHA);
1194
1195   /* Herring: */
1196
1197   texture_load(&img_golden_herring, datadir + "/images/shared/golden-herring.png",
1198                USE_ALPHA);
1199
1200
1201   /* Super background: */
1202
1203   texture_load(&img_super_bkgd, datadir + "/images/shared/super-bkgd.png",
1204                IGNORE_ALPHA);
1205
1206
1207   /* Sound effects: */
1208
1209   /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1210                     // initialize sounds[i] with the correct pointer's value:
1211                     // NULL or something else. And it will be dangerous to
1212                     // play with not-initialized pointers.
1213                     // This is also true with if (use_music)
1214                     Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1215   */
1216   for (i = 0; i < NUM_SOUNDS; i++)
1217     sounds[i] = load_sound(datadir + soundfilenames[i]);
1218
1219   /* Herring song */
1220   herring_song = load_song(datadir + "/music/SALCON.MOD");
1221 }
1222
1223
1224 /* Free shared data: */
1225
1226 void unloadshared(void)
1227 {
1228   int i;
1229
1230   for (i = 0; i < 3; i++)
1231     {
1232       texture_free(&tux_right[i]);
1233       texture_free(&tux_left[i]);
1234       texture_free(&bigtux_right[i]);
1235       texture_free(&bigtux_left[i]);
1236     }
1237
1238   texture_free(&bigtux_right_jump);
1239   texture_free(&bigtux_left_jump);
1240
1241   for (i = 0; i < 2; i++)
1242     {
1243       texture_free(&cape_right[i]);
1244       texture_free(&cape_left[i]);
1245       texture_free(&bigcape_right[i]);
1246       texture_free(&bigcape_left[i]);
1247     }
1248
1249   texture_free(&ducktux_left);
1250   texture_free(&ducktux_right);
1251
1252   texture_free(&skidtux_left);
1253   texture_free(&skidtux_right);
1254
1255   for (i = 0; i < 4; i++)
1256     {
1257       texture_free(&img_bsod_left[i]);
1258       texture_free(&img_bsod_right[i]);
1259     }
1260
1261   texture_free(&img_bsod_squished_left);
1262   texture_free(&img_bsod_squished_right);
1263
1264   texture_free(&img_bsod_falling_left);
1265   texture_free(&img_bsod_falling_right);
1266
1267   for (i = 0; i < 3; i++)
1268     {
1269       texture_free(&img_laptop_left[i]);
1270       texture_free(&img_laptop_right[i]);
1271     }
1272
1273   texture_free(&img_laptop_flat_left);
1274   texture_free(&img_laptop_flat_right);
1275
1276   texture_free(&img_laptop_falling_left);
1277   texture_free(&img_laptop_falling_right);
1278
1279   for (i = 0; i < 2; i++)
1280     {
1281       texture_free(&img_money_left[i]);
1282       texture_free(&img_money_right[i]);
1283     }
1284
1285   for(i = 0; i < 4; i++) {
1286       texture_free(&img_mrbomb_left[i]);
1287       texture_free(&img_mrbomb_right[i]);
1288   }
1289
1290   texture_free(&img_stalactite);
1291   texture_free(&img_stalactite_broken);
1292
1293   texture_free(&img_box_full);
1294   texture_free(&img_box_empty);
1295
1296   texture_free(&img_water);
1297   for (i = 0; i < 3; i++)
1298     texture_free(&img_waves[i]);
1299
1300   texture_free(&img_pole);
1301   texture_free(&img_poletop);
1302
1303   for (i = 0; i < 2; i++)
1304     texture_free(&img_flag[i]);
1305
1306   texture_free(&img_mints);
1307   texture_free(&img_coffee);
1308
1309   for (i = 0; i < 4; i++)
1310     {
1311       texture_free(&img_distro[i]);
1312       texture_free(&img_cloud[0][i]);
1313       texture_free(&img_cloud[1][i]);
1314     }
1315
1316   texture_free(&img_golden_herring);
1317
1318   for (i = 0; i < NUM_SOUNDS; i++)
1319     free_chunk(sounds[i]);
1320
1321   /* free the herring song */
1322   free_music( herring_song );
1323 }
1324
1325
1326 /* Draw a tile on the screen: */
1327
1328 void drawshape(float x, float y, unsigned int c)
1329 {
1330   if (c != 0)
1331     {
1332       Tile* ptile = TileManager::instance()->get(c);
1333       if(ptile)
1334         {
1335           if(ptile->images.size() > 1)
1336             {
1337               texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y);
1338             }
1339           else if (ptile->images.size() == 1)
1340             {
1341               texture_draw(&ptile->images[0],x,y);
1342             }
1343           else
1344             {
1345               printf("Tile not dravable %u\n", c);
1346             }
1347         }
1348     }
1349
1350   /*
1351   if (c == 'X' || c == 'x')
1352     texture_draw(&img_brick[0], x, y);
1353   else if (c == 'Y' || c == 'y')
1354     texture_draw(&img_brick[1], x, y);
1355   else if (c == 'A' || c =='B' || c == '!')
1356     texture_draw(&img_box_full, x, y);
1357   else if (c == 'a')
1358     texture_draw(&img_box_empty, x, y);
1359   else if (c >= 'C' && c <= 'F')
1360     texture_draw(&img_cloud[0][c - 'C'], x, y);
1361   else if (c >= 'c' && c <= 'f')
1362     texture_draw(&img_cloud[1][c - 'c'], x, y);
1363   else if (c >= 'G' && c <= 'J')
1364     texture_draw(&img_bkgd_tile[0][c - 'G'], x, y);
1365   else if (c >= 'g' && c <= 'j')
1366     texture_draw(&img_bkgd_tile[1][c - 'g'], x, y);
1367   else if (c == '#')
1368     texture_draw(&img_solid[0], x, y);
1369   else if (c == '[')
1370     texture_draw(&img_solid[1], x, y);
1371   else if (c == '=')
1372     texture_draw(&img_solid[2], x, y);
1373   else if (c == ']')
1374     texture_draw(&img_solid[3], x, y);
1375   else if (c == '$')
1376     {
1377       z = (global_frame_counter / 2) % 6;
1378
1379       if (z < 4)
1380         texture_draw(&img_distro[z], x, y);
1381       else if (z == 4)
1382         texture_draw(&img_distro[2], x, y);
1383       else if (z == 5)
1384         texture_draw(&img_distro[1], x, y);
1385     }
1386   else if (c == '^')
1387     {
1388       z = (global_frame_counter / 3) % 3;
1389
1390       texture_draw(&img_waves[z], x, y);
1391     }
1392   else if (c == '*')
1393     texture_draw(&img_poletop, x, y);
1394   else if (c == '|')
1395     {
1396       texture_draw(&img_pole, x, y);
1397
1398     }
1399   else if (c == '\\')
1400     {
1401       z = (global_frame_counter / 3) % 2;
1402
1403       texture_draw(&img_flag[z], x + 16, y);
1404     }
1405   else if (c == '&')
1406     texture_draw(&img_water, x, y);*/
1407
1408 }
1409
1410
1411 /* What shape is at some position? */
1412 unsigned int shape(float x, float y)
1413 {
1414
1415   int xx, yy;
1416   unsigned int c;
1417
1418   yy = ((int)y / 32);
1419   xx = ((int)x / 32);
1420
1421   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1422     {
1423       c = current_level.ia_tiles[yy][xx];
1424     }
1425   else
1426     c = 0;
1427
1428   return(c);
1429 }
1430
1431 Tile* gettile(float x, float y)
1432 {
1433   return TileManager::instance()->get(shape(x, y));
1434 }
1435
1436 bool issolid(float x, float y)
1437 {
1438   Tile* tile = TileManager::instance()->get
1439                (shape(x,y));
1440   if(tile)
1441     {
1442       if(tile->solid == true)
1443         return true;
1444       else
1445         return false;
1446     }
1447   else
1448     {
1449       return false;
1450     }
1451 }
1452
1453 /* Is it a brick? */
1454
1455 bool isbrick(float x, float y)
1456 {
1457   Tile* tile = TileManager::instance()->get
1458                (shape(x,y));
1459   if(tile)
1460     {
1461       if(tile->brick == true)
1462         return true;
1463       else
1464         return false;
1465     }
1466   else
1467     {
1468       return false;
1469     }
1470 }
1471
1472
1473 /* Is it ice? */
1474
1475 bool isice(float x, float y)
1476 {
1477   Tile* tile = TileManager::instance()->get
1478                (shape(x,y));
1479   if(tile)
1480     {
1481       if(tile->ice == true)
1482         return true;
1483       else
1484         return false;
1485     }
1486   else
1487     {
1488       return false;
1489     }
1490 }
1491
1492 /* Is it a full box? */
1493
1494 bool isfullbox(float x, float y)
1495 {
1496   Tile* tile = TileManager::instance()->get
1497                (shape(x,y));
1498   if(tile)
1499     {
1500       if(tile->fullbox == true)
1501         return true;
1502       else
1503         return false;
1504     }
1505   else
1506     {
1507       return false;
1508     }
1509 }
1510
1511 bool isdistro(float x, float y)
1512 {
1513   Tile* tile = TileManager::instance()->get(shape(x,y));
1514   return tile && tile->distro;
1515 }
1516
1517 /* Break a brick: */
1518
1519 void trybreakbrick(float x, float y)
1520 {
1521   Tile* tile = gettile(x, y);
1522   if (tile->brick)
1523     {
1524       if (tile->data > 0)
1525         {
1526           /* Get a distro from it: */
1527           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1528                             (int)(y / 32) * 32);
1529
1530           if (!counting_distros)
1531             {
1532               counting_distros = true;
1533               distro_counter = 50;
1534             }
1535
1536           if (distro_counter <= 0)
1537             level_change(&current_level,x, y, TM_IA, tile->next_tile2);
1538
1539           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1540           score = score + SCORE_DISTRO;
1541           distros++;
1542         }
1543       else
1544         {
1545           /* Get rid of it: */
1546           level_change(&current_level,x, y, TM_IA, tile->next_tile);
1547         }
1548
1549
1550       /* Replace it with broken bits: */
1551
1552       add_broken_brick(((int)(x + 1) / 32) * 32,
1553                        (int)(y / 32) * 32);
1554
1555
1556       /* Get some score: */
1557
1558       play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1559       score = score + SCORE_BRICK;
1560     }
1561 }
1562
1563
1564 /* Bounce a brick: */
1565
1566 void bumpbrick(float x, float y)
1567 {
1568   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1569                    (int)(y / 32) * 32);
1570
1571   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1572
1573 }
1574
1575
1576 /* Empty a box: */
1577 void tryemptybox(float x, float y, int col_side)
1578 {
1579   Tile* tile = gettile(x,y);
1580   if (!tile->fullbox)
1581     return;
1582
1583   // according to the collision side, set the upgrade direction
1584   if(col_side == LEFT)
1585     col_side = RIGHT;
1586   else
1587     col_side = LEFT;
1588
1589   switch(tile->data)
1590     {
1591     case 1: //'A':      /* Box with a distro! */
1592       add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1593       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1594       score = score + SCORE_DISTRO;
1595       distros++;
1596       break;
1597
1598     case 2: // 'B':      /* Add an upgrade! */
1599       if (tux.size == SMALL)     /* Tux is small, add mints! */
1600         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1601       else     /* Tux is big, add coffee: */
1602         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1603       play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1604       break;
1605
1606     case 3:// '!':     /* Add a golden herring */
1607       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1608       break;
1609     default:
1610       break;
1611     }
1612
1613   /* Empty the box: */
1614   level_change(&current_level,x, y, TM_IA, tile->next_tile);
1615 }
1616
1617 /* Try to grab a distro: */
1618 void trygrabdistro(float x, float y, int bounciness)
1619 {
1620   Tile* tile = gettile(x, y);
1621   if (tile && tile->distro)
1622     {
1623       level_change(&current_level,x, y, TM_IA, tile->next_tile);
1624       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1625
1626       if (bounciness == BOUNCE)
1627         {
1628           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1629                             (int)(y / 32) * 32);
1630         }
1631
1632       score = score + SCORE_DISTRO;
1633       distros++;
1634     }
1635 }
1636
1637 /* Try to bump a bad guy from below: */
1638 void trybumpbadguy(float x, float y)
1639 {
1640   /* Bad guys: */
1641   for (unsigned int i = 0; i < bad_guys.size(); i++)
1642     {
1643       if (bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1644           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1645         {
1646           bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_BUMP);
1647         }
1648     }
1649
1650
1651   /* Upgrades: */
1652   for (unsigned int i = 0; i < upgrades.size(); i++)
1653     {
1654       if (upgrades[i].base.height == 32 &&
1655           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1656           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1657         {
1658           upgrades[i].base.xm = -upgrades[i].base.xm;
1659           upgrades[i].base.ym = -8;
1660           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1661         }
1662     }
1663 }
1664
1665 /* (Status): */
1666 void drawstatus(void)
1667 {
1668   char str[60];
1669
1670   sprintf(str, "%d", score);
1671   text_draw(&white_text, "SCORE", 0, 0, 1);
1672   text_draw(&gold_text, str, 96, 0, 1);
1673
1674   if(st_gl_mode != ST_GL_TEST)
1675     {
1676       sprintf(str, "%d", hs_score);
1677       text_draw(&white_text, "HIGH", 0, 20, 1);
1678       text_draw(&gold_text, str, 96, 20, 1);
1679     }
1680   else
1681     {
1682       text_draw(&white_text,"Press ESC To Return",0,20,1);
1683     }
1684
1685   if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1686     {
1687       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1688       text_draw(&white_text, "TIME", 224, 0, 1);
1689       text_draw(&gold_text, str, 304, 0, 1);
1690     }
1691
1692   sprintf(str, "%d", distros);
1693   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1694   text_draw(&gold_text, str, 608, 0, 1);
1695
1696   text_draw(&white_text, "LIVES", screen->h, 20, 1);
1697
1698   if(show_fps)
1699     {
1700       sprintf(str, "%2.1f", fps_fps);
1701       text_draw(&white_text, "FPS", screen->h, 40, 1);
1702       text_draw(&gold_text, str, screen->h + 60, 40, 1);
1703     }
1704
1705   for(int i=0; i < tux.lives; ++i)
1706     {
1707       texture_draw(&tux_life,565+(18*i),20);
1708     }
1709 }
1710
1711
1712 void drawendscreen(void)
1713 {
1714   char str[80];
1715
1716   clearscreen(0, 0, 0);
1717
1718   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1719
1720   sprintf(str, "SCORE: %d", score);
1721   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1722
1723   sprintf(str, "DISTROS: %d", distros);
1724   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1725
1726   flipscreen();
1727   SDL_Delay(2000);
1728 }
1729
1730 void drawresultscreen(void)
1731 {
1732   char str[80];
1733
1734   clearscreen(0, 0, 0);
1735
1736   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1737
1738   sprintf(str, "SCORE: %d", score);
1739   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1740
1741   sprintf(str, "DISTROS: %d", distros);
1742   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1743
1744   flipscreen();
1745   SDL_Delay(2000);
1746 }
1747
1748 void savegame(int slot)
1749 {
1750   char savefile[1024];
1751   FILE* fi;
1752   unsigned int ui;
1753
1754   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1755
1756   fi = fopen(savefile, "wb");
1757
1758   if (fi == NULL)
1759     {
1760       fprintf(stderr, "Warning: I could not open the slot file ");
1761     }
1762   else
1763     {
1764       fputs(level_subset, fi);
1765       fputs("\n", fi);
1766       fwrite(&level,sizeof(int),1,fi);
1767       fwrite(&score,sizeof(int),1,fi);
1768       fwrite(&distros,sizeof(int),1,fi);
1769       fwrite(&scroll_x,sizeof(float),1,fi);
1770       fwrite(&tux,sizeof(Player),1,fi);
1771       timer_fwrite(&tux.invincible_timer,fi);
1772       timer_fwrite(&tux.skidding_timer,fi);
1773       timer_fwrite(&tux.safe_timer,fi);
1774       timer_fwrite(&tux.frame_timer,fi);
1775       timer_fwrite(&time_left,fi);
1776       ui = st_get_ticks();
1777       fwrite(&ui,sizeof(int),1,fi);
1778     }
1779   fclose(fi);
1780
1781 }
1782
1783 void loadgame(int slot)
1784 {
1785   char savefile[1024];
1786   char str[100];
1787   FILE* fi;
1788   unsigned int ui;
1789
1790   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1791
1792   fi = fopen(savefile, "rb");
1793
1794   if (fi == NULL)
1795     {
1796       fprintf(stderr, "Warning: I could not open the slot file ");
1797
1798     }
1799   else
1800     {
1801       fgets(str, 100, fi);
1802       strcpy(level_subset, str);
1803       level_subset[strlen(level_subset)-1] = '\0';
1804       fread(&level,sizeof(int),1,fi);
1805
1806       set_defaults();
1807       level_free(&current_level);
1808       if(level_load(&current_level,level_subset,level) != 0)
1809         exit(1);
1810       arrays_free();
1811       arrays_init();
1812       activate_bad_guys();
1813       activate_particle_systems();
1814       level_free_gfx();
1815       level_load_gfx(&current_level);
1816       level_free_song();
1817       level_load_song(&current_level);
1818       levelintro();
1819       update_time = st_get_ticks();
1820
1821       fread(&score,sizeof(int),1,fi);
1822       fread(&distros,sizeof(int),1,fi);
1823       fread(&scroll_x,sizeof(float),1,fi);
1824       fread(&tux, sizeof(Player), 1, fi);
1825       timer_fread(&tux.invincible_timer,fi);
1826       timer_fread(&tux.skidding_timer,fi);
1827       timer_fread(&tux.safe_timer,fi);
1828       timer_fread(&tux.frame_timer,fi);
1829       timer_fread(&time_left,fi);
1830       fread(&ui,sizeof(int),1,fi);
1831       tux.hphysic.start_time += st_get_ticks() - ui;
1832       tux.vphysic.start_time += st_get_ticks() - ui;
1833       fclose(fi);
1834     }
1835
1836 }
1837
1838 void slotinfo(char **pinfo, int slot)
1839 {
1840   FILE* fi;
1841   char slotfile[1024];
1842   char tmp[200];
1843   char str[5];
1844   int slot_level;
1845   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1846
1847   fi = fopen(slotfile, "rb");
1848
1849   sprintf(tmp,"Slot %d - ",slot);
1850
1851   if (fi == NULL)
1852     {
1853       strcat(tmp,"Free");
1854     }
1855   else
1856     {
1857       fgets(str, 100, fi);
1858       str[strlen(str)-1] = '\0';
1859       strcat(tmp, str);
1860       strcat(tmp, " / Level:");
1861       fread(&slot_level,sizeof(int),1,fi);
1862       sprintf(str,"%d",slot_level);
1863       strcat(tmp,str);
1864       fclose(fi);
1865     }
1866
1867   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1868   strcpy(*pinfo,tmp);
1869 }
1870