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