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)
314 level_free(¤t_level);
320 player_level_begin(&tux);
326 /* No more lives!? */
330 if(st_gl_mode != ST_GL_TEST)
333 if(st_gl_mode != ST_GL_TEST)
335 if (score > hs_score)
339 level_free(¤t_level);
344 } /* if (lives < 0) */
347 /* Either way, (re-)load the (next) level... */
349 player_level_begin(&tux);
351 level_free(¤t_level);
352 if(level_load(¤t_level,level_subset,level) != 0)
358 level_load_gfx(¤t_level);
360 level_load_song(¤t_level);
361 if(st_gl_mode != ST_GL_TEST)
368 /* Handle bouncy distros: */
370 for (i = 0; i < num_bouncy_distros; i++)
372 bouncy_distro_action(&bouncy_distros[i]);
376 /* Handle broken bricks: */
378 for (i = 0; i < num_broken_bricks; i++)
380 broken_brick_action(&broken_bricks[i]);
384 /* Handle distro counting: */
386 if (counting_distros == YES)
390 if (distro_counter <= 0)
391 counting_distros = -1;
395 /* Handle bouncy bricks: */
397 for (i = 0; i < num_bouncy_bricks; i++)
399 bouncy_brick_action(&bouncy_bricks[i]);
403 /* Handle floating scores: */
405 for (i = 0; i < num_floating_scores; i++)
407 floating_score_action(&floating_scores[i]);
411 /* Handle bullets: */
413 for (i = 0; i < num_bullets; ++i)
415 bullet_action(&bullets[i]);
418 /* Handle upgrades: */
420 for (i = 0; i < num_upgrades; i++)
422 upgrade_action(&upgrades[i]);
426 /* Handle bad guys: */
428 for (i = 0; i < num_bad_guys; i++)
430 badguy_action(&bad_guys[i]);
433 /* Handle all possible collisions. */
439 /* --- GAME DRAW! --- */
447 if (tux.dying && (frame % 4) == 0)
448 clearscreen(255, 255, 255);
449 else if(timer_check(&super_bkgd_timer))
450 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
453 /* Draw the real background */
454 if(current_level.bkgd_image[0] != '\0')
456 s = (int)scroll_x / 30;
457 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
458 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
462 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
466 /* Draw background: */
468 for (y = 0; y < 15; ++y)
470 for (x = 0; x < 21; ++x)
472 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
473 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
478 /* (Bouncy bricks): */
480 for (i = 0; i < num_bouncy_bricks; ++i)
482 bouncy_brick_draw(&bouncy_bricks[i]);
488 for (i = 0; i < num_bad_guys; ++i)
490 badguy_draw(&bad_guys[i]);
499 for (i = 0; i < num_bullets; ++i)
501 bullet_draw(&bullets[i]);
504 /* (Floating scores): */
506 for (i = 0; i < num_floating_scores; ++i)
508 floating_score_draw(&floating_scores[i]);
514 for (i = 0; i < num_upgrades; ++i)
516 upgrade_draw(&upgrades[i]);
520 /* (Bouncy distros): */
522 for (i = 0; i < num_bouncy_distros; ++i)
524 bouncy_distro_draw(&bouncy_distros[i]);
528 /* (Broken bricks): */
530 for (i = 0; i < num_broken_bricks; ++i)
532 broken_brick_draw(&broken_bricks[i]);
541 for(i = 0; i < x; ++i)
543 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 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
546 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
550 menu_process_current();
552 /* (Update it all!) */
559 /* --- GAME LOOP! --- */
561 int gameloop(char * subset, int levelnb, int mode)
563 int fps_cnt, jump, done;
564 timer_type fps_timer, frame_timer;
565 timer_init(&fps_timer, YES);
566 timer_init(&frame_timer, YES);
572 strcpy(level_subset,subset);
574 if(st_gl_mode != ST_GL_LOAD_GAME)
580 if(level_load(¤t_level,level_subset,level) != 0)
582 level_load_gfx(¤t_level);
584 level_load_song(¤t_level);
590 if(st_gl_mode != ST_GL_TEST)
595 if(st_gl_mode == ST_GL_PLAY)
599 timer_init(&time_left,YES);
602 if(st_gl_mode == ST_GL_LOAD_GAME)
606 /* --- MAIN GAME LOOP!!! --- */
613 timer_init(&fps_timer,YES);
614 timer_init(&frame_timer,YES);
619 clearscreen(0, 0, 0);
622 while (SDL_PollEvent(&event))
630 /* Calculate the movement-factor */
631 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
633 if(!timer_check(&frame_timer))
635 timer_start(&frame_timer,25);
642 tux.input.old_fire = tux.input.fire;
648 if(current_menu == &game_menu)
650 switch (menu_check(&game_menu))
653 st_pause_ticks_stop();
656 update_load_save_game_menu(&save_game_menu, NO);
659 update_load_save_game_menu(&load_game_menu, YES);
662 st_pause_ticks_stop();
667 else if(current_menu == &options_menu)
669 process_options_menu();
671 else if(current_menu == &save_game_menu )
673 process_save_load_game_menu(YES);
675 else if(current_menu == &load_game_menu )
677 process_save_load_game_menu(NO);
682 /* Handle actions: */
684 if(!game_pause && !show_menu)
686 if (game_action() == 0)
688 /* == 0: no more lives */
689 /* == -1: continues */
699 if(tux.input.down == DOWN)
702 /*Draw the current scene to the screen */
703 /*If the machine running the game is too slow
704 skip the drawing of the frame (so the calculations are more precise and
705 the FPS aren't affected).*/
706 /*if( ! fps_fps < 50.0 )
709 jump = YES;*/ /*FIXME: Implement this tweak right.*/
712 /* Time stops in pause mode */
713 if(game_pause || show_menu )
718 /* Set the time the last update and the time of the current update */
719 last_update_time = update_time;
720 update_time = st_get_ticks();
723 /* Pause till next frame, if the machine running the game is too fast: */
724 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
725 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
726 if(last_update_time >= update_time - 12 && jump != YES )
728 /*if((update_time - last_update_time) < 10)
729 SDL_Delay((11 - (update_time - last_update_time))/2);*/
735 if (timer_check(&time_left))
737 /* are we low on time ? */
738 if ((timer_get_left(&time_left) < TIME_WARNING)
739 && (current_music != HURRYUP_MUSIC))
741 current_music = HURRYUP_MUSIC;
742 /* stop the others music, prepare to play the fast music */
751 player_kill(&tux,KILL);
754 /* Keep playing the correct music: */
756 if (!playing_music())
758 play_current_music();
761 /* Calculate frames per second */
765 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
767 if(!timer_check(&fps_timer))
769 timer_start(&fps_timer,1000);
775 while (!done && !quit);
781 level_free(¤t_level);
792 /* Load graphics/sounds shared between all levels: */
794 void loadshared(void)
797 char * herring_song_path; /* for loading herring song*/
801 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
802 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
803 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
805 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
806 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
807 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
809 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
810 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
811 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
813 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
814 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
815 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
818 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
821 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
824 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
827 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
830 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
833 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
836 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
839 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
841 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
844 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
847 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
850 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
852 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
855 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
858 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
861 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
864 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
867 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
870 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
873 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
875 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
878 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
881 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
884 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
886 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
889 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
892 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
895 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
899 texture_load(&ducktux_right ,DATA_PREFIX
900 "/images/shared/ducktux-right.png",
903 texture_load(&ducktux_left ,DATA_PREFIX
904 "/images/shared/ducktux-left.png",
907 texture_load(&skidtux_right ,DATA_PREFIX
908 "/images/shared/skidtux-right.png",
911 texture_load(&skidtux_left ,DATA_PREFIX
912 "/images/shared/skidtux-left.png",
915 texture_load(&duckfiretux_right ,DATA_PREFIX
916 "/images/shared/duckfiretux-right.png",
919 texture_load(&duckfiretux_left ,DATA_PREFIX
920 "/images/shared/duckfiretux-left.png",
923 texture_load(&skidfiretux_right ,DATA_PREFIX
924 "/images/shared/skidfiretux-right.png",
927 texture_load(&skidfiretux_left ,DATA_PREFIX
928 "/images/shared/skidfiretux-left.png",
934 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
936 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
943 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
945 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
948 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
951 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
957 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
958 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
964 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
966 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
972 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
975 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
978 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
981 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
985 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
988 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
991 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
994 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
1002 texture_load(&img_bsod_left[0] ,DATA_PREFIX
1003 "/images/shared/bsod-left-0.png",
1006 texture_load(&img_bsod_left[1] ,DATA_PREFIX
1007 "/images/shared/bsod-left-1.png",
1010 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1011 "/images/shared/bsod-left-2.png",
1014 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1015 "/images/shared/bsod-left-3.png",
1018 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1019 "/images/shared/bsod-right-0.png",
1022 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1023 "/images/shared/bsod-right-1.png",
1026 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1027 "/images/shared/bsod-right-2.png",
1030 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1031 "/images/shared/bsod-right-3.png",
1034 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1035 "/images/shared/bsod-squished-left.png",
1038 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1039 "/images/shared/bsod-squished-right.png",
1042 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1043 "/images/shared/bsod-falling-left.png",
1046 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1047 "/images/shared/bsod-falling-right.png",
1053 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1054 "/images/shared/laptop-left-0.png",
1057 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1058 "/images/shared/laptop-left-1.png",
1061 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1062 "/images/shared/laptop-left-2.png",
1065 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1066 "/images/shared/laptop-right-0.png",
1069 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1070 "/images/shared/laptop-right-1.png",
1073 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1074 "/images/shared/laptop-right-2.png",
1077 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1078 "/images/shared/laptop-flat-left.png",
1081 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1082 "/images/shared/laptop-flat-right.png",
1085 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1086 "/images/shared/laptop-falling-left.png",
1089 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1090 "/images/shared/laptop-falling-right.png",
1096 texture_load(&img_money_left[0] ,DATA_PREFIX
1097 "/images/shared/bag-left-0.png",
1100 texture_load(&img_money_left[1] ,DATA_PREFIX
1101 "/images/shared/bag-left-1.png",
1104 texture_load(&img_money_right[0] ,DATA_PREFIX
1105 "/images/shared/bag-right-0.png",
1108 texture_load(&img_money_right[1] ,DATA_PREFIX
1109 "/images/shared/bag-right-1.png",
1116 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1117 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1122 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1124 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1131 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1134 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1137 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1140 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1146 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1151 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1155 /* Super background: */
1157 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1161 /* Sound effects: */
1163 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1164 // initialize sounds[i] with the correct pointer's value:
1165 // NULL or something else. And it will be dangerous to
1166 // play with not-initialized pointers.
1167 // This is also true with if (use_music)
1168 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1170 for (i = 0; i < NUM_SOUNDS; i++)
1171 sounds[i] = load_sound(soundfilenames[i]);
1174 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1175 strlen("SALCON.MOD") + 8));
1177 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1179 herring_song = load_song(herring_song_path);
1181 free(herring_song_path);
1186 /* Free shared data: */
1188 void unloadshared(void)
1192 for (i = 0; i < 3; i++)
1194 texture_free(&tux_right[i]);
1195 texture_free(&tux_left[i]);
1196 texture_free(&bigtux_right[i]);
1197 texture_free(&bigtux_left[i]);
1200 texture_free(&bigtux_right_jump);
1201 texture_free(&bigtux_left_jump);
1203 for (i = 0; i < 2; i++)
1205 texture_free(&cape_right[i]);
1206 texture_free(&cape_left[i]);
1207 texture_free(&bigcape_right[i]);
1208 texture_free(&bigcape_left[i]);
1211 texture_free(&ducktux_left);
1212 texture_free(&ducktux_right);
1214 texture_free(&skidtux_left);
1215 texture_free(&skidtux_right);
1217 for (i = 0; i < 4; i++)
1219 texture_free(&img_bsod_left[i]);
1220 texture_free(&img_bsod_right[i]);
1223 texture_free(&img_bsod_squished_left);
1224 texture_free(&img_bsod_squished_right);
1226 texture_free(&img_bsod_falling_left);
1227 texture_free(&img_bsod_falling_right);
1229 for (i = 0; i < 3; i++)
1231 texture_free(&img_laptop_left[i]);
1232 texture_free(&img_laptop_right[i]);
1235 texture_free(&img_laptop_flat_left);
1236 texture_free(&img_laptop_flat_right);
1238 texture_free(&img_laptop_falling_left);
1239 texture_free(&img_laptop_falling_right);
1241 for (i = 0; i < 2; i++)
1243 texture_free(&img_money_left[i]);
1244 texture_free(&img_money_right[i]);
1247 texture_free(&img_box_full);
1248 texture_free(&img_box_empty);
1250 texture_free(&img_water);
1251 for (i = 0; i < 3; i++)
1252 texture_free(&img_waves[i]);
1254 texture_free(&img_pole);
1255 texture_free(&img_poletop);
1257 for (i = 0; i < 2; i++)
1258 texture_free(&img_flag[i]);
1260 texture_free(&img_mints);
1261 texture_free(&img_coffee);
1263 for (i = 0; i < 4; i++)
1265 texture_free(&img_distro[i]);
1266 texture_free(&img_cloud[0][i]);
1267 texture_free(&img_cloud[1][i]);
1270 texture_free(&img_golden_herring);
1272 for (i = 0; i < NUM_SOUNDS; i++)
1273 free_chunk(sounds[i]);
1275 /* free the herring song */
1276 free_music( herring_song );
1280 /* Draw a tile on the screen: */
1282 void drawshape(float x, float y, unsigned char c)
1286 if (c == 'X' || c == 'x')
1287 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1288 else if (c == 'Y' || c == 'y')
1289 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1290 else if (c == 'A' || c =='B' || c == '!')
1291 texture_draw(&img_box_full, x, y, NO_UPDATE);
1293 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1294 else if (c >= 'C' && c <= 'F')
1295 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1296 else if (c >= 'c' && c <= 'f')
1297 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1298 else if (c >= 'G' && c <= 'J')
1299 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1300 else if (c >= 'g' && c <= 'j')
1301 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1303 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1305 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1307 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1309 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1313 z = (frame / 2) % 6;
1316 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1318 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1320 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1324 z = (frame / 3) % 3;
1326 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1329 texture_draw(&img_poletop, x, y, NO_UPDATE);
1332 texture_draw(&img_pole, x, y, NO_UPDATE);
1334 /* Mark this as the end position of the level! */
1340 z = (frame / 3) % 2;
1342 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1345 texture_draw(&img_water, x, y, NO_UPDATE);
1349 /* What shape is at some position? */
1351 unsigned char shape(float x, float y)
1360 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1362 c = current_level.tiles[yy][xx];
1373 int issolid(float x, float y)
1375 if (isbrick(x, y) ||
1377 (shape(x, y) == '[') ||
1378 (shape(x, y) == '=') ||
1379 (shape(x, y) == ']') ||
1380 (shape(x, y) == 'A') ||
1381 (shape(x, y) == 'B') ||
1382 (shape(x, y) == '!') ||
1383 (shape(x, y) == 'a'))
1392 int issolid(float x, float y)
1394 if (isbrick(x, y) ||
1395 isbrick(x + 31, y) ||
1398 (shape(x, y) == '[' ||
1399 shape(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) == 'A' ||
1405 shape(x + 31, y) == 'A') ||
1406 (shape(x, y) == 'B' ||
1407 shape(x + 31, y) == 'B') ||
1408 (shape(x, y) == '!' ||
1409 shape(x + 31, y) == '!') ||
1410 (shape(x, y) == 'a' ||
1411 shape(x + 31, y) == 'a'))
1420 /* Is it a brick? */
1422 int isbrick(float x, float y)
1424 if (shape(x, y) == 'X' ||
1425 shape(x, y) == 'x' ||
1426 shape(x, y) == 'Y' ||
1438 int isice(float x, float y)
1440 if (shape(x, y) == '#')
1449 /* Is it a full box? */
1451 int isfullbox(float x, float y)
1453 if (shape(x, y) == 'A' ||
1454 shape(x, y) == 'B' ||
1463 /* Break a brick: */
1465 void trybreakbrick(float x, float y)
1469 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1471 /* Get a distro from it: */
1473 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1474 (int)(y / 32) * 32);
1476 if (counting_distros == NO)
1478 counting_distros = YES;
1479 distro_counter = 50;
1482 if (distro_counter <= 0)
1483 level_change(¤t_level,x, y, 'a');
1485 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1486 score = score + SCORE_DISTRO;
1491 /* Get rid of it: */
1493 level_change(¤t_level,x, y,'.');
1497 /* Replace it with broken bits: */
1499 add_broken_brick(((int)(x + 1) / 32) * 32,
1500 (int)(y / 32) * 32);
1503 /* Get some score: */
1505 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1506 score = score + SCORE_BRICK;
1511 /* Bounce a brick: */
1513 void bumpbrick(float x, float y)
1515 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1516 (int)(y / 32) * 32);
1518 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1524 void tryemptybox(float x, float y)
1526 if (isfullbox(x, y))
1528 if (shape(x, y) == 'A')
1531 /* Box with a distro! */
1533 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1534 (int)(y / 32) * 32 - 32);
1536 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1537 score = score + SCORE_DISTRO;
1540 else if (shape(x, y) == 'B')
1542 /* Add an upgrade! */
1544 if (tux.size == SMALL)
1546 /* Tux is small, add mints! */
1548 add_upgrade((int)((x + 1) / 32) * 32,
1549 (int)(y / 32) * 32 - 32,
1554 /* Tux is big, add coffee: */
1556 add_upgrade((int)((x + 1) / 32) * 32,
1557 (int)(y / 32) * 32 - 32,
1561 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1563 else if (shape(x, y) == '!')
1565 /* Add a golden herring */
1567 add_upgrade((int)((x + 1) / 32) * 32,
1568 (int)(y / 32) * 32 - 32,
1572 /* Empty the box: */
1574 level_change(¤t_level,x, y, 'a');
1579 /* Try to grab a distro: */
1581 void trygrabdistro(float x, float y, int bounciness)
1583 if (shape(x, y) == '$')
1585 level_change(¤t_level,x, y, '.');
1586 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1588 if (bounciness == BOUNCE)
1590 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1591 (int)(y / 32) * 32);
1594 score = score + SCORE_DISTRO;
1599 /* Try to bump a bad guy from below: */
1601 void trybumpbadguy(float x, float y)
1608 for (i = 0; i < num_bad_guys; i++)
1610 if (bad_guys[i].base.alive &&
1611 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1612 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1614 if (bad_guys[i].kind == BAD_BSOD ||
1615 bad_guys[i].kind == BAD_LAPTOP)
1617 bad_guys[i].dying = FALLING;
1618 bad_guys[i].base.ym = -8;
1619 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1627 for (i = 0; i < num_upgrades; i++)
1629 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1630 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1631 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1633 upgrades[i].base.xm = -upgrades[i].base.xm;
1634 upgrades[i].base.ym = -8;
1635 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1641 void drawstatus(void)
1645 sprintf(str, "%d", score);
1646 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1647 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1649 if(st_gl_mode != ST_GL_TEST)
1651 sprintf(str, "%d", hs_score);
1652 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1653 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1657 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1660 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1662 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1663 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1664 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1667 sprintf(str, "%d", distros);
1668 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1669 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1671 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1675 sprintf(str, "%2.1f", fps_fps);
1676 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1677 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1680 for(i=0; i < tux.lives; ++i)
1682 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1687 void drawendscreen(void)
1691 clearscreen(0, 0, 0);
1693 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1695 sprintf(str, "SCORE: %d", score);
1696 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1698 sprintf(str, "DISTROS: %d", distros);
1699 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1705 void drawresultscreen(void)
1709 clearscreen(0, 0, 0);
1711 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1713 sprintf(str, "SCORE: %d", score);
1714 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1716 sprintf(str, "DISTROS: %d", distros);
1717 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1723 void savegame(int slot)
1725 char savefile[1024];
1729 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1731 fi = fopen(savefile, "wb");
1735 fprintf(stderr, "Warning: I could not open the slot file ");
1740 fputs(level_subset, fi);
1742 fwrite(&level,sizeof(int),1,fi);
1743 fwrite(&score,sizeof(int),1,fi);
1744 fwrite(&distros,sizeof(int),1,fi);
1745 fwrite(&tux,sizeof(player_type),1,fi);
1746 fwrite(&scroll_x,sizeof(float),1,fi);
1747 fwrite(&time_left,sizeof(float),1,fi);
1748 ui = st_get_ticks();
1749 fwrite(&ui,sizeof(int),1,fi);
1755 void loadgame(int slot)
1757 char savefile[1024];
1762 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1764 fi = fopen(savefile, "rb");
1768 fprintf(stderr, "Warning: I could not open the slot file ");
1775 fgets(str, 100, fi);
1776 strcpy(level_subset, str);
1777 level_subset[strlen(level_subset)-1] = '\0';
1778 fread(&level,sizeof(int),1,fi);
1781 level_free(¤t_level);
1782 if(level_load(¤t_level,level_subset,level) != 0)
1786 activate_bad_guys();
1788 level_load_gfx(¤t_level);
1790 level_load_song(¤t_level);
1792 timer_start(&time_left,current_level.time_left*1000);
1793 update_time = st_get_ticks();
1795 fread(&score,sizeof(int),1,fi);
1796 fread(&distros,sizeof(int),1,fi);
1797 fread(&tux,sizeof(player_type),1,fi);
1798 fread(&scroll_x,sizeof(float),1,fi);
1799 fread(&time_left,sizeof(float),1,fi);
1800 fread(&ui,sizeof(int),1,fi);
1801 time_left.time += st_get_ticks() - ui;
1802 tux.invincible_timer.time += st_get_ticks() - ui;
1803 tux.skidding_timer.time += st_get_ticks() - ui;
1804 tux.safe_timer.time += st_get_ticks() - ui;
1805 tux.vphysic.start_time += st_get_ticks() - ui;
1806 tux.hphysic.start_time += st_get_ticks() - ui;
1807 tux.vphysic.start_time += st_get_ticks() - ui;
1813 void slotinfo(char **pinfo, int slot)
1816 char slotfile[1024];
1820 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1822 fi = fopen(slotfile, "rb");
1824 sprintf(tmp,"Slot %d - ",slot);
1832 fgets(str, 100, fi);
1833 str[strlen(str)-1] = '\0';
1835 strcat(tmp, " / Level:");
1836 fread(&slot_level,sizeof(int),1,fi);
1837 sprintf(str,"%d",slot_level);
1842 *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));