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_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();
156 st_pause_ticks_start();
164 case SDL_KEYUP: /* A keyrelease! */
165 key = event.key.keysym.sym;
167 if(player_key_event(&tux,key,UP))
178 st_pause_ticks_stop();
183 st_pause_ticks_start();
188 if(debug_mode == YES)
189 tux.size = !tux.size;
192 if(debug_mode == YES)
196 if(debug_mode == YES)
200 if(debug_mode == YES)
204 if(debug_mode == YES)
205 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
208 if(debug_mode == YES)
212 if(debug_mode == YES)
221 case SDL_JOYAXISMOTION:
222 switch(event.jaxis.axis)
225 if (event.jaxis.value < -1024)
226 tux.input.left = DOWN;
227 else if (event.jaxis.value > 1024)
230 if (event.jaxis.value > 1024)
231 tux.input.right = DOWN;
232 else if (event.jaxis.value < -1024)
233 tux.input.right = UP;
236 if (event.jaxis.value > 1024)
237 tux.input.down = DOWN;
238 else if (event.jaxis.value < -1024)
241 /* Handle joystick for the menu */
244 if(tux.input.down == DOWN)
245 menuaction = MN_DOWN;
254 case SDL_JOYBUTTONDOWN:
255 if (event.jbutton.button == JOY_A)
257 else if (event.jbutton.button == JOY_B)
258 tux.input.fire = DOWN;
260 case SDL_JOYBUTTONUP:
261 if (event.jbutton.button == JOY_A)
263 else if (event.jbutton.button == JOY_B)
279 /* --- GAME ACTION! --- */
281 int game_action(void)
285 /* (tux_dying || next_level) */
286 if (tux.dying || next_level)
288 /* Tux either died, or reached the end of a level! */
296 /* End of a level! */
299 if(st_gl_mode == ST_GL_PLAY)
301 player_level_begin(&tux);
307 /* No more lives!? */
311 if(st_gl_mode == ST_GL_PLAY)
314 if(st_gl_mode == ST_GL_PLAY)
316 if (score > hs_score)
320 level_free(¤t_level);
325 } /* if (lives < 0) */
328 /* Either way, (re-)load the (next) level... */
330 player_level_begin(&tux);
332 level_free(¤t_level);
333 if(level_load(¤t_level,level_subset,level) != 0)
339 level_load_gfx(¤t_level);
341 level_load_song(¤t_level);
342 if(st_gl_mode == ST_GL_PLAY)
349 /* Handle bouncy distros: */
351 for (i = 0; i < num_bouncy_distros; i++)
353 bouncy_distro_action(&bouncy_distros[i]);
357 /* Handle broken bricks: */
359 for (i = 0; i < num_broken_bricks; i++)
361 broken_brick_action(&broken_bricks[i]);
365 /* Handle distro counting: */
367 if (counting_distros == YES)
371 if (distro_counter <= 0)
372 counting_distros = -1;
376 /* Handle bouncy bricks: */
378 for (i = 0; i < num_bouncy_bricks; i++)
380 bouncy_brick_action(&bouncy_bricks[i]);
384 /* Handle floating scores: */
386 for (i = 0; i < num_floating_scores; i++)
388 floating_score_action(&floating_scores[i]);
392 /* Handle bullets: */
394 for (i = 0; i < num_bullets; ++i)
396 bullet_action(&bullets[i]);
399 /* Handle upgrades: */
401 for (i = 0; i < num_upgrades; i++)
403 upgrade_action(&upgrades[i]);
407 /* Handle bad guys: */
409 for (i = 0; i < num_bad_guys; i++)
411 badguy_action(&bad_guys[i]);
414 /* Handle all possible collisions. */
420 /* --- GAME DRAW! --- */
428 if (tux.dying && (frame % 4) == 0)
429 clearscreen(255, 255, 255);
430 else if(timer_check(&super_bkgd_timer))
431 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
434 /* Draw the real background */
435 if(current_level.bkgd_image[0] != '\0')
437 s = (int)scroll_x / 30;
438 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
439 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
443 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
447 /* Draw background: */
449 for (y = 0; y < 15; ++y)
451 for (x = 0; x < 21; ++x)
453 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
454 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
459 /* (Bouncy bricks): */
461 for (i = 0; i < num_bouncy_bricks; ++i)
463 bouncy_brick_draw(&bouncy_bricks[i]);
469 for (i = 0; i < num_bad_guys; ++i)
471 badguy_draw(&bad_guys[i]);
480 for (i = 0; i < num_bullets; ++i)
482 bullet_draw(&bullets[i]);
485 /* (Floating scores): */
487 for (i = 0; i < num_floating_scores; ++i)
489 floating_score_draw(&floating_scores[i]);
495 for (i = 0; i < num_upgrades; ++i)
497 upgrade_draw(&upgrades[i]);
501 /* (Bouncy distros): */
503 for (i = 0; i < num_bouncy_distros; ++i)
505 bouncy_distro_draw(&bouncy_distros[i]);
509 /* (Broken bricks): */
511 for (i = 0; i < num_broken_bricks; ++i)
513 broken_brick_draw(&broken_bricks[i]);
522 for(i = 0; i < x; ++i)
524 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);
526 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
527 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
531 menu_process_current();
533 /* (Update it all!) */
540 /* --- GAME LOOP! --- */
542 int gameloop(char * subset, int levelnb, int mode)
544 int fps_cnt, jump, done;
545 timer_type fps_timer, frame_timer;
549 strcpy(level_subset,subset);
553 clearscreen(0, 0, 0);
561 menu_set_current(&game_menu);
567 if(level_load(¤t_level,level_subset,level) != 0)
569 level_load_gfx(¤t_level);
571 level_load_song(¤t_level);
572 if(st_gl_mode == ST_GL_PLAY)
577 if(st_gl_mode == ST_GL_PLAY)
582 /* --- MAIN GAME LOOP!!! --- */
589 timer_init(&fps_timer);
590 timer_init(&frame_timer);
593 while (SDL_PollEvent(&event))
601 /* Calculate the movement-factor */
602 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
604 if(!timer_check(&frame_timer))
606 timer_start(&frame_timer,25);
613 tux.input.old_fire = tux.input.fire;
615 /*printf("%lf\n",frame_ratio);*/
621 if(current_menu == &game_menu)
623 switch (menu_check(&game_menu))
626 st_pause_ticks_stop();
636 else if(current_menu == &options_menu)
638 process_options_menu();
643 /* Handle actions: */
645 if(!game_pause && !show_menu)
647 if (game_action() == 0)
649 /* == 0: no more lives */
650 /* == -1: continues */
660 if(tux.input.down == DOWN)
663 /*Draw the current scene to the screen */
664 /*If the machine running the game is too slow
665 skip the drawing of the frame (so the calculations are more precise and
666 the FPS aren't affected).*/
667 /*if( ! fps_fps < 50.0 )
670 jump = YES;*/ /*FIXME: Implement this tweak right.*/
673 /* Time stops in pause mode */
674 if(game_pause || show_menu )
679 /* Set the time the last update and the time of the current update */
680 last_update_time = update_time;
681 update_time = st_get_ticks();
684 /* Pause till next frame, if the machine running the game is too fast: */
685 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
686 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
687 if(last_update_time >= update_time - 12 && jump != YES )
689 //if((update_time - last_update_time) < 10)
690 // SDL_Delay((11 - (update_time - last_update_time))/2);
696 if (timer_check(&time_left))
698 /* are we low on time ? */
699 if ((timer_get_left(&time_left) < TIME_WARNING)
700 && (current_music != HURRYUP_MUSIC))
702 current_music = HURRYUP_MUSIC;
703 /* stop the others music, prepare to play the fast music */
712 player_kill(&tux,KILL);
715 /* Keep playing the correct music: */
717 if (!playing_music())
719 play_current_music();
722 /* Calculate frames per second */
726 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
728 if(!timer_check(&fps_timer))
730 timer_start(&fps_timer,1000);
736 while (!done && !quit);
742 level_free(¤t_level);
751 /* Initialize the game stuff: */
759 /* Load graphics/sounds shared between all levels: */
761 void loadshared(void)
764 char * herring_song_path; /* for loading herring song*/
768 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
769 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
770 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
772 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
773 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
774 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
776 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
777 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
778 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
780 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
781 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
782 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
785 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
788 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
791 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
794 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
797 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
800 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
803 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
806 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
808 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
811 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
814 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
817 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
819 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
822 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
825 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
828 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
831 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
834 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
837 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
840 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
842 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
845 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
848 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
851 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-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",
866 texture_load(&ducktux_right ,DATA_PREFIX
867 "/images/shared/ducktux-right.png",
870 texture_load(&ducktux_left ,DATA_PREFIX
871 "/images/shared/ducktux-left.png",
874 texture_load(&skidtux_right ,DATA_PREFIX
875 "/images/shared/skidtux-right.png",
878 texture_load(&skidtux_left ,DATA_PREFIX
879 "/images/shared/skidtux-left.png",
882 texture_load(&duckfiretux_right ,DATA_PREFIX
883 "/images/shared/duckfiretux-right.png",
886 texture_load(&duckfiretux_left ,DATA_PREFIX
887 "/images/shared/duckfiretux-left.png",
890 texture_load(&skidfiretux_right ,DATA_PREFIX
891 "/images/shared/skidfiretux-right.png",
894 texture_load(&skidfiretux_left ,DATA_PREFIX
895 "/images/shared/skidfiretux-left.png",
901 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
903 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
910 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
912 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
915 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
918 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
924 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
925 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
931 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
933 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
939 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
942 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
945 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
948 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
952 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
955 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
958 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
961 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
969 texture_load(&img_bsod_left[0] ,DATA_PREFIX
970 "/images/shared/bsod-left-0.png",
973 texture_load(&img_bsod_left[1] ,DATA_PREFIX
974 "/images/shared/bsod-left-1.png",
977 texture_load(&img_bsod_left[2] ,DATA_PREFIX
978 "/images/shared/bsod-left-2.png",
981 texture_load(&img_bsod_left[3] ,DATA_PREFIX
982 "/images/shared/bsod-left-3.png",
985 texture_load(&img_bsod_right[0] ,DATA_PREFIX
986 "/images/shared/bsod-right-0.png",
989 texture_load(&img_bsod_right[1] ,DATA_PREFIX
990 "/images/shared/bsod-right-1.png",
993 texture_load(&img_bsod_right[2] ,DATA_PREFIX
994 "/images/shared/bsod-right-2.png",
997 texture_load(&img_bsod_right[3] ,DATA_PREFIX
998 "/images/shared/bsod-right-3.png",
1001 texture_load(&img_bsod_squished_left ,DATA_PREFIX
1002 "/images/shared/bsod-squished-left.png",
1005 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1006 "/images/shared/bsod-squished-right.png",
1009 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1010 "/images/shared/bsod-falling-left.png",
1013 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1014 "/images/shared/bsod-falling-right.png",
1020 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1021 "/images/shared/laptop-left-0.png",
1024 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1025 "/images/shared/laptop-left-1.png",
1028 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1029 "/images/shared/laptop-left-2.png",
1032 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1033 "/images/shared/laptop-right-0.png",
1036 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1037 "/images/shared/laptop-right-1.png",
1040 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1041 "/images/shared/laptop-right-2.png",
1044 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1045 "/images/shared/laptop-flat-left.png",
1048 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1049 "/images/shared/laptop-flat-right.png",
1052 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1053 "/images/shared/laptop-falling-left.png",
1056 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1057 "/images/shared/laptop-falling-right.png",
1063 texture_load(&img_money_left[0] ,DATA_PREFIX
1064 "/images/shared/bag-left-0.png",
1067 texture_load(&img_money_left[1] ,DATA_PREFIX
1068 "/images/shared/bag-left-1.png",
1071 texture_load(&img_money_right[0] ,DATA_PREFIX
1072 "/images/shared/bag-right-0.png",
1075 texture_load(&img_money_right[1] ,DATA_PREFIX
1076 "/images/shared/bag-right-1.png",
1083 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1084 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1089 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1091 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1098 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1101 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1104 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1107 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1113 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1118 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1122 /* Super background: */
1124 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1128 /* Sound effects: */
1130 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1131 // initialize sounds[i] with the correct pointer's value:
1132 // NULL or something else. And it will be dangerous to
1133 // play with not-initialized pointers.
1134 // This is also true with if (use_music)
1135 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1137 for (i = 0; i < NUM_SOUNDS; i++)
1138 sounds[i] = load_sound(soundfilenames[i]);
1141 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1142 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
1144 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1146 herring_song = load_song(herring_song_path);
1148 free(herring_song_path);
1153 /* Free shared data: */
1155 void unloadshared(void)
1159 for (i = 0; i < 3; i++)
1161 texture_free(&tux_right[i]);
1162 texture_free(&tux_left[i]);
1163 texture_free(&bigtux_right[i]);
1164 texture_free(&bigtux_left[i]);
1167 texture_free(&bigtux_right_jump);
1168 texture_free(&bigtux_left_jump);
1170 for (i = 0; i < 2; i++)
1172 texture_free(&cape_right[i]);
1173 texture_free(&cape_left[i]);
1174 texture_free(&bigcape_right[i]);
1175 texture_free(&bigcape_left[i]);
1178 texture_free(&ducktux_left);
1179 texture_free(&ducktux_right);
1181 texture_free(&skidtux_left);
1182 texture_free(&skidtux_right);
1184 for (i = 0; i < 4; i++)
1186 texture_free(&img_bsod_left[i]);
1187 texture_free(&img_bsod_right[i]);
1190 texture_free(&img_bsod_squished_left);
1191 texture_free(&img_bsod_squished_right);
1193 texture_free(&img_bsod_falling_left);
1194 texture_free(&img_bsod_falling_right);
1196 for (i = 0; i < 3; i++)
1198 texture_free(&img_laptop_left[i]);
1199 texture_free(&img_laptop_right[i]);
1202 texture_free(&img_laptop_flat_left);
1203 texture_free(&img_laptop_flat_right);
1205 texture_free(&img_laptop_falling_left);
1206 texture_free(&img_laptop_falling_right);
1208 for (i = 0; i < 2; i++)
1210 texture_free(&img_money_left[i]);
1211 texture_free(&img_money_right[i]);
1214 texture_free(&img_box_full);
1215 texture_free(&img_box_empty);
1217 texture_free(&img_water);
1218 for (i = 0; i < 3; i++)
1219 texture_free(&img_waves[i]);
1221 texture_free(&img_pole);
1222 texture_free(&img_poletop);
1224 for (i = 0; i < 2; i++)
1225 texture_free(&img_flag[i]);
1227 texture_free(&img_mints);
1228 texture_free(&img_coffee);
1230 for (i = 0; i < 4; i++)
1232 texture_free(&img_distro[i]);
1233 texture_free(&img_cloud[0][i]);
1234 texture_free(&img_cloud[1][i]);
1237 texture_free(&img_golden_herring);
1239 for (i = 0; i < NUM_SOUNDS; i++)
1240 free_chunk(sounds[i]);
1242 /* free the herring song */
1243 free_music( herring_song );
1247 /* Draw a tile on the screen: */
1249 void drawshape(float x, float y, unsigned char c)
1253 if (c == 'X' || c == 'x')
1254 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1255 else if (c == 'Y' || c == 'y')
1256 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1257 else if (c == 'A' || c =='B' || c == '!')
1258 texture_draw(&img_box_full, x, y, NO_UPDATE);
1260 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1261 else if (c >= 'C' && c <= 'F')
1262 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1263 else if (c >= 'c' && c <= 'f')
1264 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1265 else if (c >= 'G' && c <= 'J')
1266 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1267 else if (c >= 'g' && c <= 'j')
1268 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1270 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1272 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1274 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1276 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1280 z = (frame / 2) % 6;
1283 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1285 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1287 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1291 z = (frame / 3) % 3;
1293 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1296 texture_draw(&img_poletop, x, y, NO_UPDATE);
1299 texture_draw(&img_pole, x, y, NO_UPDATE);
1301 /* Mark this as the end position of the level! */
1307 z = (frame / 3) % 2;
1309 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1312 texture_draw(&img_water, x, y, NO_UPDATE);
1316 /* What shape is at some position? */
1318 unsigned char shape(float x, float y)
1327 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1329 c = current_level.tiles[yy][xx];
1340 int issolid(float x, float y)
1342 if (isbrick(x, y) ||
1344 (shape(x, y) == '[') ||
1345 (shape(x, y) == '=') ||
1346 (shape(x, y) == ']') ||
1347 (shape(x, y) == 'A') ||
1348 (shape(x, y) == 'B') ||
1349 (shape(x, y) == '!') ||
1350 (shape(x, y) == 'a'))
1359 int issolid(float x, float y)
1361 if (isbrick(x, y) ||
1362 isbrick(x + 31, y) ||
1365 (shape(x, y) == '[' ||
1366 shape(x + 31, y) == '[') ||
1367 (shape(x, y) == '=' ||
1368 shape(x + 31, y) == '=') ||
1369 (shape(x, y) == ']' ||
1370 shape(x + 31, y) == ']') ||
1371 (shape(x, y) == 'A' ||
1372 shape(x + 31, y) == 'A') ||
1373 (shape(x, y) == 'B' ||
1374 shape(x + 31, y) == 'B') ||
1375 (shape(x, y) == '!' ||
1376 shape(x + 31, y) == '!') ||
1377 (shape(x, y) == 'a' ||
1378 shape(x + 31, y) == 'a'))
1387 /* Is it a brick? */
1389 int isbrick(float x, float y)
1391 if (shape(x, y) == 'X' ||
1392 shape(x, y) == 'x' ||
1393 shape(x, y) == 'Y' ||
1405 int isice(float x, float y)
1407 if (shape(x, y) == '#')
1416 /* Is it a full box? */
1418 int isfullbox(float x, float y)
1420 if (shape(x, y) == 'A' ||
1421 shape(x, y) == 'B' ||
1430 /* Break a brick: */
1432 void trybreakbrick(float x, float y)
1436 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1438 /* Get a distro from it: */
1440 add_bouncy_distro(((x + 1) / 32) * 32,
1441 (int)(y / 32) * 32);
1443 if (counting_distros == NO)
1445 counting_distros = YES;
1446 distro_counter = 50;
1449 if (distro_counter <= 0)
1450 level_change(¤t_level,x, y, 'a');
1452 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1453 score = score + SCORE_DISTRO;
1458 /* Get rid of it: */
1460 level_change(¤t_level,x, y,'.');
1464 /* Replace it with broken bits: */
1466 add_broken_brick(((x + 1) / 32) * 32,
1467 (int)(y / 32) * 32);
1470 /* Get some score: */
1472 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1473 score = score + SCORE_BRICK;
1478 /* Bounce a brick: */
1480 void bumpbrick(float x, float y)
1482 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1483 (int)(y / 32) * 32);
1485 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1491 void tryemptybox(float x, float y)
1493 if (isfullbox(x, y))
1495 if (shape(x, y) == 'A')
1498 DEBUG_MSG("Here I am");
1500 /* Box with a distro! */
1502 add_bouncy_distro(((x + 1) / 32) * 32,
1503 (int)(y / 32) * 32 - 32);
1505 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1506 score = score + SCORE_DISTRO;
1509 else if (shape(x, y) == 'B')
1511 /* Add an upgrade! */
1513 if (tux.size == SMALL)
1515 /* Tux is small, add mints! */
1517 add_upgrade(((x + 1) / 32) * 32,
1518 (int)(y / 32) * 32 - 32,
1523 /* Tux is big, add coffee: */
1525 add_upgrade(((x + 1) / 32) * 32,
1526 (int)(y / 32) * 32 - 32,
1530 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1532 else if (shape(x, y) == '!')
1534 /* Add a golden herring */
1536 add_upgrade(((x + 1) / 32) * 32,
1537 (int)(y / 32) * 32 - 32,
1541 /* Empty the box: */
1543 level_change(¤t_level,x, y, 'a');
1548 /* Try to grab a distro: */
1550 void trygrabdistro(float x, float y, int bounciness)
1552 if (shape(x, y) == '$')
1554 level_change(¤t_level,x, y, '.');
1555 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1557 if (bounciness == BOUNCE)
1559 add_bouncy_distro(((x + 1) / 32) * 32,
1560 (int)(y / 32) * 32);
1563 score = score + SCORE_DISTRO;
1568 /* Try to bump a bad guy from below: */
1570 void trybumpbadguy(float x, float y)
1577 for (i = 0; i < num_bad_guys; i++)
1579 if (bad_guys[i].base.alive &&
1580 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1581 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1583 if (bad_guys[i].kind == BAD_BSOD ||
1584 bad_guys[i].kind == BAD_LAPTOP)
1586 bad_guys[i].dying = FALLING;
1587 bad_guys[i].base.ym = -8;
1588 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1596 for (i = 0; i < num_upgrades; i++)
1598 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1599 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1600 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1602 upgrades[i].base.xm = -upgrades[i].base.xm;
1603 upgrades[i].base.ym = -8;
1604 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1610 void drawstatus(void)
1614 sprintf(str, "%d", score);
1615 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1616 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1618 if(st_gl_mode == ST_GL_PLAY)
1620 sprintf(str, "%d", hs_score);
1621 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1622 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1624 else if(st_gl_mode == ST_GL_TEST)
1626 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1629 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1631 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1632 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1633 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1636 sprintf(str, "%d", distros);
1637 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1638 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1640 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1644 sprintf(str, "%2.1f", fps_fps);
1645 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1646 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1649 for(i=0; i < tux.lives; ++i)
1651 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1656 void drawendscreen(void)
1660 clearscreen(0, 0, 0);
1662 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1664 sprintf(str, "SCORE: %d", score);
1665 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1667 sprintf(str, "DISTROS: %d", distros);
1668 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1674 void drawresultscreen(void)
1678 clearscreen(0, 0, 0);
1680 text_drawf(&blue_text, "Result:", 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);
1695 time_t current_time = time(NULL);
1696 struct tm* time_struct;
1699 time_struct = localtime(¤t_time);
1700 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);
1701 printf("%s",savefile);
1704 fi = fopen(savefile, "wb");
1708 fprintf(stderr, "Warning: I could not open the high score file ");
1713 fwrite(&level,4,1,fi);
1714 fwrite(&score,4,1,fi);
1715 fwrite(&distros,4,1,fi);
1716 fwrite(&tux.base.x,4,1,fi);
1717 fwrite(&tux.base.y,4,1,fi);
1718 fwrite(&scroll_x,4,1,fi);
1719 fwrite(¤t_level.time_left,4,1,fi);
1725 void loadgame(char* filename)
1729 time_t current_time = time(NULL);
1730 struct tm* time_struct;
1732 time_struct = localtime(¤t_time);
1733 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);
1734 printf("%s",savefile);
1737 fi = fopen(savefile, "rb");
1741 fprintf(stderr, "Warning: I could not open the high score file ");
1746 player_level_begin(&tux);
1748 level_free(¤t_level);
1749 if(level_load(¤t_level,level_subset,level) != 0)
1753 activate_bad_guys();
1755 level_load_gfx(¤t_level);
1757 level_load_song(¤t_level);
1761 fread(&level,4,1,fi);
1762 fread(&score,4,1,fi);
1763 fread(&distros,4,1,fi);
1764 fread(&tux.base.x,4,1,fi);
1765 fread(&tux.base.y,4,1,fi);
1766 fread(&scroll_x,4,1,fi);
1767 fread(¤t_level.time_left,4,1,fi);