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;
62 /* Local function prototypes: */
64 void levelintro(void);
65 void loadshared(void);
66 void unloadshared(void);
67 void drawstatus(void);
68 void drawendscreen(void);
69 void drawresultscreen(void);
77 sprintf(str, "LEVEL %d", level);
78 text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
80 sprintf(str, "%s", current_level.name);
81 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
83 sprintf(str, "TUX x %d", tux.lives);
84 text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
92 void start_timers(void)
94 timer_start(&time_left,current_level.time_left*1000);
95 st_pause_ticks_init();
96 update_time = st_get_ticks();
99 void activate_bad_guys(void)
103 /* Activate bad guys: */
105 for (y = 0; y < 15; y++)
107 for (x = 0; x < current_level.width; x++)
109 if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
111 add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
112 current_level.tiles[y][x] = '.';
119 /* --- GAME EVENT! --- */
121 void game_event(void)
123 while (SDL_PollEvent(&event))
127 case SDL_QUIT: /* Quit event - quit: */
130 case SDL_KEYDOWN: /* A keypress! */
131 key = event.key.keysym.sym;
133 /* Check for menu-events, if the menu is shown */
135 menu_event(&event.key.keysym);
137 if(player_key_event(&tux,key,DOWN))
142 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
145 if(st_gl_mode == ST_GL_TEST)
149 menu_set_current(&game_menu);
151 st_pause_ticks_stop();
155 menu_set_current(&game_menu);
157 st_pause_ticks_start();
165 case SDL_KEYUP: /* A keyrelease! */
166 key = event.key.keysym.sym;
168 if(player_key_event(&tux,key,UP))
179 st_pause_ticks_stop();
184 st_pause_ticks_start();
189 if(debug_mode == YES)
191 tux.size = !tux.size;
194 tux.base.height = 64;
197 tux.base.height = 32;
201 if(debug_mode == YES)
205 if(debug_mode == YES)
209 if(debug_mode == YES)
213 if(debug_mode == YES)
214 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
217 if(debug_mode == YES)
221 if(debug_mode == YES)
235 case SDL_JOYAXISMOTION:
236 switch(event.jaxis.axis)
239 if (event.jaxis.value < -1024)
240 tux.input.left = DOWN;
241 else if (event.jaxis.value > 1024)
244 if (event.jaxis.value > 1024)
245 tux.input.right = DOWN;
246 else if (event.jaxis.value < -1024)
247 tux.input.right = UP;
250 if (event.jaxis.value > 1024)
251 tux.input.down = DOWN;
252 else if (event.jaxis.value < -1024)
255 /* Handle joystick for the menu */
258 if(tux.input.down == DOWN)
259 menuaction = MN_DOWN;
268 case SDL_JOYBUTTONDOWN:
269 if (event.jbutton.button == JOY_A)
271 else if (event.jbutton.button == JOY_B)
272 tux.input.fire = DOWN;
274 case SDL_JOYBUTTONUP:
275 if (event.jbutton.button == JOY_A)
277 else if (event.jbutton.button == JOY_B)
294 /* --- GAME ACTION! --- */
296 int game_action(void)
300 /* (tux_dying || next_level) */
301 if (tux.dying || next_level)
303 /* Tux either died, or reached the end of a level! */
310 /* End of a level! */
313 if(st_gl_mode != ST_GL_TEST)
320 level_free(¤t_level);
326 player_level_begin(&tux);
332 /* No more lives!? */
336 if(st_gl_mode != ST_GL_TEST)
339 if(st_gl_mode != ST_GL_TEST)
341 if (score > hs_score)
345 level_free(¤t_level);
350 } /* if (lives < 0) */
353 /* Either way, (re-)load the (next) level... */
355 player_level_begin(&tux);
357 level_free(¤t_level);
358 if(level_load(¤t_level,level_subset,level) != 0)
364 level_load_gfx(¤t_level);
366 level_load_song(¤t_level);
367 if(st_gl_mode != ST_GL_TEST)
371 play_current_music();
376 /* Handle bouncy distros: */
378 for (i = 0; i < num_bouncy_distros; i++)
380 bouncy_distro_action(&bouncy_distros[i]);
384 /* Handle broken bricks: */
386 for (i = 0; i < num_broken_bricks; i++)
388 broken_brick_action(&broken_bricks[i]);
392 /* Handle distro counting: */
394 if (counting_distros == YES)
398 if (distro_counter <= 0)
399 counting_distros = -1;
403 /* Handle bouncy bricks: */
405 for (i = 0; i < num_bouncy_bricks; i++)
407 bouncy_brick_action(&bouncy_bricks[i]);
411 /* Handle floating scores: */
413 for (i = 0; i < num_floating_scores; i++)
415 floating_score_action(&floating_scores[i]);
419 /* Handle bullets: */
421 for (i = 0; i < num_bullets; ++i)
423 bullet_action(&bullets[i]);
426 /* Handle upgrades: */
428 for (i = 0; i < num_upgrades; i++)
430 upgrade_action(&upgrades[i]);
434 /* Handle bad guys: */
436 for (i = 0; i < num_bad_guys; i++)
438 badguy_action(&bad_guys[i]);
441 /* Handle all possible collisions. */
447 /* --- GAME DRAW! --- */
455 if (tux.dying && (frame % 4) == 0)
456 clearscreen(255, 255, 255);
457 else if(timer_check(&super_bkgd_timer))
458 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
461 /* Draw the real background */
462 if(current_level.bkgd_image[0] != '\0')
464 s = (int)scroll_x / 30;
465 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
466 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
470 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
474 /* Draw background: */
476 for (y = 0; y < 15; ++y)
478 for (x = 0; x < 21; ++x)
480 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
481 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
486 /* (Bouncy bricks): */
488 for (i = 0; i < num_bouncy_bricks; ++i)
490 bouncy_brick_draw(&bouncy_bricks[i]);
496 for (i = 0; i < num_bad_guys; ++i)
498 badguy_draw(&bad_guys[i]);
507 for (i = 0; i < num_bullets; ++i)
509 bullet_draw(&bullets[i]);
512 /* (Floating scores): */
514 for (i = 0; i < num_floating_scores; ++i)
516 floating_score_draw(&floating_scores[i]);
522 for (i = 0; i < num_upgrades; ++i)
524 upgrade_draw(&upgrades[i]);
528 /* (Bouncy distros): */
530 for (i = 0; i < num_bouncy_distros; ++i)
532 bouncy_distro_draw(&bouncy_distros[i]);
536 /* (Broken bricks): */
538 for (i = 0; i < num_broken_bricks; ++i)
540 broken_brick_draw(&broken_bricks[i]);
549 for(i = 0; i < x; ++i)
551 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);
553 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
554 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
558 menu_process_current();
560 /* (Update it all!) */
567 /* --- GAME LOOP! --- */
569 int gameloop(char * subset, int levelnb, int mode)
571 int fps_cnt, jump, done;
572 timer_type fps_timer, frame_timer;
573 timer_init(&fps_timer, YES);
574 timer_init(&frame_timer, YES);
580 strcpy(level_subset,subset);
586 if(level_load(¤t_level,level_subset,level) != 0)
588 level_load_gfx(¤t_level);
590 level_load_song(¤t_level);
594 if(st_gl_mode != ST_GL_TEST)
599 if(st_gl_mode == ST_GL_PLAY)
603 timer_init(&time_left,YES);
606 if(st_gl_mode == ST_GL_LOAD_GAME)
610 /* --- MAIN GAME LOOP!!! --- */
617 timer_init(&fps_timer,YES);
618 timer_init(&frame_timer,YES);
623 clearscreen(0, 0, 0);
627 play_current_music();
630 while (SDL_PollEvent(&event))
638 /* Calculate the movement-factor */
639 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
641 if(!timer_check(&frame_timer))
643 timer_start(&frame_timer,25);
649 tux.input.old_fire = tux.input.fire;
655 if(current_menu == &game_menu)
657 switch (menu_check(&game_menu))
660 st_pause_ticks_stop();
663 update_load_save_game_menu(&save_game_menu, NO);
666 update_load_save_game_menu(&load_game_menu, YES);
669 st_pause_ticks_stop();
674 else if(current_menu == &options_menu)
676 process_options_menu();
678 else if(current_menu == &save_game_menu )
680 process_save_load_game_menu(YES);
682 else if(current_menu == &load_game_menu )
684 process_save_load_game_menu(NO);
689 /* Handle actions: */
691 if(!game_pause && !show_menu)
693 /*float z = frame_ratio;
697 if (game_action() == 0)
699 /* == 0: no more lives */
700 /* == -1: continues */
712 if(debug_mode && debug_fps == YES)
715 /*Draw the current scene to the screen */
716 /*If the machine running the game is too slow
717 skip the drawing of the frame (so the calculations are more precise and
718 the FPS aren't affected).*/
719 /*if( ! fps_fps < 50.0 )
722 jump = YES;*/ /*FIXME: Implement this tweak right.*/
725 /* Time stops in pause mode */
726 if(game_pause || show_menu )
731 /* Set the time the last update and the time of the current update */
732 last_update_time = update_time;
733 update_time = st_get_ticks();
736 /* Pause till next frame, if the machine running the game is too fast: */
737 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
738 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
739 if(last_update_time >= update_time - 12 && jump != YES )
741 /*if((update_time - last_update_time) < 10)
742 SDL_Delay((11 - (update_time - last_update_time))/2);*/
748 if (timer_check(&time_left))
750 /* are we low on time ? */
751 if ((timer_get_left(&time_left) < TIME_WARNING)
752 && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */
754 set_current_music(HURRYUP_MUSIC);
755 play_current_music();
760 player_kill(&tux,KILL);
763 /* Calculate frames per second */
767 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
769 if(!timer_check(&fps_timer))
771 timer_start(&fps_timer,1000);
777 while (!done && !quit);
782 level_free(¤t_level);
793 /* Load graphics/sounds shared between all levels: */
795 void loadshared(void)
798 char * herring_song_path; /* for loading herring song*/
802 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
803 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
804 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
806 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
807 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
808 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
810 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
811 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
812 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
814 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
815 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
816 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
819 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
822 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
825 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
828 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
831 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
834 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
837 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
840 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
842 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
845 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
848 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
851 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
853 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
856 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
859 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
862 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
865 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
868 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
871 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
874 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
876 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
879 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
882 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
885 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
887 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
890 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
893 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
896 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
900 texture_load(&ducktux_right ,DATA_PREFIX
901 "/images/shared/ducktux-right.png",
904 texture_load(&ducktux_left ,DATA_PREFIX
905 "/images/shared/ducktux-left.png",
908 texture_load(&skidtux_right ,DATA_PREFIX
909 "/images/shared/skidtux-right.png",
912 texture_load(&skidtux_left ,DATA_PREFIX
913 "/images/shared/skidtux-left.png",
916 texture_load(&duckfiretux_right ,DATA_PREFIX
917 "/images/shared/duckfiretux-right.png",
920 texture_load(&duckfiretux_left ,DATA_PREFIX
921 "/images/shared/duckfiretux-left.png",
924 texture_load(&skidfiretux_right ,DATA_PREFIX
925 "/images/shared/skidfiretux-right.png",
928 texture_load(&skidfiretux_left ,DATA_PREFIX
929 "/images/shared/skidfiretux-left.png",
935 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
937 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
944 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
946 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
949 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
952 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
958 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
959 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
965 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
967 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
973 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
976 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
979 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
982 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
986 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
989 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
992 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
995 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
1003 texture_load(&img_bsod_left[0] ,DATA_PREFIX
1004 "/images/shared/bsod-left-0.png",
1007 texture_load(&img_bsod_left[1] ,DATA_PREFIX
1008 "/images/shared/bsod-left-1.png",
1011 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1012 "/images/shared/bsod-left-2.png",
1015 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1016 "/images/shared/bsod-left-3.png",
1019 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1020 "/images/shared/bsod-right-0.png",
1023 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1024 "/images/shared/bsod-right-1.png",
1027 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1028 "/images/shared/bsod-right-2.png",
1031 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1032 "/images/shared/bsod-right-3.png",
1035 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1036 "/images/shared/bsod-squished-left.png",
1039 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1040 "/images/shared/bsod-squished-right.png",
1043 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1044 "/images/shared/bsod-falling-left.png",
1047 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1048 "/images/shared/bsod-falling-right.png",
1054 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1055 "/images/shared/laptop-left-0.png",
1058 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1059 "/images/shared/laptop-left-1.png",
1062 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1063 "/images/shared/laptop-left-2.png",
1066 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1067 "/images/shared/laptop-right-0.png",
1070 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1071 "/images/shared/laptop-right-1.png",
1074 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1075 "/images/shared/laptop-right-2.png",
1078 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1079 "/images/shared/laptop-flat-left.png",
1082 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1083 "/images/shared/laptop-flat-right.png",
1086 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1087 "/images/shared/laptop-falling-left.png",
1090 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1091 "/images/shared/laptop-falling-right.png",
1097 texture_load(&img_money_left[0] ,DATA_PREFIX
1098 "/images/shared/bag-left-0.png",
1101 texture_load(&img_money_left[1] ,DATA_PREFIX
1102 "/images/shared/bag-left-1.png",
1105 texture_load(&img_money_right[0] ,DATA_PREFIX
1106 "/images/shared/bag-right-0.png",
1109 texture_load(&img_money_right[1] ,DATA_PREFIX
1110 "/images/shared/bag-right-1.png",
1117 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1118 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1123 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1125 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1132 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1135 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1138 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1141 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1147 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1152 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1156 /* Super background: */
1158 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1162 /* Sound effects: */
1164 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1165 // initialize sounds[i] with the correct pointer's value:
1166 // NULL or something else. And it will be dangerous to
1167 // play with not-initialized pointers.
1168 // This is also true with if (use_music)
1169 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1171 for (i = 0; i < NUM_SOUNDS; i++)
1172 sounds[i] = load_sound(soundfilenames[i]);
1175 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1176 strlen("SALCON.MOD") + 8));
1178 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1180 herring_song = load_song(herring_song_path);
1182 free(herring_song_path);
1187 /* Free shared data: */
1189 void unloadshared(void)
1193 for (i = 0; i < 3; i++)
1195 texture_free(&tux_right[i]);
1196 texture_free(&tux_left[i]);
1197 texture_free(&bigtux_right[i]);
1198 texture_free(&bigtux_left[i]);
1201 texture_free(&bigtux_right_jump);
1202 texture_free(&bigtux_left_jump);
1204 for (i = 0; i < 2; i++)
1206 texture_free(&cape_right[i]);
1207 texture_free(&cape_left[i]);
1208 texture_free(&bigcape_right[i]);
1209 texture_free(&bigcape_left[i]);
1212 texture_free(&ducktux_left);
1213 texture_free(&ducktux_right);
1215 texture_free(&skidtux_left);
1216 texture_free(&skidtux_right);
1218 for (i = 0; i < 4; i++)
1220 texture_free(&img_bsod_left[i]);
1221 texture_free(&img_bsod_right[i]);
1224 texture_free(&img_bsod_squished_left);
1225 texture_free(&img_bsod_squished_right);
1227 texture_free(&img_bsod_falling_left);
1228 texture_free(&img_bsod_falling_right);
1230 for (i = 0; i < 3; i++)
1232 texture_free(&img_laptop_left[i]);
1233 texture_free(&img_laptop_right[i]);
1236 texture_free(&img_laptop_flat_left);
1237 texture_free(&img_laptop_flat_right);
1239 texture_free(&img_laptop_falling_left);
1240 texture_free(&img_laptop_falling_right);
1242 for (i = 0; i < 2; i++)
1244 texture_free(&img_money_left[i]);
1245 texture_free(&img_money_right[i]);
1248 texture_free(&img_box_full);
1249 texture_free(&img_box_empty);
1251 texture_free(&img_water);
1252 for (i = 0; i < 3; i++)
1253 texture_free(&img_waves[i]);
1255 texture_free(&img_pole);
1256 texture_free(&img_poletop);
1258 for (i = 0; i < 2; i++)
1259 texture_free(&img_flag[i]);
1261 texture_free(&img_mints);
1262 texture_free(&img_coffee);
1264 for (i = 0; i < 4; i++)
1266 texture_free(&img_distro[i]);
1267 texture_free(&img_cloud[0][i]);
1268 texture_free(&img_cloud[1][i]);
1271 texture_free(&img_golden_herring);
1273 for (i = 0; i < NUM_SOUNDS; i++)
1274 free_chunk(sounds[i]);
1276 /* free the herring song */
1277 free_music( herring_song );
1281 /* Draw a tile on the screen: */
1283 void drawshape(float x, float y, unsigned char c)
1287 if (c == 'X' || c == 'x')
1288 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1289 else if (c == 'Y' || c == 'y')
1290 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1291 else if (c == 'A' || c =='B' || c == '!')
1292 texture_draw(&img_box_full, x, y, NO_UPDATE);
1294 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1295 else if (c >= 'C' && c <= 'F')
1296 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1297 else if (c >= 'c' && c <= 'f')
1298 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1299 else if (c >= 'G' && c <= 'J')
1300 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1301 else if (c >= 'g' && c <= 'j')
1302 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1304 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1306 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1308 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1310 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1314 z = (frame / 2) % 6;
1317 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1319 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1321 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1325 z = (frame / 3) % 3;
1327 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1330 texture_draw(&img_poletop, x, y, NO_UPDATE);
1333 texture_draw(&img_pole, x, y, NO_UPDATE);
1338 z = (frame / 3) % 2;
1340 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1343 texture_draw(&img_water, x, y, NO_UPDATE);
1347 /* What shape is at some position? */
1349 unsigned char shape(float x, float y)
1358 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1360 c = current_level.tiles[yy][xx];
1371 int issolid(float x, float y)
1373 if (isbrick(x, y) ||
1375 (shape(x, y) == '[') ||
1376 (shape(x, y) == '=') ||
1377 (shape(x, y) == ']') ||
1378 (shape(x, y) == 'A') ||
1379 (shape(x, y) == 'B') ||
1380 (shape(x, y) == '!') ||
1381 (shape(x, y) == 'a'))
1390 int issolid(float x, float y)
1392 if (isbrick(x, y) ||
1393 isbrick(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) == ']' ||
1401 shape(x + 31, y) == ']') ||
1402 (shape(x, y) == 'A' ||
1403 shape(x + 31, y) == 'A') ||
1404 (shape(x, y) == 'B' ||
1405 shape(x + 31, y) == 'B') ||
1406 (shape(x, y) == '!' ||
1407 shape(x + 31, y) == '!') ||
1408 (shape(x, y) == 'a' ||
1409 shape(x + 31, y) == 'a'))
1418 /* Is it a brick? */
1420 int isbrick(float x, float y)
1422 if (shape(x, y) == 'X' ||
1423 shape(x, y) == 'x' ||
1424 shape(x, y) == 'Y' ||
1436 int isice(float x, float y)
1438 if (shape(x, y) == '#')
1447 /* Is it a full box? */
1449 int isfullbox(float x, float y)
1451 if (shape(x, y) == 'A' ||
1452 shape(x, y) == 'B' ||
1461 /* Break a brick: */
1463 void trybreakbrick(float x, float y)
1467 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1469 /* Get a distro from it: */
1471 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1472 (int)(y / 32) * 32);
1474 if (counting_distros == NO)
1476 counting_distros = YES;
1477 distro_counter = 50;
1480 if (distro_counter <= 0)
1481 level_change(¤t_level,x, y, 'a');
1483 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1484 score = score + SCORE_DISTRO;
1489 /* Get rid of it: */
1491 level_change(¤t_level,x, y,'.');
1495 /* Replace it with broken bits: */
1497 add_broken_brick(((int)(x + 1) / 32) * 32,
1498 (int)(y / 32) * 32);
1501 /* Get some score: */
1503 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1504 score = score + SCORE_BRICK;
1509 /* Bounce a brick: */
1511 void bumpbrick(float x, float y)
1513 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1514 (int)(y / 32) * 32);
1516 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1523 void tryemptybox(float x, float y, int col_side)
1525 if (!isfullbox(x, y))
1528 // according to the collision side, set the upgrade direction
1530 if(col_side == LEFT)
1537 case 'A': /* Box with a distro! */
1538 add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1539 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1540 score = score + SCORE_DISTRO;
1543 case 'B': /* Add an upgrade! */
1544 if (tux.size == SMALL) /* Tux is small, add mints! */
1545 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1546 else /* Tux is big, add coffee: */
1547 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1548 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1550 case '!': /* Add a golden herring */
1551 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1557 /* Empty the box: */
1558 level_change(¤t_level,x, y, 'a');
1562 /* Try to grab a distro: */
1564 void trygrabdistro(float x, float y, int bounciness)
1566 if (shape(x, y) == '$')
1568 level_change(¤t_level,x, y, '.');
1569 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1571 if (bounciness == BOUNCE)
1573 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1574 (int)(y / 32) * 32);
1577 score = score + SCORE_DISTRO;
1582 /* Try to bump a bad guy from below: */
1584 void trybumpbadguy(float x, float y)
1591 for (i = 0; i < num_bad_guys; i++)
1593 if (bad_guys[i].base.alive &&
1594 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1595 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1597 if (bad_guys[i].kind == BAD_BSOD ||
1598 bad_guys[i].kind == BAD_LAPTOP)
1600 bad_guys[i].dying = FALLING;
1601 bad_guys[i].base.ym = -8;
1602 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1610 for (i = 0; i < num_upgrades; i++)
1612 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1613 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1614 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1616 upgrades[i].base.xm = -upgrades[i].base.xm;
1617 upgrades[i].base.ym = -8;
1618 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1624 void drawstatus(void)
1628 sprintf(str, "%d", score);
1629 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1630 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1632 if(st_gl_mode != ST_GL_TEST)
1634 sprintf(str, "%d", hs_score);
1635 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1636 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1640 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1643 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1645 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1646 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1647 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1650 sprintf(str, "%d", distros);
1651 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1652 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1654 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1658 sprintf(str, "%2.1f", fps_fps);
1659 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1660 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1663 for(i=0; i < tux.lives; ++i)
1665 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1670 void drawendscreen(void)
1674 clearscreen(0, 0, 0);
1676 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1678 sprintf(str, "SCORE: %d", score);
1679 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1681 sprintf(str, "DISTROS: %d", distros);
1682 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1688 void drawresultscreen(void)
1692 clearscreen(0, 0, 0);
1694 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1696 sprintf(str, "SCORE: %d", score);
1697 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1699 sprintf(str, "DISTROS: %d", distros);
1700 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1706 void savegame(int slot)
1708 char savefile[1024];
1712 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1714 fi = fopen(savefile, "wb");
1718 fprintf(stderr, "Warning: I could not open the slot file ");
1723 fputs(level_subset, fi);
1725 fwrite(&level,sizeof(int),1,fi);
1726 fwrite(&score,sizeof(int),1,fi);
1727 fwrite(&distros,sizeof(int),1,fi);
1728 fwrite(&scroll_x,sizeof(float),1,fi);
1729 fwrite(&tux,sizeof(player_type),1,fi);
1730 timer_fwrite(&tux.invincible_timer,fi);
1731 timer_fwrite(&tux.skidding_timer,fi);
1732 timer_fwrite(&tux.safe_timer,fi);
1733 timer_fwrite(&tux.frame_timer,fi);
1734 timer_fwrite(&time_left,fi);
1735 ui = st_get_ticks();
1736 fwrite(&ui,sizeof(int),1,fi);
1742 void loadgame(int slot)
1744 char savefile[1024];
1749 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1751 fi = fopen(savefile, "rb");
1755 fprintf(stderr, "Warning: I could not open the slot file ");
1762 fgets(str, 100, fi);
1763 strcpy(level_subset, str);
1764 level_subset[strlen(level_subset)-1] = '\0';
1765 fread(&level,sizeof(int),1,fi);
1768 level_free(¤t_level);
1769 if(level_load(¤t_level,level_subset,level) != 0)
1773 activate_bad_guys();
1775 level_load_gfx(¤t_level);
1777 level_load_song(¤t_level);
1779 update_time = st_get_ticks();
1781 fread(&score,sizeof(int),1,fi);
1782 fread(&distros,sizeof(int),1,fi);
1783 fread(&scroll_x,sizeof(float),1,fi);
1784 fread(&tux,sizeof(player_type),1,fi);
1785 timer_fread(&tux.invincible_timer,fi);
1786 timer_fread(&tux.skidding_timer,fi);
1787 timer_fread(&tux.safe_timer,fi);
1788 timer_fread(&tux.frame_timer,fi);
1789 timer_fread(&time_left,fi);
1790 fread(&ui,sizeof(int),1,fi);
1791 tux.hphysic.start_time += st_get_ticks() - ui;
1792 tux.vphysic.start_time += st_get_ticks() - ui;
1798 void slotinfo(char **pinfo, int slot)
1801 char slotfile[1024];
1805 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1807 fi = fopen(slotfile, "rb");
1809 sprintf(tmp,"Slot %d - ",slot);
1817 fgets(str, 100, fi);
1818 str[strlen(str)-1] = '\0';
1820 strcat(tmp, " / Level:");
1821 fread(&slot_level,sizeof(int),1,fi);
1822 sprintf(str,"%d",slot_level);
1827 *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));