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