6 by Bill Kendrick & Tobias Glaesser
7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - February 1st, 2004
23 #include <sys/types.h>
32 #include "high_scores.h"
40 #include "collision.h"
42 /* extern variables */
44 st_level current_level;
45 int game_started = NO;
47 /* Local variables: */
49 static texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2];
50 static texture_type img_cloud[2][4];
51 static SDL_Event event;
53 static char level_subset[100];
56 static int st_gl_mode;
57 static unsigned int last_update_time;
58 static unsigned int update_time;
59 static int pause_menu_frame;
61 /* Local function prototypes: */
63 void levelintro(void);
64 void loadshared(void);
65 void unloadshared(void);
66 void drawstatus(void);
67 void drawendscreen(void);
68 void drawresultscreen(void);
76 sprintf(str, "LEVEL %d", level);
77 text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
79 sprintf(str, "%s", current_level.name);
80 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
82 sprintf(str, "TUX x %d", tux.lives);
83 text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
91 void start_timers(void)
93 timer_start(&time_left,current_level.time_left*1000);
94 st_pause_ticks_init();
95 update_time = st_get_ticks();
98 void activate_bad_guys(void)
102 /* Activate bad guys: */
104 for (y = 0; y < 15; y++)
106 for (x = 0; x < current_level.width; x++)
108 if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
110 add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
111 current_level.tiles[y][x] = '.';
118 /* --- GAME EVENT! --- */
120 void game_event(void)
122 while (SDL_PollEvent(&event))
126 case SDL_QUIT: /* Quit event - quit: */
129 case SDL_KEYDOWN: /* A keypress! */
130 key = event.key.keysym.sym;
132 /* Check for menu-events, if the menu is shown */
134 menu_event(&event.key.keysym);
136 if(player_key_event(&tux,key,DOWN))
141 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
144 if(st_gl_mode == ST_GL_TEST)
148 menu_set_current(&game_menu);
150 st_pause_ticks_stop();
154 menu_set_current(&game_menu);
156 st_pause_ticks_start();
164 case SDL_KEYUP: /* A keyrelease! */
165 key = event.key.keysym.sym;
167 if(player_key_event(&tux,key,UP))
178 st_pause_ticks_stop();
183 st_pause_ticks_start();
188 if(debug_mode == YES)
190 tux.size = !tux.size;
193 tux.base.height = 64;
196 tux.base.height = 32;
200 if(debug_mode == YES)
204 if(debug_mode == YES)
208 if(debug_mode == YES)
212 if(debug_mode == YES)
213 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
216 if(debug_mode == YES)
220 if(debug_mode == YES)
229 case SDL_JOYAXISMOTION:
230 switch(event.jaxis.axis)
233 if (event.jaxis.value < -1024)
234 tux.input.left = DOWN;
235 else if (event.jaxis.value > 1024)
238 if (event.jaxis.value > 1024)
239 tux.input.right = DOWN;
240 else if (event.jaxis.value < -1024)
241 tux.input.right = UP;
244 if (event.jaxis.value > 1024)
245 tux.input.down = DOWN;
246 else if (event.jaxis.value < -1024)
249 /* Handle joystick for the menu */
252 if(tux.input.down == DOWN)
253 menuaction = MN_DOWN;
262 case SDL_JOYBUTTONDOWN:
263 if (event.jbutton.button == JOY_A)
265 else if (event.jbutton.button == JOY_B)
266 tux.input.fire = DOWN;
268 case SDL_JOYBUTTONUP:
269 if (event.jbutton.button == JOY_A)
271 else if (event.jbutton.button == JOY_B)
287 /* --- GAME ACTION! --- */
289 int game_action(void)
293 /* (tux_dying || next_level) */
294 if (tux.dying || next_level)
296 /* Tux either died, or reached the end of a level! */
304 /* End of a level! */
307 if(st_gl_mode != ST_GL_TEST)
309 player_level_begin(&tux);
315 /* No more lives!? */
319 if(st_gl_mode != ST_GL_TEST)
322 if(st_gl_mode != ST_GL_TEST)
324 if (score > hs_score)
328 level_free(¤t_level);
333 } /* if (lives < 0) */
336 /* Either way, (re-)load the (next) level... */
338 player_level_begin(&tux);
340 level_free(¤t_level);
341 if(level_load(¤t_level,level_subset,level) != 0)
347 level_load_gfx(¤t_level);
349 level_load_song(¤t_level);
350 if(st_gl_mode != ST_GL_TEST)
357 /* Handle bouncy distros: */
359 for (i = 0; i < num_bouncy_distros; i++)
361 bouncy_distro_action(&bouncy_distros[i]);
365 /* Handle broken bricks: */
367 for (i = 0; i < num_broken_bricks; i++)
369 broken_brick_action(&broken_bricks[i]);
373 /* Handle distro counting: */
375 if (counting_distros == YES)
379 if (distro_counter <= 0)
380 counting_distros = -1;
384 /* Handle bouncy bricks: */
386 for (i = 0; i < num_bouncy_bricks; i++)
388 bouncy_brick_action(&bouncy_bricks[i]);
392 /* Handle floating scores: */
394 for (i = 0; i < num_floating_scores; i++)
396 floating_score_action(&floating_scores[i]);
400 /* Handle bullets: */
402 for (i = 0; i < num_bullets; ++i)
404 bullet_action(&bullets[i]);
407 /* Handle upgrades: */
409 for (i = 0; i < num_upgrades; i++)
411 upgrade_action(&upgrades[i]);
415 /* Handle bad guys: */
417 for (i = 0; i < num_bad_guys; i++)
419 badguy_action(&bad_guys[i]);
422 /* Handle all possible collisions. */
428 /* --- GAME DRAW! --- */
436 if (tux.dying && (frame % 4) == 0)
437 clearscreen(255, 255, 255);
438 else if(timer_check(&super_bkgd_timer))
439 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
442 /* Draw the real background */
443 if(current_level.bkgd_image[0] != '\0')
445 s = (int)scroll_x / 30;
446 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
447 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
451 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
455 /* Draw background: */
457 for (y = 0; y < 15; ++y)
459 for (x = 0; x < 21; ++x)
461 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
462 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
467 /* (Bouncy bricks): */
469 for (i = 0; i < num_bouncy_bricks; ++i)
471 bouncy_brick_draw(&bouncy_bricks[i]);
477 for (i = 0; i < num_bad_guys; ++i)
479 badguy_draw(&bad_guys[i]);
488 for (i = 0; i < num_bullets; ++i)
490 bullet_draw(&bullets[i]);
493 /* (Floating scores): */
495 for (i = 0; i < num_floating_scores; ++i)
497 floating_score_draw(&floating_scores[i]);
503 for (i = 0; i < num_upgrades; ++i)
505 upgrade_draw(&upgrades[i]);
509 /* (Bouncy distros): */
511 for (i = 0; i < num_bouncy_distros; ++i)
513 bouncy_distro_draw(&bouncy_distros[i]);
517 /* (Broken bricks): */
519 for (i = 0; i < num_broken_bricks; ++i)
521 broken_brick_draw(&broken_bricks[i]);
530 for(i = 0; i < x; ++i)
532 fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1);
534 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
535 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
539 menu_process_current();
541 /* (Update it all!) */
548 /* --- GAME LOOP! --- */
550 int gameloop(char * subset, int levelnb, int mode)
552 int fps_cnt, jump, done;
553 timer_type fps_timer, frame_timer;
554 timer_init(&fps_timer, YES);
555 timer_init(&frame_timer, YES);
561 strcpy(level_subset,subset);
563 if(st_gl_mode != ST_GL_LOAD_GAME)
569 if(level_load(¤t_level,level_subset,level) != 0)
571 level_load_gfx(¤t_level);
573 level_load_song(¤t_level);
579 if(st_gl_mode != ST_GL_TEST)
584 if(st_gl_mode == ST_GL_PLAY)
588 timer_init(&time_left,YES);
591 if(st_gl_mode == ST_GL_LOAD_GAME)
595 /* --- MAIN GAME LOOP!!! --- */
602 timer_init(&fps_timer,YES);
603 timer_init(&frame_timer,YES);
608 clearscreen(0, 0, 0);
611 while (SDL_PollEvent(&event))
619 /* Calculate the movement-factor */
620 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
622 if(!timer_check(&frame_timer))
624 timer_start(&frame_timer,25);
631 tux.input.old_fire = tux.input.fire;
637 if(current_menu == &game_menu)
639 switch (menu_check(&game_menu))
642 st_pause_ticks_stop();
645 update_load_save_game_menu(&save_game_menu, NO);
648 update_load_save_game_menu(&load_game_menu, YES);
651 st_pause_ticks_stop();
656 else if(current_menu == &options_menu)
658 process_options_menu();
660 else if(current_menu == &save_game_menu )
662 process_save_load_game_menu(YES);
664 else if(current_menu == &load_game_menu )
666 process_save_load_game_menu(NO);
671 /* Handle actions: */
673 if(!game_pause && !show_menu)
675 if (game_action() == 0)
677 /* == 0: no more lives */
678 /* == -1: continues */
688 if(tux.input.down == DOWN)
691 /*Draw the current scene to the screen */
692 /*If the machine running the game is too slow
693 skip the drawing of the frame (so the calculations are more precise and
694 the FPS aren't affected).*/
695 /*if( ! fps_fps < 50.0 )
698 jump = YES;*/ /*FIXME: Implement this tweak right.*/
701 /* Time stops in pause mode */
702 if(game_pause || show_menu )
707 /* Set the time the last update and the time of the current update */
708 last_update_time = update_time;
709 update_time = st_get_ticks();
712 /* Pause till next frame, if the machine running the game is too fast: */
713 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
714 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
715 if(last_update_time >= update_time - 12 && jump != YES )
717 /*if((update_time - last_update_time) < 10)
718 SDL_Delay((11 - (update_time - last_update_time))/2);*/
724 if (timer_check(&time_left))
726 /* are we low on time ? */
727 if ((timer_get_left(&time_left) < TIME_WARNING)
728 && (current_music != HURRYUP_MUSIC))
730 current_music = HURRYUP_MUSIC;
731 /* stop the others music, prepare to play the fast music */
740 player_kill(&tux,KILL);
743 /* Keep playing the correct music: */
745 if (!playing_music())
747 play_current_music();
750 /* Calculate frames per second */
754 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
756 if(!timer_check(&fps_timer))
758 timer_start(&fps_timer,1000);
764 while (!done && !quit);
770 level_free(¤t_level);
781 /* Load graphics/sounds shared between all levels: */
783 void loadshared(void)
786 char * herring_song_path; /* for loading herring song*/
790 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
791 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
792 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
794 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
795 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
796 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
798 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
799 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
800 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
802 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
803 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
804 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
807 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
810 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
813 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
816 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
819 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
822 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
825 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
828 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
830 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
833 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
836 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
839 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
841 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
844 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
847 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
850 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
853 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
856 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
859 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
862 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
864 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
867 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
870 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
873 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
875 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
878 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
881 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
884 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
888 texture_load(&ducktux_right ,DATA_PREFIX
889 "/images/shared/ducktux-right.png",
892 texture_load(&ducktux_left ,DATA_PREFIX
893 "/images/shared/ducktux-left.png",
896 texture_load(&skidtux_right ,DATA_PREFIX
897 "/images/shared/skidtux-right.png",
900 texture_load(&skidtux_left ,DATA_PREFIX
901 "/images/shared/skidtux-left.png",
904 texture_load(&duckfiretux_right ,DATA_PREFIX
905 "/images/shared/duckfiretux-right.png",
908 texture_load(&duckfiretux_left ,DATA_PREFIX
909 "/images/shared/duckfiretux-left.png",
912 texture_load(&skidfiretux_right ,DATA_PREFIX
913 "/images/shared/skidfiretux-right.png",
916 texture_load(&skidfiretux_left ,DATA_PREFIX
917 "/images/shared/skidfiretux-left.png",
923 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
925 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
932 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
934 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
937 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
940 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
946 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
947 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
953 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
955 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
961 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
964 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
967 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
970 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
974 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
977 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
980 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
983 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
991 texture_load(&img_bsod_left[0] ,DATA_PREFIX
992 "/images/shared/bsod-left-0.png",
995 texture_load(&img_bsod_left[1] ,DATA_PREFIX
996 "/images/shared/bsod-left-1.png",
999 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1000 "/images/shared/bsod-left-2.png",
1003 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1004 "/images/shared/bsod-left-3.png",
1007 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1008 "/images/shared/bsod-right-0.png",
1011 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1012 "/images/shared/bsod-right-1.png",
1015 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1016 "/images/shared/bsod-right-2.png",
1019 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1020 "/images/shared/bsod-right-3.png",
1023 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1024 "/images/shared/bsod-squished-left.png",
1027 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1028 "/images/shared/bsod-squished-right.png",
1031 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1032 "/images/shared/bsod-falling-left.png",
1035 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1036 "/images/shared/bsod-falling-right.png",
1042 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1043 "/images/shared/laptop-left-0.png",
1046 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1047 "/images/shared/laptop-left-1.png",
1050 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1051 "/images/shared/laptop-left-2.png",
1054 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1055 "/images/shared/laptop-right-0.png",
1058 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1059 "/images/shared/laptop-right-1.png",
1062 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1063 "/images/shared/laptop-right-2.png",
1066 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1067 "/images/shared/laptop-flat-left.png",
1070 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1071 "/images/shared/laptop-flat-right.png",
1074 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1075 "/images/shared/laptop-falling-left.png",
1078 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1079 "/images/shared/laptop-falling-right.png",
1085 texture_load(&img_money_left[0] ,DATA_PREFIX
1086 "/images/shared/bag-left-0.png",
1089 texture_load(&img_money_left[1] ,DATA_PREFIX
1090 "/images/shared/bag-left-1.png",
1093 texture_load(&img_money_right[0] ,DATA_PREFIX
1094 "/images/shared/bag-right-0.png",
1097 texture_load(&img_money_right[1] ,DATA_PREFIX
1098 "/images/shared/bag-right-1.png",
1105 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1106 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1111 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1113 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1120 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1123 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1126 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1129 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1135 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1140 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1144 /* Super background: */
1146 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1150 /* Sound effects: */
1152 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1153 // initialize sounds[i] with the correct pointer's value:
1154 // NULL or something else. And it will be dangerous to
1155 // play with not-initialized pointers.
1156 // This is also true with if (use_music)
1157 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1159 for (i = 0; i < NUM_SOUNDS; i++)
1160 sounds[i] = load_sound(soundfilenames[i]);
1163 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1164 strlen("SALCON.MOD") + 8));
1166 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1168 herring_song = load_song(herring_song_path);
1170 free(herring_song_path);
1175 /* Free shared data: */
1177 void unloadshared(void)
1181 for (i = 0; i < 3; i++)
1183 texture_free(&tux_right[i]);
1184 texture_free(&tux_left[i]);
1185 texture_free(&bigtux_right[i]);
1186 texture_free(&bigtux_left[i]);
1189 texture_free(&bigtux_right_jump);
1190 texture_free(&bigtux_left_jump);
1192 for (i = 0; i < 2; i++)
1194 texture_free(&cape_right[i]);
1195 texture_free(&cape_left[i]);
1196 texture_free(&bigcape_right[i]);
1197 texture_free(&bigcape_left[i]);
1200 texture_free(&ducktux_left);
1201 texture_free(&ducktux_right);
1203 texture_free(&skidtux_left);
1204 texture_free(&skidtux_right);
1206 for (i = 0; i < 4; i++)
1208 texture_free(&img_bsod_left[i]);
1209 texture_free(&img_bsod_right[i]);
1212 texture_free(&img_bsod_squished_left);
1213 texture_free(&img_bsod_squished_right);
1215 texture_free(&img_bsod_falling_left);
1216 texture_free(&img_bsod_falling_right);
1218 for (i = 0; i < 3; i++)
1220 texture_free(&img_laptop_left[i]);
1221 texture_free(&img_laptop_right[i]);
1224 texture_free(&img_laptop_flat_left);
1225 texture_free(&img_laptop_flat_right);
1227 texture_free(&img_laptop_falling_left);
1228 texture_free(&img_laptop_falling_right);
1230 for (i = 0; i < 2; i++)
1232 texture_free(&img_money_left[i]);
1233 texture_free(&img_money_right[i]);
1236 texture_free(&img_box_full);
1237 texture_free(&img_box_empty);
1239 texture_free(&img_water);
1240 for (i = 0; i < 3; i++)
1241 texture_free(&img_waves[i]);
1243 texture_free(&img_pole);
1244 texture_free(&img_poletop);
1246 for (i = 0; i < 2; i++)
1247 texture_free(&img_flag[i]);
1249 texture_free(&img_mints);
1250 texture_free(&img_coffee);
1252 for (i = 0; i < 4; i++)
1254 texture_free(&img_distro[i]);
1255 texture_free(&img_cloud[0][i]);
1256 texture_free(&img_cloud[1][i]);
1259 texture_free(&img_golden_herring);
1261 for (i = 0; i < NUM_SOUNDS; i++)
1262 free_chunk(sounds[i]);
1264 /* free the herring song */
1265 free_music( herring_song );
1269 /* Draw a tile on the screen: */
1271 void drawshape(float x, float y, unsigned char c)
1275 if (c == 'X' || c == 'x')
1276 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1277 else if (c == 'Y' || c == 'y')
1278 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1279 else if (c == 'A' || c =='B' || c == '!')
1280 texture_draw(&img_box_full, x, y, NO_UPDATE);
1282 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1283 else if (c >= 'C' && c <= 'F')
1284 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1285 else if (c >= 'c' && c <= 'f')
1286 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1287 else if (c >= 'G' && c <= 'J')
1288 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1289 else if (c >= 'g' && c <= 'j')
1290 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1292 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1294 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1296 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1298 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1302 z = (frame / 2) % 6;
1305 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1307 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1309 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1313 z = (frame / 3) % 3;
1315 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1318 texture_draw(&img_poletop, x, y, NO_UPDATE);
1321 texture_draw(&img_pole, x, y, NO_UPDATE);
1323 /* Mark this as the end position of the level! */
1329 z = (frame / 3) % 2;
1331 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1334 texture_draw(&img_water, x, y, NO_UPDATE);
1338 /* What shape is at some position? */
1340 unsigned char shape(float x, float y)
1349 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1351 c = current_level.tiles[yy][xx];
1362 int issolid(float x, float y)
1364 if (isbrick(x, y) ||
1366 (shape(x, y) == '[') ||
1367 (shape(x, y) == '=') ||
1368 (shape(x, y) == ']') ||
1369 (shape(x, y) == 'A') ||
1370 (shape(x, y) == 'B') ||
1371 (shape(x, y) == '!') ||
1372 (shape(x, y) == 'a'))
1381 int issolid(float x, float y)
1383 if (isbrick(x, y) ||
1384 isbrick(x + 31, y) ||
1387 (shape(x, y) == '[' ||
1388 shape(x + 31, y) == '[') ||
1389 (shape(x, y) == '=' ||
1390 shape(x + 31, y) == '=') ||
1391 (shape(x, y) == ']' ||
1392 shape(x + 31, y) == ']') ||
1393 (shape(x, y) == 'A' ||
1394 shape(x + 31, y) == 'A') ||
1395 (shape(x, y) == 'B' ||
1396 shape(x + 31, y) == 'B') ||
1397 (shape(x, y) == '!' ||
1398 shape(x + 31, y) == '!') ||
1399 (shape(x, y) == 'a' ||
1400 shape(x + 31, y) == 'a'))
1409 /* Is it a brick? */
1411 int isbrick(float x, float y)
1413 if (shape(x, y) == 'X' ||
1414 shape(x, y) == 'x' ||
1415 shape(x, y) == 'Y' ||
1427 int isice(float x, float y)
1429 if (shape(x, y) == '#')
1438 /* Is it a full box? */
1440 int isfullbox(float x, float y)
1442 if (shape(x, y) == 'A' ||
1443 shape(x, y) == 'B' ||
1452 /* Break a brick: */
1454 void trybreakbrick(float x, float y)
1458 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1460 /* Get a distro from it: */
1462 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1463 (int)(y / 32) * 32);
1465 if (counting_distros == NO)
1467 counting_distros = YES;
1468 distro_counter = 50;
1471 if (distro_counter <= 0)
1472 level_change(¤t_level,x, y, 'a');
1474 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1475 score = score + SCORE_DISTRO;
1480 /* Get rid of it: */
1482 level_change(¤t_level,x, y,'.');
1486 /* Replace it with broken bits: */
1488 add_broken_brick(((int)(x + 1) / 32) * 32,
1489 (int)(y / 32) * 32);
1492 /* Get some score: */
1494 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1495 score = score + SCORE_BRICK;
1500 /* Bounce a brick: */
1502 void bumpbrick(float x, float y)
1504 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1505 (int)(y / 32) * 32);
1507 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1513 void tryemptybox(float x, float y)
1515 if (isfullbox(x, y))
1517 if (shape(x, y) == 'A')
1520 /* Box with a distro! */
1522 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1523 (int)(y / 32) * 32 - 32);
1525 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1526 score = score + SCORE_DISTRO;
1529 else if (shape(x, y) == 'B')
1531 /* Add an upgrade! */
1533 if (tux.size == SMALL)
1535 /* Tux is small, add mints! */
1537 add_upgrade((int)((x + 1) / 32) * 32,
1538 (int)(y / 32) * 32 - 32,
1543 /* Tux is big, add coffee: */
1545 add_upgrade((int)((x + 1) / 32) * 32,
1546 (int)(y / 32) * 32 - 32,
1550 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1552 else if (shape(x, y) == '!')
1554 /* Add a golden herring */
1556 add_upgrade((int)((x + 1) / 32) * 32,
1557 (int)(y / 32) * 32 - 32,
1561 /* Empty the box: */
1563 level_change(¤t_level,x, y, 'a');
1568 /* Try to grab a distro: */
1570 void trygrabdistro(float x, float y, int bounciness)
1572 if (shape(x, y) == '$')
1574 level_change(¤t_level,x, y, '.');
1575 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1577 if (bounciness == BOUNCE)
1579 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1580 (int)(y / 32) * 32);
1583 score = score + SCORE_DISTRO;
1588 /* Try to bump a bad guy from below: */
1590 void trybumpbadguy(float x, float y)
1597 for (i = 0; i < num_bad_guys; i++)
1599 if (bad_guys[i].base.alive &&
1600 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1601 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1603 if (bad_guys[i].kind == BAD_BSOD ||
1604 bad_guys[i].kind == BAD_LAPTOP)
1606 bad_guys[i].dying = FALLING;
1607 bad_guys[i].base.ym = -8;
1608 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1616 for (i = 0; i < num_upgrades; i++)
1618 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1619 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1620 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1622 upgrades[i].base.xm = -upgrades[i].base.xm;
1623 upgrades[i].base.ym = -8;
1624 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1630 void drawstatus(void)
1634 sprintf(str, "%d", score);
1635 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1636 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1638 if(st_gl_mode != ST_GL_TEST)
1640 sprintf(str, "%d", hs_score);
1641 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1642 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1646 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1649 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1651 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1652 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1653 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1656 sprintf(str, "%d", distros);
1657 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1658 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1660 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1664 sprintf(str, "%2.1f", fps_fps);
1665 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1666 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1669 for(i=0; i < tux.lives; ++i)
1671 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1676 void drawendscreen(void)
1680 clearscreen(0, 0, 0);
1682 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1684 sprintf(str, "SCORE: %d", score);
1685 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1687 sprintf(str, "DISTROS: %d", distros);
1688 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1694 void drawresultscreen(void)
1698 clearscreen(0, 0, 0);
1700 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1702 sprintf(str, "SCORE: %d", score);
1703 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1705 sprintf(str, "DISTROS: %d", distros);
1706 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1712 void savegame(int slot)
1714 char savefile[1024];
1718 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1720 fi = fopen(savefile, "wb");
1724 fprintf(stderr, "Warning: I could not open the slot file ");
1729 fputs(level_subset, fi);
1731 fwrite(&level,sizeof(int),1,fi);
1732 fwrite(&score,sizeof(int),1,fi);
1733 fwrite(&distros,sizeof(int),1,fi);
1734 fwrite(&tux,sizeof(player_type),1,fi);
1735 fwrite(&scroll_x,sizeof(float),1,fi);
1736 fwrite(&time_left,sizeof(float),1,fi);
1737 ui = st_get_ticks();
1738 fwrite(&ui,sizeof(int),1,fi);
1744 void loadgame(int slot)
1746 char savefile[1024];
1751 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1753 fi = fopen(savefile, "rb");
1757 fprintf(stderr, "Warning: I could not open the slot file ");
1764 fgets(str, 100, fi);
1765 strcpy(level_subset, str);
1766 level_subset[strlen(level_subset)-1] = '\0';
1767 fread(&level,sizeof(int),1,fi);
1770 level_free(¤t_level);
1771 if(level_load(¤t_level,level_subset,level) != 0)
1775 activate_bad_guys();
1777 level_load_gfx(¤t_level);
1779 level_load_song(¤t_level);
1781 timer_start(&time_left,current_level.time_left*1000);
1782 update_time = st_get_ticks();
1784 fread(&score,sizeof(int),1,fi);
1785 fread(&distros,sizeof(int),1,fi);
1786 fread(&tux,sizeof(player_type),1,fi);
1787 fread(&scroll_x,sizeof(float),1,fi);
1788 fread(&time_left,sizeof(float),1,fi);
1789 fread(&ui,sizeof(int),1,fi);
1790 time_left.time += st_get_ticks() - ui;
1791 tux.invincible_timer.time += st_get_ticks() - ui;
1792 tux.skidding_timer.time += st_get_ticks() - ui;
1793 tux.safe_timer.time += st_get_ticks() - ui;
1794 tux.vphysic.start_time += st_get_ticks() - ui;
1795 tux.hphysic.start_time += st_get_ticks() - ui;
1796 tux.vphysic.start_time += st_get_ticks() - ui;
1802 void slotinfo(char **pinfo, int slot)
1805 char slotfile[1024];
1809 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1811 fi = fopen(slotfile, "rb");
1813 sprintf(tmp,"Slot %d - ",slot);
1821 fgets(str, 100, fi);
1822 str[strlen(str)-1] = '\0';
1824 strcat(tmp, " / Level:");
1825 fread(&slot_level,sizeof(int),1,fi);
1826 sprintf(str,"%d",slot_level);
1831 *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));