fixed save/load-game.
[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)
1528 {
1529   if (isfullbox(x, y))
1530     {
1531       if (shape(x, y) == 'A')
1532         {
1533
1534           /* Box with a distro! */
1535
1536           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1537                             (int)(y / 32) * 32 - 32);
1538
1539           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1540           score = score + SCORE_DISTRO;
1541           distros++;
1542         }
1543       else if (shape(x, y) == 'B')
1544         {
1545           /* Add an upgrade! */
1546
1547           if (tux.size == SMALL)
1548             {
1549               /* Tux is small, add mints! */
1550
1551               add_upgrade((int)((x + 1) / 32) * 32,
1552                           (int)(y / 32) * 32 - 32,
1553                           UPGRADE_MINTS);
1554             }
1555           else
1556             {
1557               /* Tux is big, add coffee: */
1558
1559               add_upgrade((int)((x + 1) / 32) * 32,
1560                           (int)(y / 32) * 32 - 32,
1561                           UPGRADE_COFFEE);
1562             }
1563
1564           play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1565         }
1566       else if (shape(x, y) == '!')
1567         {
1568           /* Add a golden herring */
1569
1570           add_upgrade((int)((x + 1) / 32) * 32,
1571                       (int)(y / 32) * 32 - 32,
1572                       UPGRADE_HERRING);
1573         }
1574
1575       /* Empty the box: */
1576
1577       level_change(&current_level,x, y, 'a');
1578     }
1579 }
1580
1581
1582 /* Try to grab a distro: */
1583
1584 void trygrabdistro(float x, float y, int bounciness)
1585 {
1586   if (shape(x, y) == '$')
1587     {
1588       level_change(&current_level,x, y, '.');
1589       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1590
1591       if (bounciness == BOUNCE)
1592         {
1593           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1594                             (int)(y / 32) * 32);
1595         }
1596
1597       score = score + SCORE_DISTRO;
1598       distros++;
1599     }
1600 }
1601
1602 /* Try to bump a bad guy from below: */
1603
1604 void trybumpbadguy(float x, float y)
1605 {
1606   int i;
1607
1608
1609   /* Bad guys: */
1610
1611   for (i = 0; i < num_bad_guys; i++)
1612     {
1613       if (bad_guys[i].base.alive &&
1614           bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1615           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1616         {
1617           if (bad_guys[i].kind == BAD_BSOD ||
1618               bad_guys[i].kind == BAD_LAPTOP)
1619             {
1620               bad_guys[i].dying = FALLING;
1621               bad_guys[i].base.ym = -8;
1622               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1623             }
1624         }
1625     }
1626
1627
1628   /* Upgrades: */
1629
1630   for (i = 0; i < num_upgrades; i++)
1631     {
1632       if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1633           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1634           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1635         {
1636           upgrades[i].base.xm = -upgrades[i].base.xm;
1637           upgrades[i].base.ym = -8;
1638           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1639         }
1640     }
1641 }
1642
1643 /* (Status): */
1644 void drawstatus(void)
1645 {
1646   int i;
1647
1648   sprintf(str, "%d", score);
1649   text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1650   text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1651
1652   if(st_gl_mode != ST_GL_TEST)
1653     {
1654       sprintf(str, "%d", hs_score);
1655       text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1656       text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1657     }
1658   else
1659     {
1660       text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1661     }
1662
1663   if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1664     {
1665       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1666       text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1667       text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1668     }
1669
1670   sprintf(str, "%d", distros);
1671   text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1672   text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1673
1674   text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1675
1676   if(show_fps)
1677     {
1678       sprintf(str, "%2.1f", fps_fps);
1679       text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1680       text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1681     }
1682
1683   for(i=0; i < tux.lives; ++i)
1684     {
1685       texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1686     }
1687 }
1688
1689
1690 void drawendscreen(void)
1691 {
1692   char str[80];
1693
1694   clearscreen(0, 0, 0);
1695
1696   text_drawf(&blue_text, "GAMEOVER", 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 drawresultscreen(void)
1709 {
1710   char str[80];
1711
1712   clearscreen(0, 0, 0);
1713
1714   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1715
1716   sprintf(str, "SCORE: %d", score);
1717   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1718
1719   sprintf(str, "DISTROS: %d", distros);
1720   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1721
1722   flipscreen();
1723   SDL_Delay(2000);
1724 }
1725
1726 void savegame(int slot)
1727 {
1728   char savefile[1024];
1729   FILE* fi;
1730   unsigned int ui;
1731
1732   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1733
1734   fi = fopen(savefile, "wb");
1735
1736   if (fi == NULL)
1737     {
1738       fprintf(stderr, "Warning: I could not open the slot file ");
1739
1740     }
1741   else
1742     {
1743       fputs(level_subset, fi);
1744       fputs("\n", fi);
1745       fwrite(&level,sizeof(int),1,fi);
1746       fwrite(&score,sizeof(int),1,fi);
1747       fwrite(&distros,sizeof(int),1,fi);
1748       fwrite(&scroll_x,sizeof(float),1,fi);
1749       fwrite(&tux,sizeof(player_type),1,fi);
1750       timer_fwrite(&tux.invincible_timer,fi);
1751       printf("Time inv LEFT: %d\n",timer_get_left(&tux.invincible_timer));
1752       timer_fwrite(&tux.skidding_timer,fi);
1753       timer_fwrite(&tux.safe_timer,fi);
1754       timer_fwrite(&tux.frame_timer,fi);
1755       timer_fwrite(&time_left,fi);
1756       printf("Time LEFT: %d\n",timer_get_left(&time_left));
1757       ui = st_get_ticks();
1758       fwrite(&ui,sizeof(int),1,fi);
1759     }
1760   fclose(fi);
1761
1762 }
1763
1764 void loadgame(int slot)
1765 {
1766   char savefile[1024];
1767   char str[100];
1768   FILE* fi;
1769   unsigned int ui;
1770
1771   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1772
1773   fi = fopen(savefile, "rb");
1774
1775   if (fi == NULL)
1776     {
1777       fprintf(stderr, "Warning: I could not open the slot file ");
1778
1779     }
1780   else
1781     {
1782
1783
1784       fgets(str, 100, fi);
1785       strcpy(level_subset, str);
1786       level_subset[strlen(level_subset)-1] = '\0';
1787       fread(&level,sizeof(int),1,fi);
1788
1789       set_defaults();
1790       level_free(&current_level);
1791       if(level_load(&current_level,level_subset,level) != 0)
1792         exit(1);
1793       arrays_free();
1794       arrays_init();
1795       activate_bad_guys();
1796       level_free_gfx();
1797       level_load_gfx(&current_level);
1798       level_free_song();
1799       level_load_song(&current_level);
1800       levelintro();
1801       update_time = st_get_ticks();
1802
1803       fread(&score,sizeof(int),1,fi);
1804       fread(&distros,sizeof(int),1,fi);
1805       fread(&scroll_x,sizeof(float),1,fi);
1806       fread(&tux,sizeof(player_type),1,fi);
1807       timer_fread(&tux.invincible_timer,fi);
1808       printf("Time inv LEFT: %d - %d\n",timer_get_left(&tux.invincible_timer),tux.invincible_timer.time);
1809       timer_fread(&tux.skidding_timer,fi);
1810       timer_fread(&tux.safe_timer,fi);
1811       timer_fread(&tux.frame_timer,fi);
1812       timer_fread(&time_left,fi);
1813       printf("Time LEFT: %d\n",timer_get_left(&time_left));
1814       fread(&ui,sizeof(int),1,fi);
1815       tux.hphysic.start_time += st_get_ticks() - ui;
1816       tux.vphysic.start_time += st_get_ticks() - ui;
1817       fclose(fi);
1818     }
1819
1820 }
1821
1822 void slotinfo(char **pinfo, int slot)
1823 {
1824   FILE* fi;
1825   char slotfile[1024];
1826   char tmp[200];
1827   char str[5];
1828   int slot_level;
1829   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1830
1831   fi = fopen(slotfile, "rb");
1832
1833   sprintf(tmp,"Slot %d - ",slot);
1834
1835   if (fi == NULL)
1836     {
1837       strcat(tmp,"Free");
1838     }
1839   else
1840     {
1841       fgets(str, 100, fi);
1842       str[strlen(str)-1] = '\0';
1843       strcat(tmp, str);
1844       strcat(tmp, " / Level:");
1845       fread(&slot_level,sizeof(int),1,fi);
1846       sprintf(str,"%d",slot_level);
1847       strcat(tmp,str);
1848       fclose(fi);
1849     }
1850
1851   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1852   strcpy(*pinfo,tmp);
1853
1854 }
1855