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;
61 /* Local function prototypes: */
63 void levelintro(void);
64 void loadshared(void);
65 void unloadshared(void);
66 void drawstatus(void);
67 void drawendscreen(void);
68 void drawresultscreen(void);
76 sprintf(str, "LEVEL %d", level);
77 text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
79 sprintf(str, "%s", current_level.name);
80 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
82 sprintf(str, "TUX x %d", tux.lives);
83 text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
91 void start_timers(void)
93 timer_start(&time_left,current_level.time_left*1000);
94 st_pause_ticks_init();
95 update_time = st_get_ticks();
98 void activate_bad_guys(void)
102 /* Activate bad guys: */
104 for (y = 0; y < 15; y++)
106 for (x = 0; x < current_level.width; x++)
108 if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
110 add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
111 current_level.tiles[y][x] = '.';
118 /* --- GAME EVENT! --- */
120 void game_event(void)
122 while (SDL_PollEvent(&event))
126 case SDL_QUIT: /* Quit event - quit: */
129 case SDL_KEYDOWN: /* A keypress! */
130 key = event.key.keysym.sym;
132 /* Check for menu-events, if the menu is shown */
134 menu_event(&event.key.keysym);
136 if(player_key_event(&tux,key,DOWN))
141 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
144 if(st_gl_mode == ST_GL_TEST)
148 menu_set_current(&game_menu);
150 st_pause_ticks_stop();
154 menu_set_current(&game_menu);
156 st_pause_ticks_start();
164 case SDL_KEYUP: /* A keyrelease! */
165 key = event.key.keysym.sym;
167 if(player_key_event(&tux,key,UP))
178 st_pause_ticks_stop();
183 st_pause_ticks_start();
188 if(debug_mode == YES)
190 tux.size = !tux.size;
193 tux.base.height = 64;
196 tux.base.height = 32;
200 if(debug_mode == YES)
204 if(debug_mode == YES)
208 if(debug_mode == YES)
212 if(debug_mode == YES)
213 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
216 if(debug_mode == YES)
220 if(debug_mode == YES)
229 case SDL_JOYAXISMOTION:
230 switch(event.jaxis.axis)
233 if (event.jaxis.value < -1024)
234 tux.input.left = DOWN;
235 else if (event.jaxis.value > 1024)
238 if (event.jaxis.value > 1024)
239 tux.input.right = DOWN;
240 else if (event.jaxis.value < -1024)
241 tux.input.right = UP;
244 if (event.jaxis.value > 1024)
245 tux.input.down = DOWN;
246 else if (event.jaxis.value < -1024)
249 /* Handle joystick for the menu */
252 if(tux.input.down == DOWN)
253 menuaction = MN_DOWN;
262 case SDL_JOYBUTTONDOWN:
263 if (event.jbutton.button == JOY_A)
265 else if (event.jbutton.button == JOY_B)
266 tux.input.fire = DOWN;
268 case SDL_JOYBUTTONUP:
269 if (event.jbutton.button == JOY_A)
271 else if (event.jbutton.button == JOY_B)
287 /* --- GAME ACTION! --- */
289 int game_action(void)
293 /* (tux_dying || next_level) */
294 if (tux.dying || next_level)
296 /* Tux either died, or reached the end of a level! */
304 /* End of a level! */
307 if(st_gl_mode != ST_GL_TEST)
309 player_level_begin(&tux);
315 /* No more lives!? */
319 if(st_gl_mode != ST_GL_TEST)
322 if(st_gl_mode != ST_GL_TEST)
324 if (score > hs_score)
328 level_free(¤t_level);
333 } /* if (lives < 0) */
336 /* Either way, (re-)load the (next) level... */
338 player_level_begin(&tux);
340 level_free(¤t_level);
341 if(level_load(¤t_level,level_subset,level) != 0)
347 level_load_gfx(¤t_level);
349 level_load_song(¤t_level);
350 if(st_gl_mode != ST_GL_TEST)
357 /* Handle bouncy distros: */
359 for (i = 0; i < num_bouncy_distros; i++)
361 bouncy_distro_action(&bouncy_distros[i]);
365 /* Handle broken bricks: */
367 for (i = 0; i < num_broken_bricks; i++)
369 broken_brick_action(&broken_bricks[i]);
373 /* Handle distro counting: */
375 if (counting_distros == YES)
379 if (distro_counter <= 0)
380 counting_distros = -1;
384 /* Handle bouncy bricks: */
386 for (i = 0; i < num_bouncy_bricks; i++)
388 bouncy_brick_action(&bouncy_bricks[i]);
392 /* Handle floating scores: */
394 for (i = 0; i < num_floating_scores; i++)
396 floating_score_action(&floating_scores[i]);
400 /* Handle bullets: */
402 for (i = 0; i < num_bullets; ++i)
404 bullet_action(&bullets[i]);
407 /* Handle upgrades: */
409 for (i = 0; i < num_upgrades; i++)
411 upgrade_action(&upgrades[i]);
415 /* Handle bad guys: */
417 for (i = 0; i < num_bad_guys; i++)
419 badguy_action(&bad_guys[i]);
422 /* Handle all possible collisions. */
428 /* --- GAME DRAW! --- */
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);
442 /* Draw the real background */
443 if(current_level.bkgd_image[0] != '\0')
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);
451 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
455 /* Draw background: */
457 for (y = 0; y < 15; ++y)
459 for (x = 0; x < 21; ++x)
461 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
462 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
467 /* (Bouncy bricks): */
469 for (i = 0; i < num_bouncy_bricks; ++i)
471 bouncy_brick_draw(&bouncy_bricks[i]);
477 for (i = 0; i < num_bad_guys; ++i)
479 badguy_draw(&bad_guys[i]);
488 for (i = 0; i < num_bullets; ++i)
490 bullet_draw(&bullets[i]);
493 /* (Floating scores): */
495 for (i = 0; i < num_floating_scores; ++i)
497 floating_score_draw(&floating_scores[i]);
503 for (i = 0; i < num_upgrades; ++i)
505 upgrade_draw(&upgrades[i]);
509 /* (Bouncy distros): */
511 for (i = 0; i < num_bouncy_distros; ++i)
513 bouncy_distro_draw(&bouncy_distros[i]);
517 /* (Broken bricks): */
519 for (i = 0; i < num_broken_bricks; ++i)
521 broken_brick_draw(&broken_bricks[i]);
530 for(i = 0; i < x; ++i)
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);
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);
539 menu_process_current();
541 /* (Update it all!) */
548 /* --- GAME LOOP! --- */
550 int gameloop(char * subset, int levelnb, int mode)
552 int fps_cnt, jump, done;
553 timer_type fps_timer, frame_timer;
554 timer_init(&fps_timer, YES);
555 timer_init(&frame_timer, YES);
561 strcpy(level_subset,subset);
563 if(st_gl_mode != ST_GL_LOAD_GAME)
569 if(level_load(¤t_level,level_subset,level) != 0)
571 level_load_gfx(¤t_level);
573 level_load_song(¤t_level);
579 if(st_gl_mode != ST_GL_TEST)
584 if(st_gl_mode == ST_GL_PLAY)
588 timer_init(&time_left,YES);
591 if(st_gl_mode == ST_GL_LOAD_GAME)
595 /* --- MAIN GAME LOOP!!! --- */
602 timer_init(&fps_timer,YES);
603 timer_init(&frame_timer,YES);
608 clearscreen(0, 0, 0);
611 while (SDL_PollEvent(&event))
619 /* Calculate the movement-factor */
620 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
622 if(!timer_check(&frame_timer))
624 timer_start(&frame_timer,25);
631 tux.input.old_fire = tux.input.fire;
633 /*printf("%lf\n",frame_ratio);*/
639 if(current_menu == &game_menu)
641 switch (menu_check(&game_menu))
644 st_pause_ticks_stop();
647 update_load_save_game_menu(&save_game_menu, NO);
650 update_load_save_game_menu(&load_game_menu, YES);
653 st_pause_ticks_stop();
658 else if(current_menu == &options_menu)
660 process_options_menu();
662 else if(current_menu == &save_game_menu )
664 process_save_load_game_menu(YES);
666 else if(current_menu == &load_game_menu )
668 process_save_load_game_menu(NO);
673 /* Handle actions: */
675 if(!game_pause && !show_menu)
677 if (game_action() == 0)
679 /* == 0: no more lives */
680 /* == -1: continues */
690 if(tux.input.down == DOWN)
693 /*Draw the current scene to the screen */
694 /*If the machine running the game is too slow
695 skip the drawing of the frame (so the calculations are more precise and
696 the FPS aren't affected).*/
697 /*if( ! fps_fps < 50.0 )
700 jump = YES;*/ /*FIXME: Implement this tweak right.*/
703 /* Time stops in pause mode */
704 if(game_pause || show_menu )
709 /* Set the time the last update and the time of the current update */
710 last_update_time = update_time;
711 update_time = st_get_ticks();
714 /* Pause till next frame, if the machine running the game is too fast: */
715 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
716 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
717 if(last_update_time >= update_time - 12 && jump != YES )
719 /*if((update_time - last_update_time) < 10)
720 SDL_Delay((11 - (update_time - last_update_time))/2);*/
726 if (timer_check(&time_left))
728 /* are we low on time ? */
729 if ((timer_get_left(&time_left) < TIME_WARNING)
730 && (current_music != HURRYUP_MUSIC))
732 current_music = HURRYUP_MUSIC;
733 /* stop the others music, prepare to play the fast music */
742 player_kill(&tux,KILL);
745 /* Keep playing the correct music: */
747 if (!playing_music())
749 play_current_music();
752 /* Calculate frames per second */
756 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
758 if(!timer_check(&fps_timer))
760 timer_start(&fps_timer,1000);
766 while (!done && !quit);
772 level_free(¤t_level);
783 /* Load graphics/sounds shared between all levels: */
785 void loadshared(void)
788 char * herring_song_path; /* for loading herring song*/
792 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
793 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
794 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
796 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
797 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
798 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
800 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
801 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
802 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
804 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
805 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
806 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
809 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
812 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
815 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
818 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
821 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
824 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
827 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
830 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
832 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
835 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
838 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
841 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
843 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
846 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
849 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
852 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
855 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
858 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
861 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
864 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
866 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
869 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
872 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
875 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
877 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
880 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
883 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
886 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
890 texture_load(&ducktux_right ,DATA_PREFIX
891 "/images/shared/ducktux-right.png",
894 texture_load(&ducktux_left ,DATA_PREFIX
895 "/images/shared/ducktux-left.png",
898 texture_load(&skidtux_right ,DATA_PREFIX
899 "/images/shared/skidtux-right.png",
902 texture_load(&skidtux_left ,DATA_PREFIX
903 "/images/shared/skidtux-left.png",
906 texture_load(&duckfiretux_right ,DATA_PREFIX
907 "/images/shared/duckfiretux-right.png",
910 texture_load(&duckfiretux_left ,DATA_PREFIX
911 "/images/shared/duckfiretux-left.png",
914 texture_load(&skidfiretux_right ,DATA_PREFIX
915 "/images/shared/skidfiretux-right.png",
918 texture_load(&skidfiretux_left ,DATA_PREFIX
919 "/images/shared/skidfiretux-left.png",
925 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
927 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
934 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
936 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
939 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
942 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
948 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
949 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
955 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
957 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
963 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
966 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
969 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
972 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
976 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
979 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
982 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
985 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
993 texture_load(&img_bsod_left[0] ,DATA_PREFIX
994 "/images/shared/bsod-left-0.png",
997 texture_load(&img_bsod_left[1] ,DATA_PREFIX
998 "/images/shared/bsod-left-1.png",
1001 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1002 "/images/shared/bsod-left-2.png",
1005 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1006 "/images/shared/bsod-left-3.png",
1009 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1010 "/images/shared/bsod-right-0.png",
1013 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1014 "/images/shared/bsod-right-1.png",
1017 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1018 "/images/shared/bsod-right-2.png",
1021 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1022 "/images/shared/bsod-right-3.png",
1025 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1026 "/images/shared/bsod-squished-left.png",
1029 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1030 "/images/shared/bsod-squished-right.png",
1033 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1034 "/images/shared/bsod-falling-left.png",
1037 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1038 "/images/shared/bsod-falling-right.png",
1044 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1045 "/images/shared/laptop-left-0.png",
1048 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1049 "/images/shared/laptop-left-1.png",
1052 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1053 "/images/shared/laptop-left-2.png",
1056 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1057 "/images/shared/laptop-right-0.png",
1060 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1061 "/images/shared/laptop-right-1.png",
1064 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1065 "/images/shared/laptop-right-2.png",
1068 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1069 "/images/shared/laptop-flat-left.png",
1072 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1073 "/images/shared/laptop-flat-right.png",
1076 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1077 "/images/shared/laptop-falling-left.png",
1080 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1081 "/images/shared/laptop-falling-right.png",
1087 texture_load(&img_money_left[0] ,DATA_PREFIX
1088 "/images/shared/bag-left-0.png",
1091 texture_load(&img_money_left[1] ,DATA_PREFIX
1092 "/images/shared/bag-left-1.png",
1095 texture_load(&img_money_right[0] ,DATA_PREFIX
1096 "/images/shared/bag-right-0.png",
1099 texture_load(&img_money_right[1] ,DATA_PREFIX
1100 "/images/shared/bag-right-1.png",
1107 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1108 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1113 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1115 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1122 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1125 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1128 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1131 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1137 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1142 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1146 /* Super background: */
1148 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1152 /* Sound effects: */
1154 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1155 // initialize sounds[i] with the correct pointer's value:
1156 // NULL or something else. And it will be dangerous to
1157 // play with not-initialized pointers.
1158 // This is also true with if (use_music)
1159 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1161 for (i = 0; i < NUM_SOUNDS; i++)
1162 sounds[i] = load_sound(soundfilenames[i]);
1165 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1166 strlen("SALCON.MOD") + 8));
1168 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1170 herring_song = load_song(herring_song_path);
1172 free(herring_song_path);
1177 /* Free shared data: */
1179 void unloadshared(void)
1183 for (i = 0; i < 3; i++)
1185 texture_free(&tux_right[i]);
1186 texture_free(&tux_left[i]);
1187 texture_free(&bigtux_right[i]);
1188 texture_free(&bigtux_left[i]);
1191 texture_free(&bigtux_right_jump);
1192 texture_free(&bigtux_left_jump);
1194 for (i = 0; i < 2; i++)
1196 texture_free(&cape_right[i]);
1197 texture_free(&cape_left[i]);
1198 texture_free(&bigcape_right[i]);
1199 texture_free(&bigcape_left[i]);
1202 texture_free(&ducktux_left);
1203 texture_free(&ducktux_right);
1205 texture_free(&skidtux_left);
1206 texture_free(&skidtux_right);
1208 for (i = 0; i < 4; i++)
1210 texture_free(&img_bsod_left[i]);
1211 texture_free(&img_bsod_right[i]);
1214 texture_free(&img_bsod_squished_left);
1215 texture_free(&img_bsod_squished_right);
1217 texture_free(&img_bsod_falling_left);
1218 texture_free(&img_bsod_falling_right);
1220 for (i = 0; i < 3; i++)
1222 texture_free(&img_laptop_left[i]);
1223 texture_free(&img_laptop_right[i]);
1226 texture_free(&img_laptop_flat_left);
1227 texture_free(&img_laptop_flat_right);
1229 texture_free(&img_laptop_falling_left);
1230 texture_free(&img_laptop_falling_right);
1232 for (i = 0; i < 2; i++)
1234 texture_free(&img_money_left[i]);
1235 texture_free(&img_money_right[i]);
1238 texture_free(&img_box_full);
1239 texture_free(&img_box_empty);
1241 texture_free(&img_water);
1242 for (i = 0; i < 3; i++)
1243 texture_free(&img_waves[i]);
1245 texture_free(&img_pole);
1246 texture_free(&img_poletop);
1248 for (i = 0; i < 2; i++)
1249 texture_free(&img_flag[i]);
1251 texture_free(&img_mints);
1252 texture_free(&img_coffee);
1254 for (i = 0; i < 4; i++)
1256 texture_free(&img_distro[i]);
1257 texture_free(&img_cloud[0][i]);
1258 texture_free(&img_cloud[1][i]);
1261 texture_free(&img_golden_herring);
1263 for (i = 0; i < NUM_SOUNDS; i++)
1264 free_chunk(sounds[i]);
1266 /* free the herring song */
1267 free_music( herring_song );
1271 /* Draw a tile on the screen: */
1273 void drawshape(float x, float y, unsigned char c)
1277 if (c == 'X' || c == 'x')
1278 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1279 else if (c == 'Y' || c == 'y')
1280 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1281 else if (c == 'A' || c =='B' || c == '!')
1282 texture_draw(&img_box_full, x, y, NO_UPDATE);
1284 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1285 else if (c >= 'C' && c <= 'F')
1286 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1287 else if (c >= 'c' && c <= 'f')
1288 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1289 else if (c >= 'G' && c <= 'J')
1290 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1291 else if (c >= 'g' && c <= 'j')
1292 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1294 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1296 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1298 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1300 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1304 z = (frame / 2) % 6;
1307 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1309 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1311 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1315 z = (frame / 3) % 3;
1317 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1320 texture_draw(&img_poletop, x, y, NO_UPDATE);
1323 texture_draw(&img_pole, x, y, NO_UPDATE);
1325 /* Mark this as the end position of the level! */
1331 z = (frame / 3) % 2;
1333 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1336 texture_draw(&img_water, x, y, NO_UPDATE);
1340 /* What shape is at some position? */
1342 unsigned char shape(float x, float y)
1351 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1353 c = current_level.tiles[yy][xx];
1364 int issolid(float x, float y)
1366 if (isbrick(x, y) ||
1368 (shape(x, y) == '[') ||
1369 (shape(x, y) == '=') ||
1370 (shape(x, y) == ']') ||
1371 (shape(x, y) == 'A') ||
1372 (shape(x, y) == 'B') ||
1373 (shape(x, y) == '!') ||
1374 (shape(x, y) == 'a'))
1383 int issolid(float x, float y)
1385 if (isbrick(x, y) ||
1386 isbrick(x + 31, y) ||
1389 (shape(x, y) == '[' ||
1390 shape(x + 31, y) == '[') ||
1391 (shape(x, y) == '=' ||
1392 shape(x + 31, y) == '=') ||
1393 (shape(x, y) == ']' ||
1394 shape(x + 31, y) == ']') ||
1395 (shape(x, y) == 'A' ||
1396 shape(x + 31, y) == 'A') ||
1397 (shape(x, y) == 'B' ||
1398 shape(x + 31, y) == 'B') ||
1399 (shape(x, y) == '!' ||
1400 shape(x + 31, y) == '!') ||
1401 (shape(x, y) == 'a' ||
1402 shape(x + 31, y) == 'a'))
1411 /* Is it a brick? */
1413 int isbrick(float x, float y)
1415 if (shape(x, y) == 'X' ||
1416 shape(x, y) == 'x' ||
1417 shape(x, y) == 'Y' ||
1429 int isice(float x, float y)
1431 if (shape(x, y) == '#')
1440 /* Is it a full box? */
1442 int isfullbox(float x, float y)
1444 if (shape(x, y) == 'A' ||
1445 shape(x, y) == 'B' ||
1454 /* Break a brick: */
1456 void trybreakbrick(float x, float y)
1460 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1462 /* Get a distro from it: */
1464 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1465 (int)(y / 32) * 32);
1467 if (counting_distros == NO)
1469 counting_distros = YES;
1470 distro_counter = 50;
1473 if (distro_counter <= 0)
1474 level_change(¤t_level,x, y, 'a');
1476 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1477 score = score + SCORE_DISTRO;
1482 /* Get rid of it: */
1484 level_change(¤t_level,x, y,'.');
1488 /* Replace it with broken bits: */
1490 add_broken_brick(((int)(x + 1) / 32) * 32,
1491 (int)(y / 32) * 32);
1494 /* Get some score: */
1496 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1497 score = score + SCORE_BRICK;
1502 /* Bounce a brick: */
1504 void bumpbrick(float x, float y)
1506 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1507 (int)(y / 32) * 32);
1509 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1515 void tryemptybox(float x, float y)
1517 if (isfullbox(x, y))
1519 if (shape(x, y) == 'A')
1522 /* Box with a distro! */
1524 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1525 (int)(y / 32) * 32 - 32);
1527 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1528 score = score + SCORE_DISTRO;
1531 else if (shape(x, y) == 'B')
1533 /* Add an upgrade! */
1535 if (tux.size == SMALL)
1537 /* Tux is small, add mints! */
1539 add_upgrade((int)((x + 1) / 32) * 32,
1540 (int)(y / 32) * 32 - 32,
1545 /* Tux is big, add coffee: */
1547 add_upgrade((int)((x + 1) / 32) * 32,
1548 (int)(y / 32) * 32 - 32,
1552 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1554 else if (shape(x, y) == '!')
1556 /* Add a golden herring */
1558 add_upgrade((int)((x + 1) / 32) * 32,
1559 (int)(y / 32) * 32 - 32,
1563 /* Empty the box: */
1565 level_change(¤t_level,x, y, 'a');
1570 /* Try to grab a distro: */
1572 void trygrabdistro(float x, float y, int bounciness)
1574 if (shape(x, y) == '$')
1576 level_change(¤t_level,x, y, '.');
1577 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1579 if (bounciness == BOUNCE)
1581 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1582 (int)(y / 32) * 32);
1585 score = score + SCORE_DISTRO;
1590 /* Try to bump a bad guy from below: */
1592 void trybumpbadguy(float x, float y)
1599 for (i = 0; i < num_bad_guys; i++)
1601 if (bad_guys[i].base.alive &&
1602 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1603 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1605 if (bad_guys[i].kind == BAD_BSOD ||
1606 bad_guys[i].kind == BAD_LAPTOP)
1608 bad_guys[i].dying = FALLING;
1609 bad_guys[i].base.ym = -8;
1610 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1618 for (i = 0; i < num_upgrades; i++)
1620 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1621 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1622 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1624 upgrades[i].base.xm = -upgrades[i].base.xm;
1625 upgrades[i].base.ym = -8;
1626 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1632 void drawstatus(void)
1636 sprintf(str, "%d", score);
1637 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1638 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1640 if(st_gl_mode != ST_GL_TEST)
1642 sprintf(str, "%d", hs_score);
1643 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1644 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1648 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1651 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1653 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1654 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1655 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1658 sprintf(str, "%d", distros);
1659 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1660 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1662 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1666 sprintf(str, "%2.1f", fps_fps);
1667 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1668 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1671 for(i=0; i < tux.lives; ++i)
1673 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1678 void drawendscreen(void)
1682 clearscreen(0, 0, 0);
1684 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1686 sprintf(str, "SCORE: %d", score);
1687 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1689 sprintf(str, "DISTROS: %d", distros);
1690 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1696 void drawresultscreen(void)
1700 clearscreen(0, 0, 0);
1702 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1704 sprintf(str, "SCORE: %d", score);
1705 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1707 sprintf(str, "DISTROS: %d", distros);
1708 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1714 void savegame(int slot)
1716 char savefile[1024];
1720 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1722 fi = fopen(savefile, "wb");
1726 fprintf(stderr, "Warning: I could not open the slot file ");
1731 fputs(level_subset, fi);
1733 fwrite(&level,sizeof(int),1,fi);
1734 fwrite(&score,sizeof(int),1,fi);
1735 fwrite(&distros,sizeof(int),1,fi);
1736 fwrite(&tux,sizeof(player_type),1,fi);
1737 fwrite(&scroll_x,sizeof(float),1,fi);
1738 fwrite(&time_left,sizeof(float),1,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 timer_start(&time_left,current_level.time_left*1000);
1784 update_time = st_get_ticks();
1786 fread(&score,sizeof(int),1,fi);
1787 fread(&distros,sizeof(int),1,fi);
1788 fread(&tux,sizeof(player_type),1,fi);
1789 fread(&scroll_x,sizeof(float),1,fi);
1790 fread(&time_left,sizeof(float),1,fi);
1791 fread(&ui,sizeof(int),1,fi);
1792 time_left.time += st_get_ticks() - ui;
1793 tux.invincible_timer.time += st_get_ticks() - ui;
1794 tux.skidding_timer.time += st_get_ticks() - ui;
1795 tux.safe_timer.time += st_get_ticks() - ui;
1796 tux.vphysic.start_time += st_get_ticks() - ui;
1797 tux.hphysic.start_time += st_get_ticks() - ui;
1798 tux.vphysic.start_time += st_get_ticks() - ui;
1804 void slotinfo(char **pinfo, int slot)
1807 char slotfile[1024];
1811 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1813 fi = fopen(slotfile, "rb");
1815 sprintf(tmp,"Slot %d - ",slot);
1823 fgets(str, 100, fi);
1824 str[strlen(str)-1] = '\0';
1826 strcat(tmp, " / Level:");
1827 fread(&slot_level,sizeof(int),1,fi);
1828 sprintf(str,"%d",slot_level);
1833 *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));