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