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