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