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);
650 tux.input.old_fire = tux.input.fire;
656 if(current_menu == &game_menu)
658 switch (menu_check(&game_menu))
661 st_pause_ticks_stop();
664 update_load_save_game_menu(&save_game_menu, NO);
667 update_load_save_game_menu(&load_game_menu, YES);
670 st_pause_ticks_stop();
675 else if(current_menu == &options_menu)
677 process_options_menu();
679 else if(current_menu == &save_game_menu )
681 process_save_load_game_menu(YES);
683 else if(current_menu == &load_game_menu )
685 process_save_load_game_menu(NO);
690 /* Handle actions: */
692 if(!game_pause && !show_menu)
694 /*float z = frame_ratio;
698 if (game_action() == 0)
700 /* == 0: no more lives */
701 /* == -1: continues */
713 if(debug_mode && debug_fps == YES)
716 /*Draw the current scene to the screen */
717 /*If the machine running the game is too slow
718 skip the drawing of the frame (so the calculations are more precise and
719 the FPS aren't affected).*/
720 /*if( ! fps_fps < 50.0 )
723 jump = YES;*/ /*FIXME: Implement this tweak right.*/
726 /* Time stops in pause mode */
727 if(game_pause || show_menu )
732 /* Set the time the last update and the time of the current update */
733 last_update_time = update_time;
734 update_time = st_get_ticks();
737 /* Pause till next frame, if the machine running the game is too fast: */
738 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
739 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
740 if(last_update_time >= update_time - 12 && jump != YES )
742 /*if((update_time - last_update_time) < 10)
743 SDL_Delay((11 - (update_time - last_update_time))/2);*/
749 if (timer_check(&time_left))
751 /* are we low on time ? */
752 if ((timer_get_left(&time_left) < TIME_WARNING)
753 && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */
755 set_current_music(HURRYUP_MUSIC);
756 play_current_music();
761 player_kill(&tux,KILL);
764 /* Calculate frames per second */
768 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
770 if(!timer_check(&fps_timer))
772 timer_start(&fps_timer,1000);
778 while (!done && !quit);
783 level_free(¤t_level);
794 /* Load graphics/sounds shared between all levels: */
796 void loadshared(void)
799 char * herring_song_path; /* for loading herring song*/
803 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
804 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
805 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
807 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
808 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
809 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
811 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
812 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
813 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
815 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
816 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
817 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
820 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
823 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
826 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
829 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
832 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
835 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
838 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
841 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
843 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
846 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
849 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
852 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
854 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
857 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
860 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
863 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
866 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
869 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
872 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
875 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
877 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
880 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
883 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
886 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
888 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
891 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
894 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
897 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
901 texture_load(&ducktux_right ,DATA_PREFIX
902 "/images/shared/ducktux-right.png",
905 texture_load(&ducktux_left ,DATA_PREFIX
906 "/images/shared/ducktux-left.png",
909 texture_load(&skidtux_right ,DATA_PREFIX
910 "/images/shared/skidtux-right.png",
913 texture_load(&skidtux_left ,DATA_PREFIX
914 "/images/shared/skidtux-left.png",
917 texture_load(&duckfiretux_right ,DATA_PREFIX
918 "/images/shared/duckfiretux-right.png",
921 texture_load(&duckfiretux_left ,DATA_PREFIX
922 "/images/shared/duckfiretux-left.png",
925 texture_load(&skidfiretux_right ,DATA_PREFIX
926 "/images/shared/skidfiretux-right.png",
929 texture_load(&skidfiretux_left ,DATA_PREFIX
930 "/images/shared/skidfiretux-left.png",
936 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
938 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
945 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
947 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
950 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
953 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
959 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
960 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
966 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
968 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
974 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
977 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
980 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
983 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
987 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
990 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
993 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
996 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
1004 texture_load(&img_bsod_left[0] ,DATA_PREFIX
1005 "/images/shared/bsod-left-0.png",
1008 texture_load(&img_bsod_left[1] ,DATA_PREFIX
1009 "/images/shared/bsod-left-1.png",
1012 texture_load(&img_bsod_left[2] ,DATA_PREFIX
1013 "/images/shared/bsod-left-2.png",
1016 texture_load(&img_bsod_left[3] ,DATA_PREFIX
1017 "/images/shared/bsod-left-3.png",
1020 texture_load(&img_bsod_right[0] ,DATA_PREFIX
1021 "/images/shared/bsod-right-0.png",
1024 texture_load(&img_bsod_right[1] ,DATA_PREFIX
1025 "/images/shared/bsod-right-1.png",
1028 texture_load(&img_bsod_right[2] ,DATA_PREFIX
1029 "/images/shared/bsod-right-2.png",
1032 texture_load(&img_bsod_right[3] ,DATA_PREFIX
1033 "/images/shared/bsod-right-3.png",
1036 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1037 "/images/shared/bsod-squished-left.png",
1040 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1041 "/images/shared/bsod-squished-right.png",
1044 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1045 "/images/shared/bsod-falling-left.png",
1048 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1049 "/images/shared/bsod-falling-right.png",
1055 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1056 "/images/shared/laptop-left-0.png",
1059 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1060 "/images/shared/laptop-left-1.png",
1063 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1064 "/images/shared/laptop-left-2.png",
1067 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1068 "/images/shared/laptop-right-0.png",
1071 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1072 "/images/shared/laptop-right-1.png",
1075 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1076 "/images/shared/laptop-right-2.png",
1079 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1080 "/images/shared/laptop-flat-left.png",
1083 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1084 "/images/shared/laptop-flat-right.png",
1087 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1088 "/images/shared/laptop-falling-left.png",
1091 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1092 "/images/shared/laptop-falling-right.png",
1098 texture_load(&img_money_left[0] ,DATA_PREFIX
1099 "/images/shared/bag-left-0.png",
1102 texture_load(&img_money_left[1] ,DATA_PREFIX
1103 "/images/shared/bag-left-1.png",
1106 texture_load(&img_money_right[0] ,DATA_PREFIX
1107 "/images/shared/bag-right-0.png",
1110 texture_load(&img_money_right[1] ,DATA_PREFIX
1111 "/images/shared/bag-right-1.png",
1118 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1119 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1124 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1126 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1133 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1136 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1139 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1142 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1148 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1153 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1157 /* Super background: */
1159 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1163 /* Sound effects: */
1165 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1166 // initialize sounds[i] with the correct pointer's value:
1167 // NULL or something else. And it will be dangerous to
1168 // play with not-initialized pointers.
1169 // This is also true with if (use_music)
1170 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1172 for (i = 0; i < NUM_SOUNDS; i++)
1173 sounds[i] = load_sound(soundfilenames[i]);
1176 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1177 strlen("SALCON.MOD") + 8));
1179 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1181 herring_song = load_song(herring_song_path);
1183 free(herring_song_path);
1188 /* Free shared data: */
1190 void unloadshared(void)
1194 for (i = 0; i < 3; i++)
1196 texture_free(&tux_right[i]);
1197 texture_free(&tux_left[i]);
1198 texture_free(&bigtux_right[i]);
1199 texture_free(&bigtux_left[i]);
1202 texture_free(&bigtux_right_jump);
1203 texture_free(&bigtux_left_jump);
1205 for (i = 0; i < 2; i++)
1207 texture_free(&cape_right[i]);
1208 texture_free(&cape_left[i]);
1209 texture_free(&bigcape_right[i]);
1210 texture_free(&bigcape_left[i]);
1213 texture_free(&ducktux_left);
1214 texture_free(&ducktux_right);
1216 texture_free(&skidtux_left);
1217 texture_free(&skidtux_right);
1219 for (i = 0; i < 4; i++)
1221 texture_free(&img_bsod_left[i]);
1222 texture_free(&img_bsod_right[i]);
1225 texture_free(&img_bsod_squished_left);
1226 texture_free(&img_bsod_squished_right);
1228 texture_free(&img_bsod_falling_left);
1229 texture_free(&img_bsod_falling_right);
1231 for (i = 0; i < 3; i++)
1233 texture_free(&img_laptop_left[i]);
1234 texture_free(&img_laptop_right[i]);
1237 texture_free(&img_laptop_flat_left);
1238 texture_free(&img_laptop_flat_right);
1240 texture_free(&img_laptop_falling_left);
1241 texture_free(&img_laptop_falling_right);
1243 for (i = 0; i < 2; i++)
1245 texture_free(&img_money_left[i]);
1246 texture_free(&img_money_right[i]);
1249 texture_free(&img_box_full);
1250 texture_free(&img_box_empty);
1252 texture_free(&img_water);
1253 for (i = 0; i < 3; i++)
1254 texture_free(&img_waves[i]);
1256 texture_free(&img_pole);
1257 texture_free(&img_poletop);
1259 for (i = 0; i < 2; i++)
1260 texture_free(&img_flag[i]);
1262 texture_free(&img_mints);
1263 texture_free(&img_coffee);
1265 for (i = 0; i < 4; i++)
1267 texture_free(&img_distro[i]);
1268 texture_free(&img_cloud[0][i]);
1269 texture_free(&img_cloud[1][i]);
1272 texture_free(&img_golden_herring);
1274 for (i = 0; i < NUM_SOUNDS; i++)
1275 free_chunk(sounds[i]);
1277 /* free the herring song */
1278 free_music( herring_song );
1282 /* Draw a tile on the screen: */
1284 void drawshape(float x, float y, unsigned char c)
1288 if (c == 'X' || c == 'x')
1289 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1290 else if (c == 'Y' || c == 'y')
1291 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1292 else if (c == 'A' || c =='B' || c == '!')
1293 texture_draw(&img_box_full, x, y, NO_UPDATE);
1295 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1296 else if (c >= 'C' && c <= 'F')
1297 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1298 else if (c >= 'c' && c <= 'f')
1299 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1300 else if (c >= 'G' && c <= 'J')
1301 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1302 else if (c >= 'g' && c <= 'j')
1303 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1305 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1307 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1309 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1311 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1315 z = (frame / 2) % 6;
1318 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1320 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1322 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1326 z = (frame / 3) % 3;
1328 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1331 texture_draw(&img_poletop, x, y, NO_UPDATE);
1334 texture_draw(&img_pole, x, y, NO_UPDATE);
1336 /* Mark this as the end position of the level! */
1342 z = (frame / 3) % 2;
1344 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1347 texture_draw(&img_water, x, y, NO_UPDATE);
1351 /* What shape is at some position? */
1353 unsigned char shape(float x, float y)
1362 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1364 c = current_level.tiles[yy][xx];
1375 int issolid(float x, float y)
1377 if (isbrick(x, y) ||
1379 (shape(x, y) == '[') ||
1380 (shape(x, y) == '=') ||
1381 (shape(x, y) == ']') ||
1382 (shape(x, y) == 'A') ||
1383 (shape(x, y) == 'B') ||
1384 (shape(x, y) == '!') ||
1385 (shape(x, y) == 'a'))
1394 int issolid(float x, float y)
1396 if (isbrick(x, y) ||
1397 isbrick(x + 31, y) ||
1400 (shape(x, y) == '[' ||
1401 shape(x + 31, y) == '[') ||
1402 (shape(x, y) == '=' ||
1403 shape(x + 31, y) == '=') ||
1404 (shape(x, y) == ']' ||
1405 shape(x + 31, y) == ']') ||
1406 (shape(x, y) == 'A' ||
1407 shape(x + 31, y) == 'A') ||
1408 (shape(x, y) == 'B' ||
1409 shape(x + 31, y) == 'B') ||
1410 (shape(x, y) == '!' ||
1411 shape(x + 31, y) == '!') ||
1412 (shape(x, y) == 'a' ||
1413 shape(x + 31, y) == 'a'))
1422 /* Is it a brick? */
1424 int isbrick(float x, float y)
1426 if (shape(x, y) == 'X' ||
1427 shape(x, y) == 'x' ||
1428 shape(x, y) == 'Y' ||
1440 int isice(float x, float y)
1442 if (shape(x, y) == '#')
1451 /* Is it a full box? */
1453 int isfullbox(float x, float y)
1455 if (shape(x, y) == 'A' ||
1456 shape(x, y) == 'B' ||
1465 /* Break a brick: */
1467 void trybreakbrick(float x, float y)
1471 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1473 /* Get a distro from it: */
1475 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1476 (int)(y / 32) * 32);
1478 if (counting_distros == NO)
1480 counting_distros = YES;
1481 distro_counter = 50;
1484 if (distro_counter <= 0)
1485 level_change(¤t_level,x, y, 'a');
1487 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1488 score = score + SCORE_DISTRO;
1493 /* Get rid of it: */
1495 level_change(¤t_level,x, y,'.');
1499 /* Replace it with broken bits: */
1501 add_broken_brick(((int)(x + 1) / 32) * 32,
1502 (int)(y / 32) * 32);
1505 /* Get some score: */
1507 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1508 score = score + SCORE_BRICK;
1513 /* Bounce a brick: */
1515 void bumpbrick(float x, float y)
1517 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1518 (int)(y / 32) * 32);
1520 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1527 void tryemptybox(float x, float y, int col_side)
1529 if (!isfullbox(x, y))
1532 // according to the collision side, set the upgrade direction
1534 if(col_side == LEFT)
1541 case 'A': /* Box with a distro! */
1542 add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1543 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1544 score = score + SCORE_DISTRO;
1547 case 'B': /* Add an upgrade! */
1548 if (tux.size == SMALL) /* Tux is small, add mints! */
1549 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1550 else /* Tux is big, add coffee: */
1551 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1552 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1554 case '!': /* Add a golden herring */
1555 add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1561 /* Empty the box: */
1562 level_change(¤t_level,x, y, 'a');
1566 /* Try to grab a distro: */
1568 void trygrabdistro(float x, float y, int bounciness)
1570 if (shape(x, y) == '$')
1572 level_change(¤t_level,x, y, '.');
1573 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1575 if (bounciness == BOUNCE)
1577 add_bouncy_distro(((int)(x + 1) / 32) * 32,
1578 (int)(y / 32) * 32);
1581 score = score + SCORE_DISTRO;
1586 /* Try to bump a bad guy from below: */
1588 void trybumpbadguy(float x, float y)
1595 for (i = 0; i < num_bad_guys; i++)
1597 if (bad_guys[i].base.alive &&
1598 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1599 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1601 if (bad_guys[i].kind == BAD_BSOD ||
1602 bad_guys[i].kind == BAD_LAPTOP)
1604 bad_guys[i].dying = FALLING;
1605 bad_guys[i].base.ym = -8;
1606 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1614 for (i = 0; i < num_upgrades; i++)
1616 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1617 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1618 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1620 upgrades[i].base.xm = -upgrades[i].base.xm;
1621 upgrades[i].base.ym = -8;
1622 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1628 void drawstatus(void)
1632 sprintf(str, "%d", score);
1633 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1634 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1636 if(st_gl_mode != ST_GL_TEST)
1638 sprintf(str, "%d", hs_score);
1639 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1640 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1644 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1647 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1649 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1650 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1651 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1654 sprintf(str, "%d", distros);
1655 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1656 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1658 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1662 sprintf(str, "%2.1f", fps_fps);
1663 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1664 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1667 for(i=0; i < tux.lives; ++i)
1669 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1674 void drawendscreen(void)
1678 clearscreen(0, 0, 0);
1680 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1682 sprintf(str, "SCORE: %d", score);
1683 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1685 sprintf(str, "DISTROS: %d", distros);
1686 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1692 void drawresultscreen(void)
1696 clearscreen(0, 0, 0);
1698 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1700 sprintf(str, "SCORE: %d", score);
1701 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1703 sprintf(str, "DISTROS: %d", distros);
1704 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1710 void savegame(int slot)
1712 char savefile[1024];
1716 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1718 fi = fopen(savefile, "wb");
1722 fprintf(stderr, "Warning: I could not open the slot file ");
1727 fputs(level_subset, fi);
1729 fwrite(&level,sizeof(int),1,fi);
1730 fwrite(&score,sizeof(int),1,fi);
1731 fwrite(&distros,sizeof(int),1,fi);
1732 fwrite(&scroll_x,sizeof(float),1,fi);
1733 fwrite(&tux,sizeof(player_type),1,fi);
1734 timer_fwrite(&tux.invincible_timer,fi);
1735 timer_fwrite(&tux.skidding_timer,fi);
1736 timer_fwrite(&tux.safe_timer,fi);
1737 timer_fwrite(&tux.frame_timer,fi);
1738 timer_fwrite(&time_left,fi);
1739 ui = st_get_ticks();
1740 fwrite(&ui,sizeof(int),1,fi);
1746 void loadgame(int slot)
1748 char savefile[1024];
1753 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1755 fi = fopen(savefile, "rb");
1759 fprintf(stderr, "Warning: I could not open the slot file ");
1766 fgets(str, 100, fi);
1767 strcpy(level_subset, str);
1768 level_subset[strlen(level_subset)-1] = '\0';
1769 fread(&level,sizeof(int),1,fi);
1772 level_free(¤t_level);
1773 if(level_load(¤t_level,level_subset,level) != 0)
1777 activate_bad_guys();
1779 level_load_gfx(¤t_level);
1781 level_load_song(¤t_level);
1783 update_time = st_get_ticks();
1785 fread(&score,sizeof(int),1,fi);
1786 fread(&distros,sizeof(int),1,fi);
1787 fread(&scroll_x,sizeof(float),1,fi);
1788 fread(&tux,sizeof(player_type),1,fi);
1789 timer_fread(&tux.invincible_timer,fi);
1790 timer_fread(&tux.skidding_timer,fi);
1791 timer_fread(&tux.safe_timer,fi);
1792 timer_fread(&tux.frame_timer,fi);
1793 timer_fread(&time_left,fi);
1794 fread(&ui,sizeof(int),1,fi);
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));