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);
578 if(level_load(¤t_level,level_subset,level) != 0)
580 level_load_gfx(¤t_level);
582 level_load_song(¤t_level);
586 if(st_gl_mode != ST_GL_TEST)
591 if(st_gl_mode == ST_GL_PLAY)
595 timer_init(&time_left,YES);
598 if(st_gl_mode == ST_GL_LOAD_GAME)
602 /* --- MAIN GAME LOOP!!! --- */
609 timer_init(&fps_timer,YES);
610 timer_init(&frame_timer,YES);
615 clearscreen(0, 0, 0);
618 while (SDL_PollEvent(&event))
626 /* Calculate the movement-factor */
627 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
629 if(!timer_check(&frame_timer))
631 timer_start(&frame_timer,25);
638 tux.input.old_fire = tux.input.fire;
644 if(current_menu == &game_menu)
646 switch (menu_check(&game_menu))
649 st_pause_ticks_stop();
652 update_load_save_game_menu(&save_game_menu, NO);
655 update_load_save_game_menu(&load_game_menu, YES);
658 st_pause_ticks_stop();
663 else if(current_menu == &options_menu)
665 process_options_menu();
667 else if(current_menu == &save_game_menu )
669 process_save_load_game_menu(YES);
671 else if(current_menu == &load_game_menu )
673 process_save_load_game_menu(NO);
678 /* Handle actions: */
680 if(!game_pause && !show_menu)
682 if (game_action() == 0)
684 /* == 0: no more lives */
685 /* == -1: continues */
695 if(debug_mode && tux.input.down == DOWN)
698 /*Draw the current scene to the screen */
699 /*If the machine running the game is too slow
700 skip the drawing of the frame (so the calculations are more precise and
701 the FPS aren't affected).*/
702 /*if( ! fps_fps < 50.0 )
705 jump = YES;*/ /*FIXME: Implement this tweak right.*/
708 /* Time stops in pause mode */
709 if(game_pause || show_menu )
714 /* Set the time the last update and the time of the current update */
715 last_update_time = update_time;
716 update_time = st_get_ticks();
719 /* Pause till next frame, if the machine running the game is too fast: */
720 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
721 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
722 if(last_update_time >= update_time - 12 && jump != YES )
724 /*if((update_time - last_update_time) < 10)
725 SDL_Delay((11 - (update_time - last_update_time))/2);*/
731 if (timer_check(&time_left))
733 /* are we low on time ? */
734 if ((timer_get_left(&time_left) < TIME_WARNING)
735 && (current_music != HURRYUP_MUSIC))
737 current_music = HURRYUP_MUSIC;
738 /* stop the others music, prepare to play the fast music */
747 player_kill(&tux,KILL);
750 /* Keep playing the correct music: */
752 if (!playing_music())
754 play_current_music();
757 /* Calculate frames per second */
761 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
763 if(!timer_check(&fps_timer))
765 timer_start(&fps_timer,1000);
771 while (!done && !quit);
777 level_free(¤t_level);
788 /* Load graphics/sounds shared between all levels: */
790 void loadshared(void)
793 char * herring_song_path; /* for loading herring song*/
797 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
798 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
799 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
801 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
802 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
803 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
805 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
806 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
807 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
809 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
810 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
811 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
814 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
817 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
820 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
823 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
826 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
829 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
832 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
835 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
837 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
840 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
843 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
846 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
848 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
851 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
854 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
857 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
860 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
863 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
866 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
869 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
871 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
874 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
877 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
880 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
882 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
885 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
888 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
891 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
895 texture_load(&ducktux_right ,DATA_PREFIX
896 "/images/shared/ducktux-right.png",
899 texture_load(&ducktux_left ,DATA_PREFIX
900 "/images/shared/ducktux-left.png",
903 texture_load(&skidtux_right ,DATA_PREFIX
904 "/images/shared/skidtux-right.png",
907 texture_load(&skidtux_left ,DATA_PREFIX
908 "/images/shared/skidtux-left.png",
911 texture_load(&duckfiretux_right ,DATA_PREFIX
912 "/images/shared/duckfiretux-right.png",
915 texture_load(&duckfiretux_left ,DATA_PREFIX
916 "/images/shared/duckfiretux-left.png",
919 texture_load(&skidfiretux_right ,DATA_PREFIX
920 "/images/shared/skidfiretux-right.png",
923 texture_load(&skidfiretux_left ,DATA_PREFIX
924 "/images/shared/skidfiretux-left.png",
930 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
932 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
939 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
941 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
944 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
947 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
953 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
954 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
960 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
962 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
968 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
971 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
974 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
977 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
981 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
984 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
987 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
990 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
998 texture_load(&img_bsod_left[0] ,DATA_PREFIX
999 "/images/shared/bsod-left-0.png",
1002 texture_load(&img_bsod_left[1] ,DATA_PREFIX
1003 "/images/shared/bsod-left-1.png",
1006 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1007 "/images/shared/bsod-left-2.png",
1010 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1011 "/images/shared/bsod-left-3.png",
1014 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1015 "/images/shared/bsod-right-0.png",
1018 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1019 "/images/shared/bsod-right-1.png",
1022 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1023 "/images/shared/bsod-right-2.png",
1026 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1027 "/images/shared/bsod-right-3.png",
1030 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1031 "/images/shared/bsod-squished-left.png",
1034 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1035 "/images/shared/bsod-squished-right.png",
1038 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1039 "/images/shared/bsod-falling-left.png",
1042 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1043 "/images/shared/bsod-falling-right.png",
1049 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1050 "/images/shared/laptop-left-0.png",
1053 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1054 "/images/shared/laptop-left-1.png",
1057 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1058 "/images/shared/laptop-left-2.png",
1061 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1062 "/images/shared/laptop-right-0.png",
1065 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1066 "/images/shared/laptop-right-1.png",
1069 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1070 "/images/shared/laptop-right-2.png",
1073 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1074 "/images/shared/laptop-flat-left.png",
1077 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1078 "/images/shared/laptop-flat-right.png",
1081 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1082 "/images/shared/laptop-falling-left.png",
1085 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1086 "/images/shared/laptop-falling-right.png",
1092 texture_load(&img_money_left[0] ,DATA_PREFIX
1093 "/images/shared/bag-left-0.png",
1096 texture_load(&img_money_left[1] ,DATA_PREFIX
1097 "/images/shared/bag-left-1.png",
1100 texture_load(&img_money_right[0] ,DATA_PREFIX
1101 "/images/shared/bag-right-0.png",
1104 texture_load(&img_money_right[1] ,DATA_PREFIX
1105 "/images/shared/bag-right-1.png",
1112 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1113 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1118 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1120 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1127 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1130 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1133 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1136 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1142 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1147 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1151 /* Super background: */
1153 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1157 /* Sound effects: */
1159 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1160 // initialize sounds[i] with the correct pointer's value:
1161 // NULL or something else. And it will be dangerous to
1162 // play with not-initialized pointers.
1163 // This is also true with if (use_music)
1164 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1166 for (i = 0; i < NUM_SOUNDS; i++)
1167 sounds[i] = load_sound(soundfilenames[i]);
1170 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1171 strlen("SALCON.MOD") + 8));
1173 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1175 herring_song = load_song(herring_song_path);
1177 free(herring_song_path);
1182 /* Free shared data: */
1184 void unloadshared(void)
1188 for (i = 0; i < 3; i++)
1190 texture_free(&tux_right[i]);
1191 texture_free(&tux_left[i]);
1192 texture_free(&bigtux_right[i]);
1193 texture_free(&bigtux_left[i]);
1196 texture_free(&bigtux_right_jump);
1197 texture_free(&bigtux_left_jump);
1199 for (i = 0; i < 2; i++)
1201 texture_free(&cape_right[i]);
1202 texture_free(&cape_left[i]);
1203 texture_free(&bigcape_right[i]);
1204 texture_free(&bigcape_left[i]);
1207 texture_free(&ducktux_left);
1208 texture_free(&ducktux_right);
1210 texture_free(&skidtux_left);
1211 texture_free(&skidtux_right);
1213 for (i = 0; i < 4; i++)
1215 texture_free(&img_bsod_left[i]);
1216 texture_free(&img_bsod_right[i]);
1219 texture_free(&img_bsod_squished_left);
1220 texture_free(&img_bsod_squished_right);
1222 texture_free(&img_bsod_falling_left);
1223 texture_free(&img_bsod_falling_right);
1225 for (i = 0; i < 3; i++)
1227 texture_free(&img_laptop_left[i]);
1228 texture_free(&img_laptop_right[i]);
1231 texture_free(&img_laptop_flat_left);
1232 texture_free(&img_laptop_flat_right);
1234 texture_free(&img_laptop_falling_left);
1235 texture_free(&img_laptop_falling_right);
1237 for (i = 0; i < 2; i++)
1239 texture_free(&img_money_left[i]);
1240 texture_free(&img_money_right[i]);
1243 texture_free(&img_box_full);
1244 texture_free(&img_box_empty);
1246 texture_free(&img_water);
1247 for (i = 0; i < 3; i++)
1248 texture_free(&img_waves[i]);
1250 texture_free(&img_pole);
1251 texture_free(&img_poletop);
1253 for (i = 0; i < 2; i++)
1254 texture_free(&img_flag[i]);
1256 texture_free(&img_mints);
1257 texture_free(&img_coffee);
1259 for (i = 0; i < 4; i++)
1261 texture_free(&img_distro[i]);
1262 texture_free(&img_cloud[0][i]);
1263 texture_free(&img_cloud[1][i]);
1266 texture_free(&img_golden_herring);
1268 for (i = 0; i < NUM_SOUNDS; i++)
1269 free_chunk(sounds[i]);
1271 /* free the herring song */
1272 free_music( herring_song );
1276 /* Draw a tile on the screen: */
1278 void drawshape(float x, float y, unsigned char c)
1282 if (c == 'X' || c == 'x')
1283 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1284 else if (c == 'Y' || c == 'y')
1285 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1286 else if (c == 'A' || c =='B' || c == '!')
1287 texture_draw(&img_box_full, x, y, NO_UPDATE);
1289 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1290 else if (c >= 'C' && c <= 'F')
1291 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1292 else if (c >= 'c' && c <= 'f')
1293 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1294 else if (c >= 'G' && c <= 'J')
1295 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1296 else if (c >= 'g' && c <= 'j')
1297 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1299 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1301 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1303 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1305 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1309 z = (frame / 2) % 6;
1312 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1314 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1316 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1320 z = (frame / 3) % 3;
1322 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1325 texture_draw(&img_poletop, x, y, NO_UPDATE);
1328 texture_draw(&img_pole, x, y, NO_UPDATE);
1330 /* Mark this as the end position of the level! */
1336 z = (frame / 3) % 2;
1338 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1341 texture_draw(&img_water, x, y, NO_UPDATE);
1345 /* What shape is at some position? */
1347 unsigned char shape(float x, float y)
1356 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1358 c = current_level.tiles[yy][xx];
1369 int issolid(float x, float y)
1371 if (isbrick(x, y) ||
1373 (shape(x, y) == '[') ||
1374 (shape(x, y) == '=') ||
1375 (shape(x, y) == ']') ||
1376 (shape(x, y) == 'A') ||
1377 (shape(x, y) == 'B') ||
1378 (shape(x, y) == '!') ||
1379 (shape(x, y) == 'a'))
1388 int issolid(float x, float y)
1390 if (isbrick(x, y) ||
1391 isbrick(x + 31, y) ||
1394 (shape(x, y) == '[' ||
1395 shape(x + 31, y) == '[') ||
1396 (shape(x, y) == '=' ||
1397 shape(x + 31, y) == '=') ||
1398 (shape(x, y) == ']' ||
1399 shape(x + 31, y) == ']') ||
1400 (shape(x, y) == 'A' ||
1401 shape(x + 31, y) == 'A') ||
1402 (shape(x, y) == 'B' ||
1403 shape(x + 31, y) == 'B') ||
1404 (shape(x, y) == '!' ||
1405 shape(x + 31, y) == '!') ||
1406 (shape(x, y) == 'a' ||
1407 shape(x + 31, y) == 'a'))
1416 /* Is it a brick? */
1418 int isbrick(float x, float y)
1420 if (shape(x, y) == 'X' ||
1421 shape(x, y) == 'x' ||
1422 shape(x, y) == 'Y' ||
1434 int isice(float x, float y)
1436 if (shape(x, y) == '#')
1445 /* Is it a full box? */
1447 int isfullbox(float x, float y)
1449 if (shape(x, y) == 'A' ||
1450 shape(x, y) == 'B' ||
1459 /* Break a brick: */
1461 void trybreakbrick(float x, float y)
1465 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1467 /* Get a distro from it: */
1469 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1470 (int)(y / 32) * 32);
1472 if (counting_distros == NO)
1474 counting_distros = YES;
1475 distro_counter = 50;
1478 if (distro_counter <= 0)
1479 level_change(¤t_level,x, y, 'a');
1481 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1482 score = score + SCORE_DISTRO;
1487 /* Get rid of it: */
1489 level_change(¤t_level,x, y,'.');
1493 /* Replace it with broken bits: */
1495 add_broken_brick(((int)(x + 1) / 32) * 32,
1496 (int)(y / 32) * 32);
1499 /* Get some score: */
1501 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1502 score = score + SCORE_BRICK;
1507 /* Bounce a brick: */
1509 void bumpbrick(float x, float y)
1511 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1512 (int)(y / 32) * 32);
1514 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1520 void tryemptybox(float x, float y)
1522 if (isfullbox(x, y))
1524 if (shape(x, y) == 'A')
1527 /* Box with a distro! */
1529 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1530 (int)(y / 32) * 32 - 32);
1532 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1533 score = score + SCORE_DISTRO;
1536 else if (shape(x, y) == 'B')
1538 /* Add an upgrade! */
1540 if (tux.size == SMALL)
1542 /* Tux is small, add mints! */
1544 add_upgrade((int)((x + 1) / 32) * 32,
1545 (int)(y / 32) * 32 - 32,
1550 /* Tux is big, add coffee: */
1552 add_upgrade((int)((x + 1) / 32) * 32,
1553 (int)(y / 32) * 32 - 32,
1557 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1559 else if (shape(x, y) == '!')
1561 /* Add a golden herring */
1563 add_upgrade((int)((x + 1) / 32) * 32,
1564 (int)(y / 32) * 32 - 32,
1568 /* Empty the box: */
1570 level_change(¤t_level,x, y, 'a');
1575 /* Try to grab a distro: */
1577 void trygrabdistro(float x, float y, int bounciness)
1579 if (shape(x, y) == '$')
1581 level_change(¤t_level,x, y, '.');
1582 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1584 if (bounciness == BOUNCE)
1586 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1587 (int)(y / 32) * 32);
1590 score = score + SCORE_DISTRO;
1595 /* Try to bump a bad guy from below: */
1597 void trybumpbadguy(float x, float y)
1604 for (i = 0; i < num_bad_guys; i++)
1606 if (bad_guys[i].base.alive &&
1607 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1608 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1610 if (bad_guys[i].kind == BAD_BSOD ||
1611 bad_guys[i].kind == BAD_LAPTOP)
1613 bad_guys[i].dying = FALLING;
1614 bad_guys[i].base.ym = -8;
1615 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1623 for (i = 0; i < num_upgrades; i++)
1625 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1626 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1627 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1629 upgrades[i].base.xm = -upgrades[i].base.xm;
1630 upgrades[i].base.ym = -8;
1631 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1637 void drawstatus(void)
1641 sprintf(str, "%d", score);
1642 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1643 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1645 if(st_gl_mode != ST_GL_TEST)
1647 sprintf(str, "%d", hs_score);
1648 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1649 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1653 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1656 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1658 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1659 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1660 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1663 sprintf(str, "%d", distros);
1664 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1665 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1667 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1671 sprintf(str, "%2.1f", fps_fps);
1672 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1673 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1676 for(i=0; i < tux.lives; ++i)
1678 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1683 void drawendscreen(void)
1687 clearscreen(0, 0, 0);
1689 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1691 sprintf(str, "SCORE: %d", score);
1692 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1694 sprintf(str, "DISTROS: %d", distros);
1695 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1701 void drawresultscreen(void)
1705 clearscreen(0, 0, 0);
1707 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1709 sprintf(str, "SCORE: %d", score);
1710 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1712 sprintf(str, "DISTROS: %d", distros);
1713 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1719 void savegame(int slot)
1721 char savefile[1024];
1725 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1727 fi = fopen(savefile, "wb");
1731 fprintf(stderr, "Warning: I could not open the slot file ");
1736 fputs(level_subset, fi);
1738 fwrite(&level,sizeof(int),1,fi);
1739 fwrite(&score,sizeof(int),1,fi);
1740 fwrite(&distros,sizeof(int),1,fi);
1741 fwrite(&scroll_x,sizeof(float),1,fi);
1742 fwrite(&tux,sizeof(player_type),1,fi);
1743 timer_fwrite(&tux.invincible_timer,fi);
1744 printf("Time inv LEFT: %d\n",timer_get_left(&tux.invincible_timer));
1745 timer_fwrite(&tux.skidding_timer,fi);
1746 timer_fwrite(&tux.safe_timer,fi);
1747 timer_fwrite(&tux.frame_timer,fi);
1748 timer_fwrite(&time_left,fi);
1749 printf("Time LEFT: %d\n",timer_get_left(&time_left));
1750 ui = st_get_ticks();
1751 fwrite(&ui,sizeof(int),1,fi);
1757 void loadgame(int slot)
1759 char savefile[1024];
1764 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1766 fi = fopen(savefile, "rb");
1770 fprintf(stderr, "Warning: I could not open the slot file ");
1777 fgets(str, 100, fi);
1778 strcpy(level_subset, str);
1779 level_subset[strlen(level_subset)-1] = '\0';
1780 fread(&level,sizeof(int),1,fi);
1783 level_free(¤t_level);
1784 if(level_load(¤t_level,level_subset,level) != 0)
1788 activate_bad_guys();
1790 level_load_gfx(¤t_level);
1792 level_load_song(¤t_level);
1794 update_time = st_get_ticks();
1796 fread(&score,sizeof(int),1,fi);
1797 fread(&distros,sizeof(int),1,fi);
1798 fread(&scroll_x,sizeof(float),1,fi);
1799 fread(&tux,sizeof(player_type),1,fi);
1800 timer_fread(&tux.invincible_timer,fi);
1801 printf("Time inv LEFT: %d - %d\n",timer_get_left(&tux.invincible_timer),tux.invincible_timer.time);
1802 timer_fread(&tux.skidding_timer,fi);
1803 timer_fread(&tux.safe_timer,fi);
1804 timer_fread(&tux.frame_timer,fi);
1805 timer_fread(&time_left,fi);
1806 printf("Time LEFT: %d\n",timer_get_left(&time_left));
1807 fread(&ui,sizeof(int),1,fi);
1808 tux.hphysic.start_time += st_get_ticks() - ui;
1809 tux.vphysic.start_time += st_get_ticks() - ui;
1815 void slotinfo(char **pinfo, int slot)
1818 char slotfile[1024];
1822 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1824 fi = fopen(slotfile, "rb");
1826 sprintf(tmp,"Slot %d - ",slot);
1834 fgets(str, 100, fi);
1835 str[strlen(str)-1] = '\0';
1837 strcat(tmp, " / Level:");
1838 fread(&slot_level,sizeof(int),1,fi);
1839 sprintf(str,"%d",slot_level);
1844 *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));