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