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)
288 /* --- GAME ACTION! --- */
290 int game_action(void)
294 /* (tux_dying || next_level) */
295 if (tux.dying || next_level)
297 /* Tux either died, or reached the end of a level! */
305 /* End of a level! */
308 if(st_gl_mode != ST_GL_TEST)
315 level_free(¤t_level);
321 player_level_begin(&tux);
327 /* No more lives!? */
331 if(st_gl_mode != ST_GL_TEST)
334 if(st_gl_mode != ST_GL_TEST)
336 if (score > hs_score)
340 level_free(¤t_level);
345 } /* if (lives < 0) */
348 /* Either way, (re-)load the (next) level... */
350 player_level_begin(&tux);
352 level_free(¤t_level);
353 if(level_load(¤t_level,level_subset,level) != 0)
359 level_load_gfx(¤t_level);
361 level_load_song(¤t_level);
362 if(st_gl_mode != ST_GL_TEST)
369 /* Handle bouncy distros: */
371 for (i = 0; i < num_bouncy_distros; i++)
373 bouncy_distro_action(&bouncy_distros[i]);
377 /* Handle broken bricks: */
379 for (i = 0; i < num_broken_bricks; i++)
381 broken_brick_action(&broken_bricks[i]);
385 /* Handle distro counting: */
387 if (counting_distros == YES)
391 if (distro_counter <= 0)
392 counting_distros = -1;
396 /* Handle bouncy bricks: */
398 for (i = 0; i < num_bouncy_bricks; i++)
400 bouncy_brick_action(&bouncy_bricks[i]);
404 /* Handle floating scores: */
406 for (i = 0; i < num_floating_scores; i++)
408 floating_score_action(&floating_scores[i]);
412 /* Handle bullets: */
414 for (i = 0; i < num_bullets; ++i)
416 bullet_action(&bullets[i]);
419 /* Handle upgrades: */
421 for (i = 0; i < num_upgrades; i++)
423 upgrade_action(&upgrades[i]);
427 /* Handle bad guys: */
429 for (i = 0; i < num_bad_guys; i++)
431 badguy_action(&bad_guys[i]);
434 /* Handle all possible collisions. */
440 /* --- GAME DRAW! --- */
448 if (tux.dying && (frame % 4) == 0)
449 clearscreen(255, 255, 255);
450 else if(timer_check(&super_bkgd_timer))
451 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
454 /* Draw the real background */
455 if(current_level.bkgd_image[0] != '\0')
457 s = (int)scroll_x / 30;
458 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
459 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
463 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
467 /* Draw background: */
469 for (y = 0; y < 15; ++y)
471 for (x = 0; x < 21; ++x)
473 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
474 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
479 /* (Bouncy bricks): */
481 for (i = 0; i < num_bouncy_bricks; ++i)
483 bouncy_brick_draw(&bouncy_bricks[i]);
489 for (i = 0; i < num_bad_guys; ++i)
491 badguy_draw(&bad_guys[i]);
500 for (i = 0; i < num_bullets; ++i)
502 bullet_draw(&bullets[i]);
505 /* (Floating scores): */
507 for (i = 0; i < num_floating_scores; ++i)
509 floating_score_draw(&floating_scores[i]);
515 for (i = 0; i < num_upgrades; ++i)
517 upgrade_draw(&upgrades[i]);
521 /* (Bouncy distros): */
523 for (i = 0; i < num_bouncy_distros; ++i)
525 bouncy_distro_draw(&bouncy_distros[i]);
529 /* (Broken bricks): */
531 for (i = 0; i < num_broken_bricks; ++i)
533 broken_brick_draw(&broken_bricks[i]);
542 for(i = 0; i < x; ++i)
544 fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1);
546 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
547 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
551 menu_process_current();
553 /* (Update it all!) */
560 /* --- GAME LOOP! --- */
562 int gameloop(char * subset, int levelnb, int mode)
564 int fps_cnt, jump, done;
565 timer_type fps_timer, frame_timer;
566 timer_init(&fps_timer, YES);
567 timer_init(&frame_timer, YES);
573 strcpy(level_subset,subset);
579 if(level_load(¤t_level,level_subset,level) != 0)
581 level_load_gfx(¤t_level);
583 level_load_song(¤t_level);
587 if(st_gl_mode != ST_GL_TEST)
592 if(st_gl_mode == ST_GL_PLAY)
596 timer_init(&time_left,YES);
599 if(st_gl_mode == ST_GL_LOAD_GAME)
603 /* --- MAIN GAME LOOP!!! --- */
610 timer_init(&fps_timer,YES);
611 timer_init(&frame_timer,YES);
616 clearscreen(0, 0, 0);
619 while (SDL_PollEvent(&event))
627 /* Calculate the movement-factor */
628 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
630 if(!timer_check(&frame_timer))
632 timer_start(&frame_timer,25);
639 tux.input.old_fire = tux.input.fire;
645 if(current_menu == &game_menu)
647 switch (menu_check(&game_menu))
650 st_pause_ticks_stop();
653 update_load_save_game_menu(&save_game_menu, NO);
656 update_load_save_game_menu(&load_game_menu, YES);
659 st_pause_ticks_stop();
664 else if(current_menu == &options_menu)
666 process_options_menu();
668 else if(current_menu == &save_game_menu )
670 process_save_load_game_menu(YES);
672 else if(current_menu == &load_game_menu )
674 process_save_load_game_menu(NO);
679 /* Handle actions: */
681 if(!game_pause && !show_menu)
683 if (game_action() == 0)
685 /* == 0: no more lives */
686 /* == -1: continues */
696 if(debug_mode && tux.input.down == DOWN)
699 /*Draw the current scene to the screen */
700 /*If the machine running the game is too slow
701 skip the drawing of the frame (so the calculations are more precise and
702 the FPS aren't affected).*/
703 /*if( ! fps_fps < 50.0 )
706 jump = YES;*/ /*FIXME: Implement this tweak right.*/
709 /* Time stops in pause mode */
710 if(game_pause || show_menu )
715 /* Set the time the last update and the time of the current update */
716 last_update_time = update_time;
717 update_time = st_get_ticks();
720 /* Pause till next frame, if the machine running the game is too fast: */
721 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
722 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
723 if(last_update_time >= update_time - 12 && jump != YES )
725 /*if((update_time - last_update_time) < 10)
726 SDL_Delay((11 - (update_time - last_update_time))/2);*/
732 if (timer_check(&time_left))
734 /* are we low on time ? */
735 if ((timer_get_left(&time_left) < TIME_WARNING)
736 && (current_music != HURRYUP_MUSIC))
738 current_music = HURRYUP_MUSIC;
739 /* stop the others music, prepare to play the fast music */
748 player_kill(&tux,KILL);
751 /* Keep playing the correct music: */
753 if (!playing_music())
755 play_current_music();
758 /* Calculate frames per second */
762 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
764 if(!timer_check(&fps_timer))
766 timer_start(&fps_timer,1000);
772 while (!done && !quit);
778 level_free(¤t_level);
789 /* Load graphics/sounds shared between all levels: */
791 void loadshared(void)
794 char * herring_song_path; /* for loading herring song*/
798 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
799 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
800 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
802 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
803 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
804 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
806 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
807 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
808 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
810 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
811 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
812 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
815 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
818 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
821 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
824 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
827 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
830 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
833 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
836 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
838 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
841 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
844 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
847 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
849 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
852 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
855 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
858 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
861 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
864 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
867 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
870 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
872 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
875 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
878 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
881 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
883 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
886 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
889 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
892 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
896 texture_load(&ducktux_right ,DATA_PREFIX
897 "/images/shared/ducktux-right.png",
900 texture_load(&ducktux_left ,DATA_PREFIX
901 "/images/shared/ducktux-left.png",
904 texture_load(&skidtux_right ,DATA_PREFIX
905 "/images/shared/skidtux-right.png",
908 texture_load(&skidtux_left ,DATA_PREFIX
909 "/images/shared/skidtux-left.png",
912 texture_load(&duckfiretux_right ,DATA_PREFIX
913 "/images/shared/duckfiretux-right.png",
916 texture_load(&duckfiretux_left ,DATA_PREFIX
917 "/images/shared/duckfiretux-left.png",
920 texture_load(&skidfiretux_right ,DATA_PREFIX
921 "/images/shared/skidfiretux-right.png",
924 texture_load(&skidfiretux_left ,DATA_PREFIX
925 "/images/shared/skidfiretux-left.png",
931 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
933 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
940 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
942 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
945 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
948 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
954 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
955 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
961 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
963 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
969 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
972 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
975 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
978 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
982 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
985 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
988 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
991 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
999 texture_load(&img_bsod_left[0] ,DATA_PREFIX
1000 "/images/shared/bsod-left-0.png",
1003 texture_load(&img_bsod_left[1] ,DATA_PREFIX
1004 "/images/shared/bsod-left-1.png",
1007 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1008 "/images/shared/bsod-left-2.png",
1011 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1012 "/images/shared/bsod-left-3.png",
1015 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1016 "/images/shared/bsod-right-0.png",
1019 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1020 "/images/shared/bsod-right-1.png",
1023 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1024 "/images/shared/bsod-right-2.png",
1027 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1028 "/images/shared/bsod-right-3.png",
1031 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1032 "/images/shared/bsod-squished-left.png",
1035 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1036 "/images/shared/bsod-squished-right.png",
1039 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1040 "/images/shared/bsod-falling-left.png",
1043 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1044 "/images/shared/bsod-falling-right.png",
1050 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1051 "/images/shared/laptop-left-0.png",
1054 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1055 "/images/shared/laptop-left-1.png",
1058 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1059 "/images/shared/laptop-left-2.png",
1062 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1063 "/images/shared/laptop-right-0.png",
1066 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1067 "/images/shared/laptop-right-1.png",
1070 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1071 "/images/shared/laptop-right-2.png",
1074 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1075 "/images/shared/laptop-flat-left.png",
1078 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1079 "/images/shared/laptop-flat-right.png",
1082 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1083 "/images/shared/laptop-falling-left.png",
1086 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1087 "/images/shared/laptop-falling-right.png",
1093 texture_load(&img_money_left[0] ,DATA_PREFIX
1094 "/images/shared/bag-left-0.png",
1097 texture_load(&img_money_left[1] ,DATA_PREFIX
1098 "/images/shared/bag-left-1.png",
1101 texture_load(&img_money_right[0] ,DATA_PREFIX
1102 "/images/shared/bag-right-0.png",
1105 texture_load(&img_money_right[1] ,DATA_PREFIX
1106 "/images/shared/bag-right-1.png",
1113 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1114 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1119 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1121 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1128 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1131 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1134 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1137 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1143 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1148 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1152 /* Super background: */
1154 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1158 /* Sound effects: */
1160 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1161 // initialize sounds[i] with the correct pointer's value:
1162 // NULL or something else. And it will be dangerous to
1163 // play with not-initialized pointers.
1164 // This is also true with if (use_music)
1165 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1167 for (i = 0; i < NUM_SOUNDS; i++)
1168 sounds[i] = load_sound(soundfilenames[i]);
1171 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1172 strlen("SALCON.MOD") + 8));
1174 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1176 herring_song = load_song(herring_song_path);
1178 free(herring_song_path);
1183 /* Free shared data: */
1185 void unloadshared(void)
1189 for (i = 0; i < 3; i++)
1191 texture_free(&tux_right[i]);
1192 texture_free(&tux_left[i]);
1193 texture_free(&bigtux_right[i]);
1194 texture_free(&bigtux_left[i]);
1197 texture_free(&bigtux_right_jump);
1198 texture_free(&bigtux_left_jump);
1200 for (i = 0; i < 2; i++)
1202 texture_free(&cape_right[i]);
1203 texture_free(&cape_left[i]);
1204 texture_free(&bigcape_right[i]);
1205 texture_free(&bigcape_left[i]);
1208 texture_free(&ducktux_left);
1209 texture_free(&ducktux_right);
1211 texture_free(&skidtux_left);
1212 texture_free(&skidtux_right);
1214 for (i = 0; i < 4; i++)
1216 texture_free(&img_bsod_left[i]);
1217 texture_free(&img_bsod_right[i]);
1220 texture_free(&img_bsod_squished_left);
1221 texture_free(&img_bsod_squished_right);
1223 texture_free(&img_bsod_falling_left);
1224 texture_free(&img_bsod_falling_right);
1226 for (i = 0; i < 3; i++)
1228 texture_free(&img_laptop_left[i]);
1229 texture_free(&img_laptop_right[i]);
1232 texture_free(&img_laptop_flat_left);
1233 texture_free(&img_laptop_flat_right);
1235 texture_free(&img_laptop_falling_left);
1236 texture_free(&img_laptop_falling_right);
1238 for (i = 0; i < 2; i++)
1240 texture_free(&img_money_left[i]);
1241 texture_free(&img_money_right[i]);
1244 texture_free(&img_box_full);
1245 texture_free(&img_box_empty);
1247 texture_free(&img_water);
1248 for (i = 0; i < 3; i++)
1249 texture_free(&img_waves[i]);
1251 texture_free(&img_pole);
1252 texture_free(&img_poletop);
1254 for (i = 0; i < 2; i++)
1255 texture_free(&img_flag[i]);
1257 texture_free(&img_mints);
1258 texture_free(&img_coffee);
1260 for (i = 0; i < 4; i++)
1262 texture_free(&img_distro[i]);
1263 texture_free(&img_cloud[0][i]);
1264 texture_free(&img_cloud[1][i]);
1267 texture_free(&img_golden_herring);
1269 for (i = 0; i < NUM_SOUNDS; i++)
1270 free_chunk(sounds[i]);
1272 /* free the herring song */
1273 free_music( herring_song );
1277 /* Draw a tile on the screen: */
1279 void drawshape(float x, float y, unsigned char c)
1283 if (c == 'X' || c == 'x')
1284 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1285 else if (c == 'Y' || c == 'y')
1286 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1287 else if (c == 'A' || c =='B' || c == '!')
1288 texture_draw(&img_box_full, x, y, NO_UPDATE);
1290 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1291 else if (c >= 'C' && c <= 'F')
1292 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1293 else if (c >= 'c' && c <= 'f')
1294 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1295 else if (c >= 'G' && c <= 'J')
1296 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1297 else if (c >= 'g' && c <= 'j')
1298 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1300 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1302 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1304 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1306 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1310 z = (frame / 2) % 6;
1313 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1315 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1317 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1321 z = (frame / 3) % 3;
1323 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1326 texture_draw(&img_poletop, x, y, NO_UPDATE);
1329 texture_draw(&img_pole, x, y, NO_UPDATE);
1331 /* Mark this as the end position of the level! */
1337 z = (frame / 3) % 2;
1339 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1342 texture_draw(&img_water, x, y, NO_UPDATE);
1346 /* What shape is at some position? */
1348 unsigned char shape(float x, float y)
1357 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1359 c = current_level.tiles[yy][xx];
1370 int issolid(float x, float y)
1372 if (isbrick(x, y) ||
1374 (shape(x, y) == '[') ||
1375 (shape(x, y) == '=') ||
1376 (shape(x, y) == ']') ||
1377 (shape(x, y) == 'A') ||
1378 (shape(x, y) == 'B') ||
1379 (shape(x, y) == '!') ||
1380 (shape(x, y) == 'a'))
1389 int issolid(float x, float y)
1391 if (isbrick(x, y) ||
1392 isbrick(x + 31, y) ||
1395 (shape(x, y) == '[' ||
1396 shape(x + 31, y) == '[') ||
1397 (shape(x, y) == '=' ||
1398 shape(x + 31, y) == '=') ||
1399 (shape(x, y) == ']' ||
1400 shape(x + 31, y) == ']') ||
1401 (shape(x, y) == 'A' ||
1402 shape(x + 31, y) == 'A') ||
1403 (shape(x, y) == 'B' ||
1404 shape(x + 31, y) == 'B') ||
1405 (shape(x, y) == '!' ||
1406 shape(x + 31, y) == '!') ||
1407 (shape(x, y) == 'a' ||
1408 shape(x + 31, y) == 'a'))
1417 /* Is it a brick? */
1419 int isbrick(float x, float y)
1421 if (shape(x, y) == 'X' ||
1422 shape(x, y) == 'x' ||
1423 shape(x, y) == 'Y' ||
1435 int isice(float x, float y)
1437 if (shape(x, y) == '#')
1446 /* Is it a full box? */
1448 int isfullbox(float x, float y)
1450 if (shape(x, y) == 'A' ||
1451 shape(x, y) == 'B' ||
1460 /* Break a brick: */
1462 void trybreakbrick(float x, float y)
1466 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1468 /* Get a distro from it: */
1470 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1471 (int)(y / 32) * 32);
1473 if (counting_distros == NO)
1475 counting_distros = YES;
1476 distro_counter = 50;
1479 if (distro_counter <= 0)
1480 level_change(¤t_level,x, y, 'a');
1482 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1483 score = score + SCORE_DISTRO;
1488 /* Get rid of it: */
1490 level_change(¤t_level,x, y,'.');
1494 /* Replace it with broken bits: */
1496 add_broken_brick(((int)(x + 1) / 32) * 32,
1497 (int)(y / 32) * 32);
1500 /* Get some score: */
1502 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1503 score = score + SCORE_BRICK;
1508 /* Bounce a brick: */
1510 void bumpbrick(float x, float y)
1512 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1513 (int)(y / 32) * 32);
1515 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1521 void tryemptybox(float x, float y)
1523 if (isfullbox(x, y))
1525 if (shape(x, y) == 'A')
1528 /* Box with a distro! */
1530 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1531 (int)(y / 32) * 32 - 32);
1533 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1534 score = score + SCORE_DISTRO;
1537 else if (shape(x, y) == 'B')
1539 /* Add an upgrade! */
1541 if (tux.size == SMALL)
1543 /* Tux is small, add mints! */
1545 add_upgrade((int)((x + 1) / 32) * 32,
1546 (int)(y / 32) * 32 - 32,
1551 /* Tux is big, add coffee: */
1553 add_upgrade((int)((x + 1) / 32) * 32,
1554 (int)(y / 32) * 32 - 32,
1558 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1560 else if (shape(x, y) == '!')
1562 /* Add a golden herring */
1564 add_upgrade((int)((x + 1) / 32) * 32,
1565 (int)(y / 32) * 32 - 32,
1569 /* Empty the box: */
1571 level_change(¤t_level,x, y, 'a');
1576 /* Try to grab a distro: */
1578 void trygrabdistro(float x, float y, int bounciness)
1580 if (shape(x, y) == '$')
1582 level_change(¤t_level,x, y, '.');
1583 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1585 if (bounciness == BOUNCE)
1587 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1588 (int)(y / 32) * 32);
1591 score = score + SCORE_DISTRO;
1596 /* Try to bump a bad guy from below: */
1598 void trybumpbadguy(float x, float y)
1605 for (i = 0; i < num_bad_guys; i++)
1607 if (bad_guys[i].base.alive &&
1608 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1609 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1611 if (bad_guys[i].kind == BAD_BSOD ||
1612 bad_guys[i].kind == BAD_LAPTOP)
1614 bad_guys[i].dying = FALLING;
1615 bad_guys[i].base.ym = -8;
1616 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1624 for (i = 0; i < num_upgrades; i++)
1626 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1627 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1628 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1630 upgrades[i].base.xm = -upgrades[i].base.xm;
1631 upgrades[i].base.ym = -8;
1632 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1638 void drawstatus(void)
1642 sprintf(str, "%d", score);
1643 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1644 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1646 if(st_gl_mode != ST_GL_TEST)
1648 sprintf(str, "%d", hs_score);
1649 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1650 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1654 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1657 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1659 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1660 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1661 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1664 sprintf(str, "%d", distros);
1665 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1666 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1668 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1672 sprintf(str, "%2.1f", fps_fps);
1673 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1674 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1677 for(i=0; i < tux.lives; ++i)
1679 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1684 void drawendscreen(void)
1688 clearscreen(0, 0, 0);
1690 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1692 sprintf(str, "SCORE: %d", score);
1693 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1695 sprintf(str, "DISTROS: %d", distros);
1696 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1702 void drawresultscreen(void)
1706 clearscreen(0, 0, 0);
1708 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1710 sprintf(str, "SCORE: %d", score);
1711 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1713 sprintf(str, "DISTROS: %d", distros);
1714 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1720 void savegame(int slot)
1722 char savefile[1024];
1726 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1728 fi = fopen(savefile, "wb");
1732 fprintf(stderr, "Warning: I could not open the slot file ");
1737 fputs(level_subset, fi);
1739 fwrite(&level,sizeof(int),1,fi);
1740 fwrite(&score,sizeof(int),1,fi);
1741 fwrite(&distros,sizeof(int),1,fi);
1742 fwrite(&scroll_x,sizeof(float),1,fi);
1743 fwrite(&tux,sizeof(player_type),1,fi);
1744 timer_fwrite(&tux.invincible_timer,fi);
1745 printf("Time inv LEFT: %d\n",timer_get_left(&tux.invincible_timer));
1746 timer_fwrite(&tux.skidding_timer,fi);
1747 timer_fwrite(&tux.safe_timer,fi);
1748 timer_fwrite(&tux.frame_timer,fi);
1749 timer_fwrite(&time_left,fi);
1750 printf("Time LEFT: %d\n",timer_get_left(&time_left));
1751 ui = st_get_ticks();
1752 fwrite(&ui,sizeof(int),1,fi);
1758 void loadgame(int slot)
1760 char savefile[1024];
1765 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1767 fi = fopen(savefile, "rb");
1771 fprintf(stderr, "Warning: I could not open the slot file ");
1778 fgets(str, 100, fi);
1779 strcpy(level_subset, str);
1780 level_subset[strlen(level_subset)-1] = '\0';
1781 fread(&level,sizeof(int),1,fi);
1784 level_free(¤t_level);
1785 if(level_load(¤t_level,level_subset,level) != 0)
1789 activate_bad_guys();
1791 level_load_gfx(¤t_level);
1793 level_load_song(¤t_level);
1795 update_time = st_get_ticks();
1797 fread(&score,sizeof(int),1,fi);
1798 fread(&distros,sizeof(int),1,fi);
1799 fread(&scroll_x,sizeof(float),1,fi);
1800 fread(&tux,sizeof(player_type),1,fi);
1801 timer_fread(&tux.invincible_timer,fi);
1802 printf("Time inv LEFT: %d - %d\n",timer_get_left(&tux.invincible_timer),tux.invincible_timer.time);
1803 timer_fread(&tux.skidding_timer,fi);
1804 timer_fread(&tux.safe_timer,fi);
1805 timer_fread(&tux.frame_timer,fi);
1806 timer_fread(&time_left,fi);
1807 printf("Time LEFT: %d\n",timer_get_left(&time_left));
1808 fread(&ui,sizeof(int),1,fi);
1809 tux.hphysic.start_time += st_get_ticks() - ui;
1810 tux.vphysic.start_time += st_get_ticks() - ui;
1816 void slotinfo(char **pinfo, int slot)
1819 char slotfile[1024];
1823 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1825 fi = fopen(slotfile, "rb");
1827 sprintf(tmp,"Slot %d - ",slot);
1835 fgets(str, 100, fi);
1836 str[strlen(str)-1] = '\0';
1838 strcat(tmp, " / Level:");
1839 fread(&slot_level,sizeof(int),1,fi);
1840 sprintf(str,"%d",slot_level);
1845 *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));