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