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