many code-cleanups. merged leveleditor patch from Ricardo Cruz. Fixed bugs. many...
[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
555   game_started = YES;
556
557   st_gl_mode = mode;
558   level = levelnb;
559   strcpy(level_subset,subset);
560
561   if(st_gl_mode != ST_GL_LOAD_GAME)
562     {
563       /* Init the game: */
564       arrays_init();
565       set_defaults();
566
567       if(level_load(&current_level,level_subset,level) != 0)
568         exit(1);
569       level_load_gfx(&current_level);
570       activate_bad_guys();
571       level_load_song(&current_level);
572
573     }
574
575   player_init(&tux);
576
577   if(st_gl_mode != ST_GL_TEST)
578     load_hs();
579
580   loadshared();
581
582   if(st_gl_mode == ST_GL_PLAY)
583     levelintro();
584
585
586   start_timers();
587
588   if(st_gl_mode == ST_GL_LOAD_GAME)
589     loadgame(levelnb);
590
591
592   /* --- MAIN GAME LOOP!!! --- */
593
594   jump = NO;
595   done = 0;
596   quit = 0;
597   frame = 0;
598   game_pause = 0;
599   timer_init(&fps_timer);
600   timer_init(&frame_timer);
601   fps_cnt = 0;
602
603   /* Clear screen: */
604
605   clearscreen(0, 0, 0);
606   updatescreen();
607
608   while (SDL_PollEvent(&event))
609   {}
610
611   game_draw();
612   do
613     {
614       jump = NO;
615
616       /* Calculate the movement-factor */
617       frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
618
619       if(!timer_check(&frame_timer))
620         {
621           timer_start(&frame_timer,25);
622           ++frame;
623         }
624
625
626       /* Handle events: */
627
628       tux.input.old_fire = tux.input.fire;
629
630       /*printf("%lf\n",frame_ratio);*/
631
632       game_event();
633
634       if(show_menu)
635         {
636           if(current_menu == &game_menu)
637             {
638               switch (menu_check(&game_menu))
639                 {
640                 case 0:
641                   st_pause_ticks_stop();
642                   break;
643                 case 1:
644                   update_load_save_game_menu(&save_game_menu, NO);
645                   break;
646                 case 2:
647                   update_load_save_game_menu(&load_game_menu, YES);
648                   break;
649                 case 4:
650                   done = 1;
651                   break;
652                 }
653             }
654           else if(current_menu == &options_menu)
655             {
656               process_options_menu();
657             }
658           else if(current_menu == &save_game_menu )
659             {
660               process_save_load_game_menu(YES);
661             }
662           else if(current_menu == &load_game_menu )
663             {
664               process_save_load_game_menu(NO);
665             }
666         }
667
668
669       /* Handle actions: */
670
671       if(!game_pause && !show_menu)
672         {
673           if (game_action() == 0)
674             {
675               /* == 0: no more lives */
676               /* == -1: continues */
677               return 0;
678             }
679         }
680       else
681         {
682           ++pause_menu_frame;
683           SDL_Delay(50);
684         }
685
686       if(tux.input.down == DOWN)
687         SDL_Delay(30);
688
689       /*Draw the current scene to the screen */
690       /*If the machine running the game is too slow
691         skip the drawing of the frame (so the calculations are more precise and
692       the FPS aren't affected).*/
693       /*if( ! fps_fps < 50.0 )
694       game_draw();
695       else
696       jump = YES;*/ /*FIXME: Implement this tweak right.*/
697       game_draw();
698
699       /* Time stops in pause mode */
700       if(game_pause || show_menu )
701         {
702           continue;
703         }
704
705       /* Set the time the last update and the time of the current update */
706       last_update_time = update_time;
707       update_time = st_get_ticks();
708
709
710       /* Pause till next frame, if the machine running the game is too fast: */
711       /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
712                 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
713       if(last_update_time >= update_time - 12 && jump != YES )
714         SDL_Delay(10);
715       /*if((update_time - last_update_time) < 10)
716           SDL_Delay((11 - (update_time - last_update_time))/2);*/
717
718
719
720       /* Handle time: */
721
722       if (timer_check(&time_left))
723         {
724           /* are we low on time ? */
725           if ((timer_get_left(&time_left) < TIME_WARNING)
726               && (current_music != HURRYUP_MUSIC))
727             {
728               current_music = HURRYUP_MUSIC;
729               /* stop the others music, prepare to play the fast music */
730               if (playing_music())
731                 {
732                   halt_music();
733                 }
734             }
735
736         }
737       else
738         player_kill(&tux,KILL);
739
740
741       /* Keep playing the correct music: */
742
743       if (!playing_music())
744         {
745           play_current_music();
746         }
747
748       /* Calculate frames per second */
749       if(show_fps)
750         {
751           ++fps_cnt;
752           fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
753
754           if(!timer_check(&fps_timer))
755             {
756               timer_start(&fps_timer,1000);
757               fps_cnt = 0;
758             }
759         }
760
761     }
762   while (!done && !quit);
763
764   if (playing_music())
765     halt_music();
766
767   level_free_gfx();
768   level_free(&current_level);
769   level_free_song();
770   unloadshared();
771   arrays_free();
772
773   game_started = NO;
774
775   return(quit);
776 }
777
778
779 /* Load graphics/sounds shared between all levels: */
780
781 void loadshared(void)
782 {
783   int i;
784   char * herring_song_path; /* for loading herring song*/
785
786   /* Tuxes: */
787
788   texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
789   texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
790   texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
791
792   texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
793   texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
794   texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
795
796   texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
797   texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
798   texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
799
800   texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
801   texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
802   texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
803
804
805   texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
806                USE_ALPHA);
807
808   texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
809                USE_ALPHA);
810
811   texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
812                USE_ALPHA);
813
814   texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
815                USE_ALPHA);
816
817   texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
818                USE_ALPHA);
819
820   texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
821                USE_ALPHA);
822
823   texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
824                USE_ALPHA);
825
826   texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
827
828   texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
829                USE_ALPHA);
830
831   texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
832                USE_ALPHA);
833
834   texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
835                USE_ALPHA);
836
837   texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
838
839   texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
840                USE_ALPHA);
841
842   texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
843                USE_ALPHA);
844
845   texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
846                USE_ALPHA);
847
848   texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
849                USE_ALPHA);
850
851   texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
852                USE_ALPHA);
853
854   texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
855                USE_ALPHA);
856
857   texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
858                USE_ALPHA);
859
860   texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
861
862   texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
863                USE_ALPHA);
864
865   texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
866                USE_ALPHA);
867
868   texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
869                USE_ALPHA);
870
871   texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
872
873   texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
874                USE_ALPHA);
875
876   texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
877                USE_ALPHA);
878
879   texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
880                USE_ALPHA);
881
882   texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
883                USE_ALPHA);
884
885
886   texture_load(&ducktux_right ,DATA_PREFIX
887                "/images/shared/ducktux-right.png",
888                USE_ALPHA);
889
890   texture_load(&ducktux_left ,DATA_PREFIX
891                "/images/shared/ducktux-left.png",
892                USE_ALPHA);
893
894   texture_load(&skidtux_right ,DATA_PREFIX
895                "/images/shared/skidtux-right.png",
896                USE_ALPHA);
897
898   texture_load(&skidtux_left ,DATA_PREFIX
899                "/images/shared/skidtux-left.png",
900                USE_ALPHA);
901
902   texture_load(&duckfiretux_right ,DATA_PREFIX
903                "/images/shared/duckfiretux-right.png",
904                USE_ALPHA);
905
906   texture_load(&duckfiretux_left ,DATA_PREFIX
907                "/images/shared/duckfiretux-left.png",
908                USE_ALPHA);
909
910   texture_load(&skidfiretux_right ,DATA_PREFIX
911                "/images/shared/skidfiretux-right.png",
912                USE_ALPHA);
913
914   texture_load(&skidfiretux_left ,DATA_PREFIX
915                "/images/shared/skidfiretux-left.png",
916                USE_ALPHA);
917
918
919   /* Boxes: */
920
921   texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
922                IGNORE_ALPHA);
923   texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
924                IGNORE_ALPHA);
925
926
927   /* Water: */
928
929
930   texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
931
932   texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
933                USE_ALPHA);
934
935   texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
936                USE_ALPHA);
937
938   texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
939                USE_ALPHA);
940
941
942   /* Pole: */
943
944   texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
945   texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
946                USE_ALPHA);
947
948
949   /* Flag: */
950
951   texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
952                USE_ALPHA);
953   texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
954                USE_ALPHA);
955
956
957   /* Cloud: */
958
959   texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
960                USE_ALPHA);
961
962   texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
963                USE_ALPHA);
964
965   texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
966                USE_ALPHA);
967
968   texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
969                USE_ALPHA);
970
971
972   texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
973                USE_ALPHA);
974
975   texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
976                USE_ALPHA);
977
978   texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
979                USE_ALPHA);
980
981   texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
982                USE_ALPHA);
983
984
985   /* Bad guys: */
986
987   /* (BSOD) */
988
989   texture_load(&img_bsod_left[0] ,DATA_PREFIX
990                "/images/shared/bsod-left-0.png",
991                USE_ALPHA);
992
993   texture_load(&img_bsod_left[1] ,DATA_PREFIX
994                "/images/shared/bsod-left-1.png",
995                USE_ALPHA);
996
997   texture_load(&img_bsod_left[2] ,DATA_PREFIX
998                "/images/shared/bsod-left-2.png",
999                USE_ALPHA);
1000
1001   texture_load(&img_bsod_left[3] ,DATA_PREFIX
1002                "/images/shared/bsod-left-3.png",
1003                USE_ALPHA);
1004
1005   texture_load(&img_bsod_right[0] ,DATA_PREFIX
1006                "/images/shared/bsod-right-0.png",
1007                USE_ALPHA);
1008
1009   texture_load(&img_bsod_right[1] ,DATA_PREFIX
1010                "/images/shared/bsod-right-1.png",
1011                USE_ALPHA);
1012
1013   texture_load(&img_bsod_right[2] ,DATA_PREFIX
1014                "/images/shared/bsod-right-2.png",
1015                USE_ALPHA);
1016
1017   texture_load(&img_bsod_right[3] ,DATA_PREFIX
1018                "/images/shared/bsod-right-3.png",
1019                USE_ALPHA);
1020
1021   texture_load(&img_bsod_squished_left ,DATA_PREFIX
1022                "/images/shared/bsod-squished-left.png",
1023                USE_ALPHA);
1024
1025   texture_load(&img_bsod_squished_right ,DATA_PREFIX
1026                "/images/shared/bsod-squished-right.png",
1027                USE_ALPHA);
1028
1029   texture_load(&img_bsod_falling_left ,DATA_PREFIX
1030                "/images/shared/bsod-falling-left.png",
1031                USE_ALPHA);
1032
1033   texture_load(&img_bsod_falling_right ,DATA_PREFIX
1034                "/images/shared/bsod-falling-right.png",
1035                USE_ALPHA);
1036
1037
1038   /* (Laptop) */
1039
1040   texture_load(&img_laptop_left[0] ,DATA_PREFIX
1041                "/images/shared/laptop-left-0.png",
1042                USE_ALPHA);
1043
1044   texture_load(&img_laptop_left[1] ,DATA_PREFIX
1045                "/images/shared/laptop-left-1.png",
1046                USE_ALPHA);
1047
1048   texture_load(&img_laptop_left[2] ,DATA_PREFIX
1049                "/images/shared/laptop-left-2.png",
1050                USE_ALPHA);
1051
1052   texture_load(&img_laptop_right[0] ,DATA_PREFIX
1053                "/images/shared/laptop-right-0.png",
1054                USE_ALPHA);
1055
1056   texture_load(&img_laptop_right[1] ,DATA_PREFIX
1057                "/images/shared/laptop-right-1.png",
1058                USE_ALPHA);
1059
1060   texture_load(&img_laptop_right[2] ,DATA_PREFIX
1061                "/images/shared/laptop-right-2.png",
1062                USE_ALPHA);
1063
1064   texture_load(&img_laptop_flat_left ,DATA_PREFIX
1065                "/images/shared/laptop-flat-left.png",
1066                USE_ALPHA);
1067
1068   texture_load(&img_laptop_flat_right ,DATA_PREFIX
1069                "/images/shared/laptop-flat-right.png",
1070                USE_ALPHA);
1071
1072   texture_load(&img_laptop_falling_left ,DATA_PREFIX
1073                "/images/shared/laptop-falling-left.png",
1074                USE_ALPHA);
1075
1076   texture_load(&img_laptop_falling_right ,DATA_PREFIX
1077                "/images/shared/laptop-falling-right.png",
1078                USE_ALPHA);
1079
1080
1081   /* (Money) */
1082
1083   texture_load(&img_money_left[0] ,DATA_PREFIX
1084                "/images/shared/bag-left-0.png",
1085                USE_ALPHA);
1086
1087   texture_load(&img_money_left[1] ,DATA_PREFIX
1088                "/images/shared/bag-left-1.png",
1089                USE_ALPHA);
1090
1091   texture_load(&img_money_right[0] ,DATA_PREFIX
1092                "/images/shared/bag-right-0.png",
1093                USE_ALPHA);
1094
1095   texture_load(&img_money_right[1] ,DATA_PREFIX
1096                "/images/shared/bag-right-1.png",
1097                USE_ALPHA);
1098
1099
1100
1101   /* Upgrades: */
1102
1103   texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1104   texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1105
1106
1107   /* Weapons: */
1108
1109   texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1110
1111   texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1112                USE_ALPHA);
1113
1114
1115
1116   /* Distros: */
1117
1118   texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1119                USE_ALPHA);
1120
1121   texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1122                USE_ALPHA);
1123
1124   texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1125                USE_ALPHA);
1126
1127   texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1128                USE_ALPHA);
1129
1130
1131   /* Tux life: */
1132
1133   texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1134                USE_ALPHA);
1135
1136   /* Herring: */
1137
1138   texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1139                USE_ALPHA);
1140
1141
1142   /* Super background: */
1143
1144   texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1145                IGNORE_ALPHA);
1146
1147
1148   /* Sound effects: */
1149
1150   /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1151                     // initialize sounds[i] with the correct pointer's value:
1152                     // NULL or something else. And it will be dangerous to
1153                     // play with not-initialized pointers.
1154                     // This is also true with if (use_music)
1155      Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1156   */
1157   for (i = 0; i < NUM_SOUNDS; i++)
1158     sounds[i] = load_sound(soundfilenames[i]);
1159
1160   /* Herring song */
1161   herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1162                                       strlen("SALCON.MOD") + 8));
1163
1164   sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1165
1166   herring_song = load_song(herring_song_path);
1167
1168   free(herring_song_path);
1169
1170 }
1171
1172
1173 /* Free shared data: */
1174
1175 void unloadshared(void)
1176 {
1177   int i;
1178
1179   for (i = 0; i < 3; i++)
1180     {
1181       texture_free(&tux_right[i]);
1182       texture_free(&tux_left[i]);
1183       texture_free(&bigtux_right[i]);
1184       texture_free(&bigtux_left[i]);
1185     }
1186
1187   texture_free(&bigtux_right_jump);
1188   texture_free(&bigtux_left_jump);
1189
1190   for (i = 0; i < 2; i++)
1191     {
1192       texture_free(&cape_right[i]);
1193       texture_free(&cape_left[i]);
1194       texture_free(&bigcape_right[i]);
1195       texture_free(&bigcape_left[i]);
1196     }
1197
1198   texture_free(&ducktux_left);
1199   texture_free(&ducktux_right);
1200
1201   texture_free(&skidtux_left);
1202   texture_free(&skidtux_right);
1203
1204   for (i = 0; i < 4; i++)
1205     {
1206       texture_free(&img_bsod_left[i]);
1207       texture_free(&img_bsod_right[i]);
1208     }
1209
1210   texture_free(&img_bsod_squished_left);
1211   texture_free(&img_bsod_squished_right);
1212
1213   texture_free(&img_bsod_falling_left);
1214   texture_free(&img_bsod_falling_right);
1215
1216   for (i = 0; i < 3; i++)
1217     {
1218       texture_free(&img_laptop_left[i]);
1219       texture_free(&img_laptop_right[i]);
1220     }
1221
1222   texture_free(&img_laptop_flat_left);
1223   texture_free(&img_laptop_flat_right);
1224
1225   texture_free(&img_laptop_falling_left);
1226   texture_free(&img_laptop_falling_right);
1227
1228   for (i = 0; i < 2; i++)
1229     {
1230       texture_free(&img_money_left[i]);
1231       texture_free(&img_money_right[i]);
1232     }
1233
1234   texture_free(&img_box_full);
1235   texture_free(&img_box_empty);
1236
1237   texture_free(&img_water);
1238   for (i = 0; i < 3; i++)
1239     texture_free(&img_waves[i]);
1240
1241   texture_free(&img_pole);
1242   texture_free(&img_poletop);
1243
1244   for (i = 0; i < 2; i++)
1245     texture_free(&img_flag[i]);
1246
1247   texture_free(&img_mints);
1248   texture_free(&img_coffee);
1249
1250   for (i = 0; i < 4; i++)
1251     {
1252       texture_free(&img_distro[i]);
1253       texture_free(&img_cloud[0][i]);
1254       texture_free(&img_cloud[1][i]);
1255     }
1256
1257   texture_free(&img_golden_herring);
1258
1259   for (i = 0; i < NUM_SOUNDS; i++)
1260     free_chunk(sounds[i]);
1261
1262   /* free the herring song */
1263   free_music( herring_song );
1264 }
1265
1266
1267 /* Draw a tile on the screen: */
1268
1269 void drawshape(float x, float y, unsigned char c)
1270 {
1271   int z;
1272
1273   if (c == 'X' || c == 'x')
1274     texture_draw(&img_brick[0], x, y, NO_UPDATE);
1275   else if (c == 'Y' || c == 'y')
1276     texture_draw(&img_brick[1], x, y, NO_UPDATE);
1277   else if (c == 'A' || c =='B' || c == '!')
1278     texture_draw(&img_box_full, x, y, NO_UPDATE);
1279   else if (c == 'a')
1280     texture_draw(&img_box_empty, x, y, NO_UPDATE);
1281   else if (c >= 'C' && c <= 'F')
1282     texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1283   else if (c >= 'c' && c <= 'f')
1284     texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1285   else if (c >= 'G' && c <= 'J')
1286     texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1287   else if (c >= 'g' && c <= 'j')
1288     texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1289   else if (c == '#')
1290     texture_draw(&img_solid[0], x, y, NO_UPDATE);
1291   else if (c == '[')
1292     texture_draw(&img_solid[1], x, y, NO_UPDATE);
1293   else if (c == '=')
1294     texture_draw(&img_solid[2], x, y, NO_UPDATE);
1295   else if (c == ']')
1296     texture_draw(&img_solid[3], x, y, NO_UPDATE);
1297   else if (c == '$')
1298     {
1299
1300       z = (frame / 2) % 6;
1301
1302       if (z < 4)
1303         texture_draw(&img_distro[z], x, y, NO_UPDATE);
1304       else if (z == 4)
1305         texture_draw(&img_distro[2], x, y, NO_UPDATE);
1306       else if (z == 5)
1307         texture_draw(&img_distro[1], x, y, NO_UPDATE);
1308     }
1309   else if (c == '^')
1310     {
1311       z = (frame / 3) % 3;
1312
1313       texture_draw(&img_waves[z], x, y, NO_UPDATE);
1314     }
1315   else if (c == '*')
1316     texture_draw(&img_poletop, x, y, NO_UPDATE);
1317   else if (c == '|')
1318     {
1319       texture_draw(&img_pole, x, y, NO_UPDATE);
1320
1321       /* Mark this as the end position of the level! */
1322
1323       endpos = (int)x;
1324     }
1325   else if (c == '\\')
1326     {
1327       z = (frame / 3) % 2;
1328
1329       texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1330     }
1331   else if (c == '&')
1332     texture_draw(&img_water, x, y, NO_UPDATE);
1333 }
1334
1335
1336 /* What shape is at some position? */
1337
1338 unsigned char shape(float x, float y)
1339 {
1340
1341   int xx, yy;
1342   unsigned char c;
1343
1344   yy = ((int)y / 32);
1345   xx = ((int)x / 32);
1346
1347   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1348     {
1349       c = current_level.tiles[yy][xx];
1350     }
1351   else
1352     c = '.';
1353
1354   return(c);
1355 }
1356
1357 /* Is is ground? */
1358
1359
1360 int issolid(float x, float y)
1361 {
1362   if (isbrick(x, y) ||
1363       isice(x, y) ||
1364       (shape(x, y) == '[') ||
1365       (shape(x, y) == '=') ||
1366       (shape(x, y) == ']') ||
1367       (shape(x, y) == 'A') ||
1368       (shape(x, y) == 'B') ||
1369       (shape(x, y) == '!') ||
1370       (shape(x, y) == 'a'))
1371     {
1372       return YES;
1373     }
1374
1375   return NO;
1376 }
1377
1378 /*
1379 int issolid(float x, float y)
1380 {
1381   if (isbrick(x, y) ||
1382       isbrick(x + 31, y) ||
1383       isice(x, y) ||
1384       isice(x + 31, y) ||
1385       (shape(x, y) == '[' ||
1386        shape(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) == 'A' ||
1392        shape(x + 31, y) == 'A') ||
1393       (shape(x, y) == 'B' ||
1394        shape(x + 31, y) == 'B') ||
1395       (shape(x, y) == '!' ||
1396        shape(x + 31, y) == '!') ||
1397       (shape(x, y) == 'a' ||
1398        shape(x + 31, y) == 'a'))
1399     {
1400       return YES;
1401     }
1402  
1403   return NO;
1404 }*/
1405
1406
1407 /* Is it a brick? */
1408
1409 int isbrick(float x, float y)
1410 {
1411   if (shape(x, y) == 'X' ||
1412       shape(x, y) == 'x' ||
1413       shape(x, y) == 'Y' ||
1414       shape(x, y) == 'y')
1415     {
1416       return YES;
1417     }
1418
1419   return NO;
1420 }
1421
1422
1423 /* Is it ice? */
1424
1425 int isice(float x, float y)
1426 {
1427   if (shape(x, y) == '#')
1428     {
1429       return YES;
1430     }
1431
1432   return NO;
1433 }
1434
1435
1436 /* Is it a full box? */
1437
1438 int isfullbox(float x, float y)
1439 {
1440   if (shape(x, y) == 'A' ||
1441       shape(x, y) == 'B' ||
1442       shape(x, y) == '!')
1443     {
1444       return YES;
1445     }
1446
1447   return NO;
1448 }
1449
1450 /* Break a brick: */
1451
1452 void trybreakbrick(float x, float y)
1453 {
1454   if (isbrick(x, y))
1455     {
1456       if (shape(x, y) == 'x' || shape(x, y) == 'y')
1457         {
1458           /* Get a distro from it: */
1459
1460           add_bouncy_distro(((x + 1) / 32) * 32,
1461                             (int)(y / 32) * 32);
1462
1463           if (counting_distros == NO)
1464             {
1465               counting_distros = YES;
1466               distro_counter = 50;
1467             }
1468
1469           if (distro_counter <= 0)
1470             level_change(&current_level,x, y, 'a');
1471
1472           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1473           score = score + SCORE_DISTRO;
1474           distros++;
1475         }
1476       else
1477         {
1478           /* Get rid of it: */
1479
1480           level_change(&current_level,x, y,'.');
1481         }
1482
1483
1484       /* Replace it with broken bits: */
1485
1486       add_broken_brick(((x + 1) / 32) * 32,
1487                        (int)(y / 32) * 32);
1488
1489
1490       /* Get some score: */
1491
1492       play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1493       score = score + SCORE_BRICK;
1494     }
1495 }
1496
1497
1498 /* Bounce a brick: */
1499
1500 void bumpbrick(float x, float y)
1501 {
1502   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1503                    (int)(y / 32) * 32);
1504
1505   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1506 }
1507
1508
1509 /* Empty a box: */
1510
1511 void tryemptybox(float x, float y)
1512 {
1513   if (isfullbox(x, y))
1514     {
1515       if (shape(x, y) == 'A')
1516         {
1517
1518           DEBUG_MSG("Here I am");
1519
1520           /* Box with a distro! */
1521
1522           add_bouncy_distro(((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(((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(((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(((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(((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