6 by Bill Kendrick & Tobias Glaesser
7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - February 1st, 2004
23 #include <sys/types.h>
32 #include "high_scores.h"
40 #include "collision.h"
42 /* extern variables */
44 st_level current_level;
45 int game_started = NO;
47 /* Local variables: */
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;
53 static char level_subset[100];
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;
62 /* Local function prototypes: */
64 void levelintro(void);
65 void loadshared(void);
66 void unloadshared(void);
67 void drawstatus(void);
68 void drawendscreen(void);
69 void drawresultscreen(void);
71 #define JOYSTICK_DEAD_ZONE 4096
79 sprintf(str, "LEVEL %d", level);
80 text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
82 sprintf(str, "%s", current_level.name);
83 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
85 sprintf(str, "TUX x %d", tux.lives);
86 text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
94 void start_timers(void)
96 timer_start(&time_left,current_level.time_left*1000);
97 st_pause_ticks_init();
98 update_time = st_get_ticks();
101 void activate_bad_guys(void)
105 /* Activate bad guys: */
107 for (y = 0; y < 15; y++)
109 for (x = 0; x < current_level.width; x++)
111 if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
113 add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
114 current_level.tiles[y][x] = '.';
121 /* --- GAME EVENT! --- */
123 void game_event(void)
125 while (SDL_PollEvent(&event))
129 case SDL_QUIT: /* Quit event - quit: */
132 case SDL_KEYDOWN: /* A keypress! */
133 key = event.key.keysym.sym;
135 /* Check for menu-events, if the menu is shown */
137 menu_event(&event.key.keysym);
139 if(player_key_event(&tux,key,DOWN))
144 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
147 if(st_gl_mode == ST_GL_TEST)
151 menu_set_current(&game_menu);
153 st_pause_ticks_stop();
157 menu_set_current(&game_menu);
159 st_pause_ticks_start();
167 case SDL_KEYUP: /* A keyrelease! */
168 key = event.key.keysym.sym;
170 if(player_key_event(&tux,key,UP))
181 st_pause_ticks_stop();
186 st_pause_ticks_start();
191 if(debug_mode == YES)
193 tux.size = !tux.size;
196 tux.base.height = 64;
199 tux.base.height = 32;
203 if(debug_mode == YES)
207 if(debug_mode == YES)
211 if(debug_mode == YES)
215 if(debug_mode == YES)
216 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
219 if(debug_mode == YES)
223 if(debug_mode == YES)
237 case SDL_JOYAXISMOTION:
238 switch(event.jaxis.axis)
241 if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
242 tux.input.left = DOWN;
243 else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
246 if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
247 tux.input.right = DOWN;
248 else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
249 tux.input.right = UP;
252 if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
253 tux.input.down = DOWN;
254 else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
257 /* Handle joystick for the menu */
260 if(tux.input.down == DOWN)
261 menuaction = MN_DOWN;
270 case SDL_JOYBUTTONDOWN:
271 if (event.jbutton.button == JOY_A)
273 else if (event.jbutton.button == JOY_B)
274 tux.input.fire = DOWN;
276 case SDL_JOYBUTTONUP:
277 if (event.jbutton.button == JOY_A)
279 else if (event.jbutton.button == JOY_B)
296 /* --- GAME ACTION! --- */
298 int game_action(void)
302 /* (tux_dying || next_level) */
303 if (tux.dying || next_level)
305 /* Tux either died, or reached the end of a level! */
312 /* End of a level! */
315 if(st_gl_mode != ST_GL_TEST)
322 level_free(¤t_level);
328 player_level_begin(&tux);
334 /* No more lives!? */
338 if(st_gl_mode != ST_GL_TEST)
341 if(st_gl_mode != ST_GL_TEST)
343 if (score > hs_score)
347 level_free(¤t_level);
352 } /* if (lives < 0) */
355 /* Either way, (re-)load the (next) level... */
357 player_level_begin(&tux);
359 level_free(¤t_level);
360 if(level_load(¤t_level,level_subset,level) != 0)
366 level_load_gfx(¤t_level);
368 level_load_song(¤t_level);
369 if(st_gl_mode != ST_GL_TEST)
373 play_current_music();
378 /* Handle bouncy distros: */
380 for (i = 0; i < num_bouncy_distros; i++)
382 bouncy_distro_action(&bouncy_distros[i]);
386 /* Handle broken bricks: */
388 for (i = 0; i < num_broken_bricks; i++)
390 broken_brick_action(&broken_bricks[i]);
394 /* Handle distro counting: */
396 if (counting_distros == YES)
400 if (distro_counter <= 0)
401 counting_distros = -1;
405 /* Handle bouncy bricks: */
407 for (i = 0; i < num_bouncy_bricks; i++)
409 bouncy_brick_action(&bouncy_bricks[i]);
413 /* Handle floating scores: */
415 for (i = 0; i < num_floating_scores; i++)
417 floating_score_action(&floating_scores[i]);
421 /* Handle bullets: */
423 for (i = 0; i < num_bullets; ++i)
425 bullet_action(&bullets[i]);
428 /* Handle upgrades: */
430 for (i = 0; i < num_upgrades; i++)
432 upgrade_action(&upgrades[i]);
436 /* Handle bad guys: */
438 for (i = 0; i < num_bad_guys; i++)
440 badguy_action(&bad_guys[i]);
443 /* Handle all possible collisions. */
449 /* --- GAME DRAW! --- */
457 if (tux.dying && (frame % 4) == 0)
458 clearscreen(255, 255, 255);
459 else if(timer_check(&super_bkgd_timer))
460 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
463 /* Draw the real background */
464 if(current_level.bkgd_image[0] != '\0')
466 s = (int)scroll_x / 30;
467 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
468 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
472 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
476 /* Draw background: */
478 for (y = 0; y < 15; ++y)
480 for (x = 0; x < 21; ++x)
482 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
483 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
488 /* (Bouncy bricks): */
490 for (i = 0; i < num_bouncy_bricks; ++i)
492 bouncy_brick_draw(&bouncy_bricks[i]);
498 for (i = 0; i < num_bad_guys; ++i)
500 badguy_draw(&bad_guys[i]);
509 for (i = 0; i < num_bullets; ++i)
511 bullet_draw(&bullets[i]);
514 /* (Floating scores): */
516 for (i = 0; i < num_floating_scores; ++i)
518 floating_score_draw(&floating_scores[i]);
524 for (i = 0; i < num_upgrades; ++i)
526 upgrade_draw(&upgrades[i]);
530 /* (Bouncy distros): */
532 for (i = 0; i < num_bouncy_distros; ++i)
534 bouncy_distro_draw(&bouncy_distros[i]);
538 /* (Broken bricks): */
540 for (i = 0; i < num_broken_bricks; ++i)
542 broken_brick_draw(&broken_bricks[i]);
551 for(i = 0; i < x; ++i)
553 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);
555 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
556 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
560 menu_process_current();
562 /* (Update it all!) */
569 /* --- GAME LOOP! --- */
571 int gameloop(char * subset, int levelnb, int mode)
573 int fps_cnt, jump, done;
574 timer_type fps_timer, frame_timer;
575 timer_init(&fps_timer, YES);
576 timer_init(&frame_timer, YES);
582 strcpy(level_subset,subset);
588 if(level_load(¤t_level,level_subset,level) != 0)
590 level_load_gfx(¤t_level);
592 level_load_song(¤t_level);
596 if(st_gl_mode != ST_GL_TEST)
601 if(st_gl_mode == ST_GL_PLAY)
605 timer_init(&time_left,YES);
608 if(st_gl_mode == ST_GL_LOAD_GAME)
612 /* --- MAIN GAME LOOP!!! --- */
619 timer_init(&fps_timer,YES);
620 timer_init(&frame_timer,YES);
625 clearscreen(0, 0, 0);
629 play_current_music();
632 while (SDL_PollEvent(&event))
640 /* Calculate the movement-factor */
641 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
642 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
643 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
645 if(!timer_check(&frame_timer))
647 timer_start(&frame_timer,25);
653 tux.input.old_fire = tux.input.fire;
659 if(current_menu == &game_menu)
661 switch (menu_check(&game_menu))
664 st_pause_ticks_stop();
667 update_load_save_game_menu(&save_game_menu, NO);
670 update_load_save_game_menu(&load_game_menu, YES);
673 st_pause_ticks_stop();
678 else if(current_menu == &options_menu)
680 process_options_menu();
682 else if(current_menu == &save_game_menu )
684 process_save_load_game_menu(YES);
686 else if(current_menu == &load_game_menu )
688 process_save_load_game_menu(NO);
693 /* Handle actions: */
695 if(!game_pause && !show_menu)
697 /*float z = frame_ratio;
701 if (game_action() == 0)
703 /* == 0: no more lives */
704 /* == -1: continues */
716 if(debug_mode && debug_fps == YES)
719 /*Draw the current scene to the screen */
720 /*If the machine running the game is too slow
721 skip the drawing of the frame (so the calculations are more precise and
722 the FPS aren't affected).*/
723 /*if( ! fps_fps < 50.0 )
726 jump = YES;*/ /*FIXME: Implement this tweak right.*/
729 /* Time stops in pause mode */
730 if(game_pause || show_menu )
735 /* Set the time the last update and the time of the current update */
736 last_update_time = update_time;
737 update_time = st_get_ticks();
740 /* Pause till next frame, if the machine running the game is too fast: */
741 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
742 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
743 if(last_update_time >= update_time - 12 && jump != YES )
745 /*if((update_time - last_update_time) < 10)
746 SDL_Delay((11 - (update_time - last_update_time))/2);*/
752 if (timer_check(&time_left))
754 /* are we low on time ? */
755 if ((timer_get_left(&time_left) < TIME_WARNING)
756 && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */
758 set_current_music(HURRYUP_MUSIC);
759 play_current_music();
764 player_kill(&tux,KILL);
767 /* Calculate frames per second */
771 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
773 if(!timer_check(&fps_timer))
775 timer_start(&fps_timer,1000);
781 while (!done && !quit);
786 level_free(¤t_level);
797 /* Load graphics/sounds shared between all levels: */
799 void loadshared(void)
802 char * herring_song_path; /* for loading herring song*/
806 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
807 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
808 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
810 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
811 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
812 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
814 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
815 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
816 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
818 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
819 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
820 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
823 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
826 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
829 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
832 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
835 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
838 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
841 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
844 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
846 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
849 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
852 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
855 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
857 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
860 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
863 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
866 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
869 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
872 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
875 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
878 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
880 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
883 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
886 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
889 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
891 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
894 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
897 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
900 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
904 texture_load(&ducktux_right ,DATA_PREFIX
905 "/images/shared/ducktux-right.png",
908 texture_load(&ducktux_left ,DATA_PREFIX
909 "/images/shared/ducktux-left.png",
912 texture_load(&skidtux_right ,DATA_PREFIX
913 "/images/shared/skidtux-right.png",
916 texture_load(&skidtux_left ,DATA_PREFIX
917 "/images/shared/skidtux-left.png",
920 texture_load(&duckfiretux_right ,DATA_PREFIX
921 "/images/shared/duckfiretux-right.png",
924 texture_load(&duckfiretux_left ,DATA_PREFIX
925 "/images/shared/duckfiretux-left.png",
928 texture_load(&skidfiretux_right ,DATA_PREFIX
929 "/images/shared/skidfiretux-right.png",
932 texture_load(&skidfiretux_left ,DATA_PREFIX
933 "/images/shared/skidfiretux-left.png",
939 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
941 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
948 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
950 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
953 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
956 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
962 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
963 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
969 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
971 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
977 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
980 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
983 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
986 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
990 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
993 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
996 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
999 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
1007 texture_load(&img_bsod_left[0] ,DATA_PREFIX
1008 "/images/shared/bsod-left-0.png",
1011 texture_load(&img_bsod_left[1] ,DATA_PREFIX
1012 "/images/shared/bsod-left-1.png",
1015 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1016 "/images/shared/bsod-left-2.png",
1019 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1020 "/images/shared/bsod-left-3.png",
1023 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1024 "/images/shared/bsod-right-0.png",
1027 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1028 "/images/shared/bsod-right-1.png",
1031 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1032 "/images/shared/bsod-right-2.png",
1035 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1036 "/images/shared/bsod-right-3.png",
1039 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1040 "/images/shared/bsod-squished-left.png",
1043 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1044 "/images/shared/bsod-squished-right.png",
1047 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1048 "/images/shared/bsod-falling-left.png",
1051 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1052 "/images/shared/bsod-falling-right.png",
1058 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1059 "/images/shared/laptop-left-0.png",
1062 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1063 "/images/shared/laptop-left-1.png",
1066 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1067 "/images/shared/laptop-left-2.png",
1070 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1071 "/images/shared/laptop-right-0.png",
1074 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1075 "/images/shared/laptop-right-1.png",
1078 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1079 "/images/shared/laptop-right-2.png",
1082 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1083 "/images/shared/laptop-flat-left.png",
1086 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1087 "/images/shared/laptop-flat-right.png",
1090 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1091 "/images/shared/laptop-falling-left.png",
1094 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1095 "/images/shared/laptop-falling-right.png",
1101 texture_load(&img_money_left[0] ,DATA_PREFIX
1102 "/images/shared/bag-left-0.png",
1105 texture_load(&img_money_left[1] ,DATA_PREFIX
1106 "/images/shared/bag-left-1.png",
1109 texture_load(&img_money_right[0] ,DATA_PREFIX
1110 "/images/shared/bag-right-0.png",
1113 texture_load(&img_money_right[1] ,DATA_PREFIX
1114 "/images/shared/bag-right-1.png",
1121 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1122 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1127 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1129 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1136 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1139 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1142 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1145 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1151 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1156 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1160 /* Super background: */
1162 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1166 /* Sound effects: */
1168 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1169 // initialize sounds[i] with the correct pointer's value:
1170 // NULL or something else. And it will be dangerous to
1171 // play with not-initialized pointers.
1172 // This is also true with if (use_music)
1173 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1175 for (i = 0; i < NUM_SOUNDS; i++)
1176 sounds[i] = load_sound(soundfilenames[i]);
1179 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1180 strlen("SALCON.MOD") + 8));
1182 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1184 herring_song = load_song(herring_song_path);
1186 free(herring_song_path);
1191 /* Free shared data: */
1193 void unloadshared(void)
1197 for (i = 0; i < 3; i++)
1199 texture_free(&tux_right[i]);
1200 texture_free(&tux_left[i]);
1201 texture_free(&bigtux_right[i]);
1202 texture_free(&bigtux_left[i]);
1205 texture_free(&bigtux_right_jump);
1206 texture_free(&bigtux_left_jump);
1208 for (i = 0; i < 2; i++)
1210 texture_free(&cape_right[i]);
1211 texture_free(&cape_left[i]);
1212 texture_free(&bigcape_right[i]);
1213 texture_free(&bigcape_left[i]);
1216 texture_free(&ducktux_left);
1217 texture_free(&ducktux_right);
1219 texture_free(&skidtux_left);
1220 texture_free(&skidtux_right);
1222 for (i = 0; i < 4; i++)
1224 texture_free(&img_bsod_left[i]);
1225 texture_free(&img_bsod_right[i]);
1228 texture_free(&img_bsod_squished_left);
1229 texture_free(&img_bsod_squished_right);
1231 texture_free(&img_bsod_falling_left);
1232 texture_free(&img_bsod_falling_right);
1234 for (i = 0; i < 3; i++)
1236 texture_free(&img_laptop_left[i]);
1237 texture_free(&img_laptop_right[i]);
1240 texture_free(&img_laptop_flat_left);
1241 texture_free(&img_laptop_flat_right);
1243 texture_free(&img_laptop_falling_left);
1244 texture_free(&img_laptop_falling_right);
1246 for (i = 0; i < 2; i++)
1248 texture_free(&img_money_left[i]);
1249 texture_free(&img_money_right[i]);
1252 texture_free(&img_box_full);
1253 texture_free(&img_box_empty);
1255 texture_free(&img_water);
1256 for (i = 0; i < 3; i++)
1257 texture_free(&img_waves[i]);
1259 texture_free(&img_pole);
1260 texture_free(&img_poletop);
1262 for (i = 0; i < 2; i++)
1263 texture_free(&img_flag[i]);
1265 texture_free(&img_mints);
1266 texture_free(&img_coffee);
1268 for (i = 0; i < 4; i++)
1270 texture_free(&img_distro[i]);
1271 texture_free(&img_cloud[0][i]);
1272 texture_free(&img_cloud[1][i]);
1275 texture_free(&img_golden_herring);
1277 for (i = 0; i < NUM_SOUNDS; i++)
1278 free_chunk(sounds[i]);
1280 /* free the herring song */
1281 free_music( herring_song );
1285 /* Draw a tile on the screen: */
1287 void drawshape(float x, float y, unsigned char c)
1291 if (c == 'X' || c == 'x')
1292 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1293 else if (c == 'Y' || c == 'y')
1294 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1295 else if (c == 'A' || c =='B' || c == '!')
1296 texture_draw(&img_box_full, x, y, NO_UPDATE);
1298 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1299 else if (c >= 'C' && c <= 'F')
1300 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1301 else if (c >= 'c' && c <= 'f')
1302 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1303 else if (c >= 'G' && c <= 'J')
1304 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1305 else if (c >= 'g' && c <= 'j')
1306 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1308 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1310 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1312 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1314 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1318 z = (frame / 2) % 6;
1321 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1323 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1325 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1329 z = (frame / 3) % 3;
1331 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1334 texture_draw(&img_poletop, x, y, NO_UPDATE);
1337 texture_draw(&img_pole, x, y, NO_UPDATE);
1342 z = (frame / 3) % 2;
1344 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1347 texture_draw(&img_water, x, y, NO_UPDATE);
1351 /* What shape is at some position? */
1353 unsigned char shape(float x, float y)
1362 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1364 c = current_level.tiles[yy][xx];
1375 int issolid(float x, float y)
1377 if (isbrick(x, y) ||
1379 (shape(x, y) == '[') ||
1380 (shape(x, y) == '=') ||
1381 (shape(x, y) == ']') ||
1382 (shape(x, y) == 'A') ||
1383 (shape(x, y) == 'B') ||
1384 (shape(x, y) == '!') ||
1385 (shape(x, y) == 'a'))
1394 int issolid(float x, float y)
1396 if (isbrick(x, y) ||
1397 isbrick(x + 31, y) ||
1400 (shape(x, y) == '[' ||
1401 shape(x + 31, y) == '[') ||
1402 (shape(x, y) == '=' ||
1403 shape(x + 31, y) == '=') ||
1404 (shape(x, y) == ']' ||
1405 shape(x + 31, y) == ']') ||
1406 (shape(x, y) == 'A' ||
1407 shape(x + 31, y) == 'A') ||
1408 (shape(x, y) == 'B' ||
1409 shape(x + 31, y) == 'B') ||
1410 (shape(x, y) == '!' ||
1411 shape(x + 31, y) == '!') ||
1412 (shape(x, y) == 'a' ||
1413 shape(x + 31, y) == 'a'))
1422 /* Is it a brick? */
1424 int isbrick(float x, float y)
1426 if (shape(x, y) == 'X' ||
1427 shape(x, y) == 'x' ||
1428 shape(x, y) == 'Y' ||
1440 int isice(float x, float y)
1442 if (shape(x, y) == '#')
1451 /* Is it a full box? */
1453 int isfullbox(float x, float y)
1455 if (shape(x, y) == 'A' ||
1456 shape(x, y) == 'B' ||
1465 /* Break a brick: */
1467 void trybreakbrick(float x, float y)
1471 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1473 /* Get a distro from it: */
1475 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1476 (int)(y / 32) * 32);
1478 if (counting_distros == NO)
1480 counting_distros = YES;
1481 distro_counter = 50;
1484 if (distro_counter <= 0)
1485 level_change(¤t_level,x, y, 'a');
1487 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1488 score = score + SCORE_DISTRO;
1493 /* Get rid of it: */
1495 level_change(¤t_level,x, y,'.');
1499 /* Replace it with broken bits: */
1501 add_broken_brick(((int)(x + 1) / 32) * 32,
1502 (int)(y / 32) * 32);
1505 /* Get some score: */
1507 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1508 score = score + SCORE_BRICK;
1513 /* Bounce a brick: */
1515 void bumpbrick(float x, float y)
1517 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1518 (int)(y / 32) * 32);
1520 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1527 void tryemptybox(float x, float y, int col_side)
1529 if (!isfullbox(x, y))
1532 // according to the collision side, set the upgrade direction
1534 if(col_side == LEFT)
1541 case 'A': /* Box with a distro! */
1542 add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1543 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1544 score = score + SCORE_DISTRO;
1547 case 'B': /* Add an upgrade! */
1548 if (tux.size == SMALL) /* Tux is small, add mints! */
1549 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1550 else /* Tux is big, add coffee: */
1551 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1552 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1554 case '!': /* Add a golden herring */
1555 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1561 /* Empty the box: */
1562 level_change(¤t_level,x, y, 'a');
1566 /* Try to grab a distro: */
1568 void trygrabdistro(float x, float y, int bounciness)
1570 if (shape(x, y) == '$')
1572 level_change(¤t_level,x, y, '.');
1573 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1575 if (bounciness == BOUNCE)
1577 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1578 (int)(y / 32) * 32);
1581 score = score + SCORE_DISTRO;
1586 /* Try to bump a bad guy from below: */
1588 void trybumpbadguy(float x, float y)
1595 for (i = 0; i < num_bad_guys; i++)
1597 if (bad_guys[i].base.alive &&
1598 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1599 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1601 if (bad_guys[i].kind == BAD_BSOD ||
1602 bad_guys[i].kind == BAD_LAPTOP)
1604 bad_guys[i].dying = FALLING;
1605 bad_guys[i].base.ym = -8;
1606 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1614 for (i = 0; i < num_upgrades; i++)
1616 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1617 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1618 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1620 upgrades[i].base.xm = -upgrades[i].base.xm;
1621 upgrades[i].base.ym = -8;
1622 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1628 void drawstatus(void)
1632 sprintf(str, "%d", score);
1633 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1634 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1636 if(st_gl_mode != ST_GL_TEST)
1638 sprintf(str, "%d", hs_score);
1639 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1640 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1644 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1647 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1649 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1650 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1651 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1654 sprintf(str, "%d", distros);
1655 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1656 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1658 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1662 sprintf(str, "%2.1f", fps_fps);
1663 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1664 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1667 for(i=0; i < tux.lives; ++i)
1669 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1674 void drawendscreen(void)
1678 clearscreen(0, 0, 0);
1680 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1682 sprintf(str, "SCORE: %d", score);
1683 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1685 sprintf(str, "DISTROS: %d", distros);
1686 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1692 void drawresultscreen(void)
1696 clearscreen(0, 0, 0);
1698 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1700 sprintf(str, "SCORE: %d", score);
1701 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1703 sprintf(str, "DISTROS: %d", distros);
1704 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1710 void savegame(int slot)
1712 char savefile[1024];
1716 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1718 fi = fopen(savefile, "wb");
1722 fprintf(stderr, "Warning: I could not open the slot file ");
1727 fputs(level_subset, fi);
1729 fwrite(&level,sizeof(int),1,fi);
1730 fwrite(&score,sizeof(int),1,fi);
1731 fwrite(&distros,sizeof(int),1,fi);
1732 fwrite(&scroll_x,sizeof(float),1,fi);
1733 fwrite(&tux,sizeof(player_type),1,fi);
1734 timer_fwrite(&tux.invincible_timer,fi);
1735 timer_fwrite(&tux.skidding_timer,fi);
1736 timer_fwrite(&tux.safe_timer,fi);
1737 timer_fwrite(&tux.frame_timer,fi);
1738 timer_fwrite(&time_left,fi);
1739 ui = st_get_ticks();
1740 fwrite(&ui,sizeof(int),1,fi);
1746 void loadgame(int slot)
1748 char savefile[1024];
1753 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1755 fi = fopen(savefile, "rb");
1759 fprintf(stderr, "Warning: I could not open the slot file ");
1766 fgets(str, 100, fi);
1767 strcpy(level_subset, str);
1768 level_subset[strlen(level_subset)-1] = '\0';
1769 fread(&level,sizeof(int),1,fi);
1772 level_free(¤t_level);
1773 if(level_load(¤t_level,level_subset,level) != 0)
1777 activate_bad_guys();
1779 level_load_gfx(¤t_level);
1781 level_load_song(¤t_level);
1783 update_time = st_get_ticks();
1785 fread(&score,sizeof(int),1,fi);
1786 fread(&distros,sizeof(int),1,fi);
1787 fread(&scroll_x,sizeof(float),1,fi);
1788 fread(&tux,sizeof(player_type),1,fi);
1789 timer_fread(&tux.invincible_timer,fi);
1790 timer_fread(&tux.skidding_timer,fi);
1791 timer_fread(&tux.safe_timer,fi);
1792 timer_fread(&tux.frame_timer,fi);
1793 timer_fread(&time_left,fi);
1794 fread(&ui,sizeof(int),1,fi);
1795 tux.hphysic.start_time += st_get_ticks() - ui;
1796 tux.vphysic.start_time += st_get_ticks() - ui;
1802 void slotinfo(char **pinfo, int slot)
1805 char slotfile[1024];
1809 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1811 fi = fopen(slotfile, "rb");
1813 sprintf(tmp,"Slot %d - ",slot);
1821 fgets(str, 100, fi);
1822 str[strlen(str)-1] = '\0';
1824 strcat(tmp, " / Level:");
1825 fread(&slot_level,sizeof(int),1,fi);
1826 sprintf(str,"%d",slot_level);
1831 *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));