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