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 extern char* soundfilenames[NUM_SOUNDS];
45 st_level current_level;
47 /* Local variables: */
49 texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2];
50 texture_type img_cloud[2][4];
53 char level_subset[100];
57 unsigned int last_update_time;
58 unsigned int update_time;
61 /* Local function prototypes: */
63 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_keydown_event(&tux,key))
142 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
145 if(st_gl_mode == ST_GL_TEST)
150 st_pause_ticks_stop();
155 st_pause_ticks_start();
163 case SDL_KEYUP: /* A keyrelease! */
164 key = event.key.keysym.sym;
166 if(player_keyup_event(&tux,key))
177 st_pause_ticks_stop();
182 st_pause_ticks_start();
187 if(debug_mode == YES)
188 tux.size = !tux.size;
191 if(debug_mode == YES)
195 if(debug_mode == YES)
199 if(debug_mode == YES)
203 if(debug_mode == YES)
204 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
207 if(debug_mode == YES)
211 if(debug_mode == YES)
220 case SDL_JOYAXISMOTION:
221 switch(event.jaxis.axis)
224 if (event.jaxis.value < -1024)
225 tux.input.left = DOWN;
226 else if (event.jaxis.value > 1024)
229 if (event.jaxis.value > 1024)
230 tux.input.right = DOWN;
231 else if (event.jaxis.value < -1024)
232 tux.input.right = UP;
235 if (event.jaxis.value > 1024)
236 tux.input.down = DOWN;
237 else if (event.jaxis.value < -1024)
240 /* Handle joystick for the menu */
243 if(tux.input.down == DOWN)
244 menuaction = MN_DOWN;
253 case SDL_JOYBUTTONDOWN:
254 if (event.jbutton.button == JOY_A)
256 else if (event.jbutton.button == JOY_B)
257 tux.input.fire = DOWN;
259 case SDL_JOYBUTTONUP:
260 if (event.jbutton.button == JOY_A)
262 else if (event.jbutton.button == JOY_B)
278 /* --- GAME ACTION! --- */
280 int game_action(void)
284 /* (tux_dying || next_level) */
285 if (tux.dying || next_level)
287 /* Tux either died, or reached the end of a level! */
295 /* End of a level! */
298 if(st_gl_mode == ST_GL_PLAY)
300 player_level_begin(&tux);
306 /* No more lives!? */
310 if(st_gl_mode == ST_GL_PLAY)
313 if(st_gl_mode == ST_GL_PLAY)
315 if (score > hs_score)
319 level_free(¤t_level);
324 } /* if (lives < 0) */
327 /* Either way, (re-)load the (next) level... */
329 player_level_begin(&tux);
331 level_free(¤t_level);
332 if(level_load(¤t_level,level_subset,level) != 0)
338 level_load_gfx(¤t_level);
340 level_load_song(¤t_level);
341 if(st_gl_mode == ST_GL_PLAY)
348 /* Handle bouncy distros: */
350 for (i = 0; i < num_bouncy_distros; i++)
352 bouncy_distro_action(&bouncy_distros[i]);
356 /* Handle broken bricks: */
358 for (i = 0; i < num_broken_bricks; i++)
360 broken_brick_action(&broken_bricks[i]);
364 /* Handle distro counting: */
366 if (counting_distros == YES)
370 if (distro_counter <= 0)
371 counting_distros = -1;
375 /* Handle bouncy bricks: */
377 for (i = 0; i < num_bouncy_bricks; i++)
379 bouncy_brick_action(&bouncy_bricks[i]);
383 /* Handle floating scores: */
385 for (i = 0; i < num_floating_scores; i++)
387 floating_score_action(&floating_scores[i]);
391 /* Handle bullets: */
393 for (i = 0; i < num_bullets; ++i)
395 bullet_action(&bullets[i]);
398 /* Handle upgrades: */
400 for (i = 0; i < num_upgrades; i++)
402 upgrade_action(&upgrades[i]);
406 /* Handle bad guys: */
408 for (i = 0; i < num_bad_guys; i++)
410 badguy_action(&bad_guys[i]);
413 /* Handle all possible collisions. */
419 /* --- GAME DRAW! --- */
427 if (tux.dying && (frame % 4) == 0)
428 clearscreen(255, 255, 255);
429 else if(timer_check(&super_bkgd_timer))
430 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
433 /* Draw the real background */
434 if(current_level.bkgd_image[0] != '\0')
436 s = (int)scroll_x / 30;
437 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
438 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
442 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
446 /* Draw background: */
448 for (y = 0; y < 15; ++y)
450 for (x = 0; x < 21; ++x)
452 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
453 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
458 /* (Bouncy bricks): */
460 for (i = 0; i < num_bouncy_bricks; ++i)
462 bouncy_brick_draw(&bouncy_bricks[i]);
468 for (i = 0; i < num_bad_guys; ++i)
470 badguy_draw(&bad_guys[i]);
479 for (i = 0; i < num_bullets; ++i)
481 bullet_draw(&bullets[i]);
484 /* (Floating scores): */
486 for (i = 0; i < num_floating_scores; ++i)
488 floating_score_draw(&floating_scores[i]);
494 for (i = 0; i < num_upgrades; ++i)
496 upgrade_draw(&upgrades[i]);
500 /* (Bouncy distros): */
502 for (i = 0; i < num_bouncy_distros; ++i)
504 bouncy_distro_draw(&bouncy_distros[i]);
508 /* (Broken bricks): */
510 for (i = 0; i < num_broken_bricks; ++i)
512 broken_brick_draw(&broken_bricks[i]);
521 for(i = 0; i < x; ++i)
523 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);
525 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
526 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
530 menu_process_current();
532 /* (Update it all!) */
539 /* --- GAME LOOP! --- */
541 int gameloop(char * subset, int levelnb, int mode)
543 int fps_cnt, jump, done;
544 timer_type fps_timer, frame_timer;
548 strcpy(level_subset,subset);
552 clearscreen(0, 0, 0);
560 menu_set_current(&game_menu);
566 if(level_load(¤t_level,level_subset,level) != 0)
568 level_load_gfx(¤t_level);
570 level_load_song(¤t_level);
571 if(st_gl_mode == ST_GL_PLAY)
576 if(st_gl_mode == ST_GL_PLAY)
581 /* --- MAIN GAME LOOP!!! --- */
588 timer_init(&fps_timer);
589 timer_init(&frame_timer);
597 /* Calculate the movement-factor */
598 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
600 if(!timer_check(&frame_timer))
602 timer_start(&frame_timer,25);
609 tux.input.old_fire = tux.input.fire;
611 /*printf("%lf\n",frame_ratio);*/
617 if(current_menu == &game_menu)
619 switch (menu_check(&game_menu))
622 st_pause_ticks_stop();
635 else if(current_menu == &options_menu)
637 process_options_menu();
642 /* Handle actions: */
644 if(!game_pause && !show_menu)
646 if (game_action() == 0)
648 /* == 0: no more lives */
649 /* == -1: continues */
659 if(tux.input.down == DOWN)
662 /*Draw the current scene to the screen */
663 /*If the machine running the game is too slow
664 skip the drawing of the frame (so the calculations are more precise and
665 the FPS aren't affected).*/
666 /*if( ! fps_fps < 50.0 )
669 jump = YES;*/ /*FIXME: Implement this tweak right.*/
672 /* Time stops in pause mode */
673 if(game_pause || show_menu )
678 /* Set the time the last update and the time of the current update */
679 last_update_time = update_time;
680 update_time = st_get_ticks();
683 /* Pause till next frame, if the machine running the game is too fast: */
684 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
685 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
686 if(last_update_time >= update_time - 12 && jump != YES )
688 //if((update_time - last_update_time) < 10)
689 // SDL_Delay((11 - (update_time - last_update_time))/2);
695 if (timer_check(&time_left))
697 /* are we low on time ? */
698 if ((timer_get_left(&time_left) < TIME_WARNING)
699 && (current_music != HURRYUP_MUSIC))
701 current_music = HURRYUP_MUSIC;
702 /* stop the others music, prepare to play the fast music */
711 player_kill(&tux,KILL);
714 /* Keep playing the correct music: */
716 if (!playing_music())
718 play_current_music();
721 /* Calculate frames per second */
725 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
727 if(!timer_check(&fps_timer))
729 timer_start(&fps_timer,1000);
735 while (!done && !quit);
741 level_free(¤t_level);
750 /* Initialize the game stuff: */
758 /* Load graphics/sounds shared between all levels: */
760 void loadshared(void)
763 char * herring_song_path; /* for loading herring song*/
767 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
768 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
769 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
771 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
772 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
773 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
775 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
776 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
777 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
779 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
780 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
781 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
784 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
787 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
790 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
793 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
796 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
799 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
802 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
805 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
807 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
810 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
813 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
816 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
818 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
821 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
824 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
827 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
830 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
833 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
836 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
839 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
841 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
844 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
847 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
850 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
852 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
855 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
858 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
861 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
865 texture_load(&ducktux_right ,DATA_PREFIX
866 "/images/shared/ducktux-right.png",
869 texture_load(&ducktux_left ,DATA_PREFIX
870 "/images/shared/ducktux-left.png",
873 texture_load(&skidtux_right ,DATA_PREFIX
874 "/images/shared/skidtux-right.png",
877 texture_load(&skidtux_left ,DATA_PREFIX
878 "/images/shared/skidtux-left.png",
881 texture_load(&duckfiretux_right ,DATA_PREFIX
882 "/images/shared/duckfiretux-right.png",
885 texture_load(&duckfiretux_left ,DATA_PREFIX
886 "/images/shared/duckfiretux-left.png",
889 texture_load(&skidfiretux_right ,DATA_PREFIX
890 "/images/shared/skidfiretux-right.png",
893 texture_load(&skidfiretux_left ,DATA_PREFIX
894 "/images/shared/skidfiretux-left.png",
900 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
902 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
909 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
911 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
914 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
917 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
923 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
924 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
930 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
932 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
938 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
941 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
944 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
947 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
951 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
954 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
957 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
960 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
968 texture_load(&img_bsod_left[0] ,DATA_PREFIX
969 "/images/shared/bsod-left-0.png",
972 texture_load(&img_bsod_left[1] ,DATA_PREFIX
973 "/images/shared/bsod-left-1.png",
976 texture_load(&img_bsod_left[2] ,DATA_PREFIX
977 "/images/shared/bsod-left-2.png",
980 texture_load(&img_bsod_left[3] ,DATA_PREFIX
981 "/images/shared/bsod-left-3.png",
984 texture_load(&img_bsod_right[0] ,DATA_PREFIX
985 "/images/shared/bsod-right-0.png",
988 texture_load(&img_bsod_right[1] ,DATA_PREFIX
989 "/images/shared/bsod-right-1.png",
992 texture_load(&img_bsod_right[2] ,DATA_PREFIX
993 "/images/shared/bsod-right-2.png",
996 texture_load(&img_bsod_right[3] ,DATA_PREFIX
997 "/images/shared/bsod-right-3.png",
1000 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1001 "/images/shared/bsod-squished-left.png",
1004 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1005 "/images/shared/bsod-squished-right.png",
1008 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1009 "/images/shared/bsod-falling-left.png",
1012 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1013 "/images/shared/bsod-falling-right.png",
1019 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1020 "/images/shared/laptop-left-0.png",
1023 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1024 "/images/shared/laptop-left-1.png",
1027 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1028 "/images/shared/laptop-left-2.png",
1031 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1032 "/images/shared/laptop-right-0.png",
1035 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1036 "/images/shared/laptop-right-1.png",
1039 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1040 "/images/shared/laptop-right-2.png",
1043 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1044 "/images/shared/laptop-flat-left.png",
1047 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1048 "/images/shared/laptop-flat-right.png",
1051 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1052 "/images/shared/laptop-falling-left.png",
1055 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1056 "/images/shared/laptop-falling-right.png",
1062 texture_load(&img_money_left[0] ,DATA_PREFIX
1063 "/images/shared/bag-left-0.png",
1066 texture_load(&img_money_left[1] ,DATA_PREFIX
1067 "/images/shared/bag-left-1.png",
1070 texture_load(&img_money_right[0] ,DATA_PREFIX
1071 "/images/shared/bag-right-0.png",
1074 texture_load(&img_money_right[1] ,DATA_PREFIX
1075 "/images/shared/bag-right-1.png",
1082 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1083 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1088 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1090 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1097 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1100 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1103 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1106 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1112 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1117 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1121 /* Super background: */
1123 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1127 /* Sound effects: */
1129 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1130 // initialize sounds[i] with the correct pointer's value:
1131 // NULL or something else. And it will be dangerous to
1132 // play with not-initialized pointers.
1133 // This is also true with if (use_music)
1134 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1136 for (i = 0; i < NUM_SOUNDS; i++)
1137 sounds[i] = load_sound(soundfilenames[i]);
1140 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1141 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
1143 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1145 herring_song = load_song(herring_song_path);
1147 free(herring_song_path);
1152 /* Free shared data: */
1154 void unloadshared(void)
1158 for (i = 0; i < 3; i++)
1160 texture_free(&tux_right[i]);
1161 texture_free(&tux_left[i]);
1162 texture_free(&bigtux_right[i]);
1163 texture_free(&bigtux_left[i]);
1166 texture_free(&bigtux_right_jump);
1167 texture_free(&bigtux_left_jump);
1169 for (i = 0; i < 2; i++)
1171 texture_free(&cape_right[i]);
1172 texture_free(&cape_left[i]);
1173 texture_free(&bigcape_right[i]);
1174 texture_free(&bigcape_left[i]);
1177 texture_free(&ducktux_left);
1178 texture_free(&ducktux_right);
1180 texture_free(&skidtux_left);
1181 texture_free(&skidtux_right);
1183 for (i = 0; i < 4; i++)
1185 texture_free(&img_bsod_left[i]);
1186 texture_free(&img_bsod_right[i]);
1189 texture_free(&img_bsod_squished_left);
1190 texture_free(&img_bsod_squished_right);
1192 texture_free(&img_bsod_falling_left);
1193 texture_free(&img_bsod_falling_right);
1195 for (i = 0; i < 3; i++)
1197 texture_free(&img_laptop_left[i]);
1198 texture_free(&img_laptop_right[i]);
1201 texture_free(&img_laptop_flat_left);
1202 texture_free(&img_laptop_flat_right);
1204 texture_free(&img_laptop_falling_left);
1205 texture_free(&img_laptop_falling_right);
1207 for (i = 0; i < 2; i++)
1209 texture_free(&img_money_left[i]);
1210 texture_free(&img_money_right[i]);
1213 texture_free(&img_box_full);
1214 texture_free(&img_box_empty);
1216 texture_free(&img_water);
1217 for (i = 0; i < 3; i++)
1218 texture_free(&img_waves[i]);
1220 texture_free(&img_pole);
1221 texture_free(&img_poletop);
1223 for (i = 0; i < 2; i++)
1224 texture_free(&img_flag[i]);
1226 texture_free(&img_mints);
1227 texture_free(&img_coffee);
1229 for (i = 0; i < 4; i++)
1231 texture_free(&img_distro[i]);
1232 texture_free(&img_cloud[0][i]);
1233 texture_free(&img_cloud[1][i]);
1236 texture_free(&img_golden_herring);
1238 for (i = 0; i < NUM_SOUNDS; i++)
1239 free_chunk(sounds[i]);
1241 /* free the herring song */
1242 free_music( herring_song );
1246 /* Draw a tile on the screen: */
1248 void drawshape(float x, float y, unsigned char c)
1252 if (c == 'X' || c == 'x')
1253 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1254 else if (c == 'Y' || c == 'y')
1255 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1256 else if (c == 'A' || c =='B' || c == '!')
1257 texture_draw(&img_box_full, x, y, NO_UPDATE);
1259 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1260 else if (c >= 'C' && c <= 'F')
1261 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1262 else if (c >= 'c' && c <= 'f')
1263 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1264 else if (c >= 'G' && c <= 'J')
1265 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1266 else if (c >= 'g' && c <= 'j')
1267 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1269 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1271 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1273 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1275 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1279 z = (frame / 2) % 6;
1282 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1284 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1286 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1290 z = (frame / 3) % 3;
1292 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1295 texture_draw(&img_poletop, x, y, NO_UPDATE);
1298 texture_draw(&img_pole, x, y, NO_UPDATE);
1300 /* Mark this as the end position of the level! */
1306 z = (frame / 3) % 2;
1308 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1311 texture_draw(&img_water, x, y, NO_UPDATE);
1315 /* What shape is at some position? */
1317 unsigned char shape(float x, float y)
1326 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1328 c = current_level.tiles[yy][xx];
1339 int issolid(float x, float y)
1341 if (isbrick(x, y) ||
1343 (shape(x, y) == '[') ||
1344 (shape(x, y) == '=') ||
1345 (shape(x, y) == ']') ||
1346 (shape(x, y) == 'A') ||
1347 (shape(x, y) == 'B') ||
1348 (shape(x, y) == '!') ||
1349 (shape(x, y) == 'a'))
1358 int issolid(float x, float y)
1360 if (isbrick(x, y) ||
1361 isbrick(x + 31, y) ||
1364 (shape(x, y) == '[' ||
1365 shape(x + 31, y) == '[') ||
1366 (shape(x, y) == '=' ||
1367 shape(x + 31, y) == '=') ||
1368 (shape(x, y) == ']' ||
1369 shape(x + 31, y) == ']') ||
1370 (shape(x, y) == 'A' ||
1371 shape(x + 31, y) == 'A') ||
1372 (shape(x, y) == 'B' ||
1373 shape(x + 31, y) == 'B') ||
1374 (shape(x, y) == '!' ||
1375 shape(x + 31, y) == '!') ||
1376 (shape(x, y) == 'a' ||
1377 shape(x + 31, y) == 'a'))
1386 /* Is it a brick? */
1388 int isbrick(float x, float y)
1390 if (shape(x, y) == 'X' ||
1391 shape(x, y) == 'x' ||
1392 shape(x, y) == 'Y' ||
1404 int isice(float x, float y)
1406 if (shape(x, y) == '#')
1415 /* Is it a full box? */
1417 int isfullbox(float x, float y)
1419 if (shape(x, y) == 'A' ||
1420 shape(x, y) == 'B' ||
1429 /* Break a brick: */
1431 void trybreakbrick(float x, float y)
1435 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1437 /* Get a distro from it: */
1439 add_bouncy_distro(((x + 1) / 32) * 32,
1440 (int)(y / 32) * 32);
1442 if (counting_distros == NO)
1444 counting_distros = YES;
1445 distro_counter = 50;
1448 if (distro_counter <= 0)
1449 level_change(¤t_level,x, y, 'a');
1451 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1452 score = score + SCORE_DISTRO;
1457 /* Get rid of it: */
1459 level_change(¤t_level,x, y,'.');
1463 /* Replace it with broken bits: */
1465 add_broken_brick(((x + 1) / 32) * 32,
1466 (int)(y / 32) * 32);
1469 /* Get some score: */
1471 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1472 score = score + SCORE_BRICK;
1477 /* Bounce a brick: */
1479 void bumpbrick(float x, float y)
1481 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1482 (int)(y / 32) * 32);
1484 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1490 void tryemptybox(float x, float y)
1492 if (isfullbox(x, y))
1494 if (shape(x, y) == 'A')
1497 DEBUG_MSG("Here I am");
1499 /* Box with a distro! */
1501 add_bouncy_distro(((x + 1) / 32) * 32,
1502 (int)(y / 32) * 32 - 32);
1504 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1505 score = score + SCORE_DISTRO;
1508 else if (shape(x, y) == 'B')
1510 /* Add an upgrade! */
1512 if (tux.size == SMALL)
1514 /* Tux is small, add mints! */
1516 add_upgrade(((x + 1) / 32) * 32,
1517 (int)(y / 32) * 32 - 32,
1522 /* Tux is big, add coffee: */
1524 add_upgrade(((x + 1) / 32) * 32,
1525 (int)(y / 32) * 32 - 32,
1529 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1531 else if (shape(x, y) == '!')
1533 /* Add a golden herring */
1535 add_upgrade(((x + 1) / 32) * 32,
1536 (int)(y / 32) * 32 - 32,
1540 /* Empty the box: */
1542 level_change(¤t_level,x, y, 'a');
1547 /* Try to grab a distro: */
1549 void trygrabdistro(float x, float y, int bounciness)
1551 if (shape(x, y) == '$')
1553 level_change(¤t_level,x, y, '.');
1554 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1556 if (bounciness == BOUNCE)
1558 add_bouncy_distro(((x + 1) / 32) * 32,
1559 (int)(y / 32) * 32);
1562 score = score + SCORE_DISTRO;
1567 /* Try to bump a bad guy from below: */
1569 void trybumpbadguy(float x, float y)
1576 for (i = 0; i < num_bad_guys; i++)
1578 if (bad_guys[i].base.alive &&
1579 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1580 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1582 if (bad_guys[i].kind == BAD_BSOD ||
1583 bad_guys[i].kind == BAD_LAPTOP)
1585 bad_guys[i].dying = FALLING;
1586 bad_guys[i].base.ym = -8;
1587 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1595 for (i = 0; i < num_upgrades; i++)
1597 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1598 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1599 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1601 upgrades[i].base.xm = -upgrades[i].base.xm;
1602 upgrades[i].base.ym = -8;
1603 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1609 void drawstatus(void)
1613 sprintf(str, "%d", score);
1614 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1615 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1617 if(st_gl_mode == ST_GL_PLAY)
1619 sprintf(str, "%d", hs_score);
1620 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1621 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1623 else if(st_gl_mode == ST_GL_TEST)
1625 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1628 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1630 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1631 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1632 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1635 sprintf(str, "%d", distros);
1636 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1637 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1639 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1643 sprintf(str, "%2.1f", fps_fps);
1644 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1645 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1648 for(i=0; i < tux.lives; ++i)
1650 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1655 void drawendscreen(void)
1659 clearscreen(0, 0, 0);
1661 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1663 sprintf(str, "SCORE: %d", score);
1664 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1666 sprintf(str, "DISTROS: %d", distros);
1667 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1673 void drawresultscreen(void)
1677 clearscreen(0, 0, 0);
1679 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1681 sprintf(str, "SCORE: %d", score);
1682 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1684 sprintf(str, "DISTROS: %d", distros);
1685 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1694 time_t current_time = time(NULL);
1695 struct tm* time_struct;
1698 time_struct = localtime(¤t_time);
1699 sprintf(savefile,"%s/%d-%d-%d-%d.save",st_save_dir,time_struct->tm_year+1900,time_struct->tm_mon,time_struct->tm_mday,time_struct->tm_hour);
1700 printf("%s",savefile);
1703 fi = fopen(savefile, "wb");
1707 fprintf(stderr, "Warning: I could not open the high score file ");
1712 fwrite(&level,4,1,fi);
1713 fwrite(&score,4,1,fi);
1714 fwrite(&distros,4,1,fi);
1715 fwrite(&tux.base.x,4,1,fi);
1716 fwrite(&tux.base.y,4,1,fi);
1717 fwrite(&scroll_x,4,1,fi);
1718 fwrite(¤t_level.time_left,4,1,fi);
1724 void loadgame(char* filename)
1728 time_t current_time = time(NULL);
1729 struct tm* time_struct;
1731 time_struct = localtime(¤t_time);
1732 sprintf(savefile,"%s/%d-%d-%d-%d.save",st_save_dir,time_struct->tm_year+1900,time_struct->tm_mon,time_struct->tm_mday,time_struct->tm_hour);
1733 printf("%s",savefile);
1736 fi = fopen(savefile, "rb");
1740 fprintf(stderr, "Warning: I could not open the high score file ");
1745 player_level_begin(&tux);
1747 level_free(¤t_level);
1748 if(level_load(¤t_level,level_subset,level) != 0)
1752 activate_bad_guys();
1754 level_load_gfx(¤t_level);
1756 level_load_song(¤t_level);
1760 fread(&level,4,1,fi);
1761 fread(&score,4,1,fi);
1762 fread(&distros,4,1,fi);
1763 fread(&tux.base.x,4,1,fi);
1764 fread(&tux.base.y,4,1,fi);
1765 fread(&scroll_x,4,1,fi);
1766 fread(¤t_level.time_left,4,1,fi);