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