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)
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_key_event(&tux,key,UP))
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();
632 else if(current_menu == &options_menu)
634 process_options_menu();
639 /* Handle actions: */
641 if(!game_pause && !show_menu)
643 if (game_action() == 0)
645 /* == 0: no more lives */
646 /* == -1: continues */
656 if(tux.input.down == DOWN)
659 /*Draw the current scene to the screen */
660 /*If the machine running the game is too slow
661 skip the drawing of the frame (so the calculations are more precise and
662 the FPS aren't affected).*/
663 /*if( ! fps_fps < 50.0 )
666 jump = YES;*/ /*FIXME: Implement this tweak right.*/
669 /* Time stops in pause mode */
670 if(game_pause || show_menu )
675 /* Set the time the last update and the time of the current update */
676 last_update_time = update_time;
677 update_time = st_get_ticks();
680 /* Pause till next frame, if the machine running the game is too fast: */
681 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
682 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
683 if(last_update_time >= update_time - 12 && jump != YES )
685 //if((update_time - last_update_time) < 10)
686 // SDL_Delay((11 - (update_time - last_update_time))/2);
692 if (timer_check(&time_left))
694 /* are we low on time ? */
695 if ((timer_get_left(&time_left) < TIME_WARNING)
696 && (current_music != HURRYUP_MUSIC))
698 current_music = HURRYUP_MUSIC;
699 /* stop the others music, prepare to play the fast music */
708 player_kill(&tux,KILL);
711 /* Keep playing the correct music: */
713 if (!playing_music())
715 play_current_music();
718 /* Calculate frames per second */
722 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
724 if(!timer_check(&fps_timer))
726 timer_start(&fps_timer,1000);
732 while (!done && !quit);
738 level_free(¤t_level);
747 /* Initialize the game stuff: */
755 /* Load graphics/sounds shared between all levels: */
757 void loadshared(void)
760 char * herring_song_path; /* for loading herring song*/
764 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
765 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
766 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
768 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
769 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
770 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
772 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
773 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
774 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
776 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
777 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
778 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
781 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
784 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
787 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
790 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
793 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
796 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
799 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
802 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
804 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
807 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
810 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
813 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
815 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
818 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
821 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
824 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
827 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
830 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
833 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
836 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
838 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
841 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
844 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
847 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
849 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
852 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
855 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
858 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
862 texture_load(&ducktux_right ,DATA_PREFIX
863 "/images/shared/ducktux-right.png",
866 texture_load(&ducktux_left ,DATA_PREFIX
867 "/images/shared/ducktux-left.png",
870 texture_load(&skidtux_right ,DATA_PREFIX
871 "/images/shared/skidtux-right.png",
874 texture_load(&skidtux_left ,DATA_PREFIX
875 "/images/shared/skidtux-left.png",
878 texture_load(&duckfiretux_right ,DATA_PREFIX
879 "/images/shared/duckfiretux-right.png",
882 texture_load(&duckfiretux_left ,DATA_PREFIX
883 "/images/shared/duckfiretux-left.png",
886 texture_load(&skidfiretux_right ,DATA_PREFIX
887 "/images/shared/skidfiretux-right.png",
890 texture_load(&skidfiretux_left ,DATA_PREFIX
891 "/images/shared/skidfiretux-left.png",
897 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
899 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
906 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
908 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
911 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
914 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
920 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
921 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
927 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
929 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
935 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
938 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
941 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
944 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
948 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
951 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
954 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
957 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
965 texture_load(&img_bsod_left[0] ,DATA_PREFIX
966 "/images/shared/bsod-left-0.png",
969 texture_load(&img_bsod_left[1] ,DATA_PREFIX
970 "/images/shared/bsod-left-1.png",
973 texture_load(&img_bsod_left[2] ,DATA_PREFIX
974 "/images/shared/bsod-left-2.png",
977 texture_load(&img_bsod_left[3] ,DATA_PREFIX
978 "/images/shared/bsod-left-3.png",
981 texture_load(&img_bsod_right[0] ,DATA_PREFIX
982 "/images/shared/bsod-right-0.png",
985 texture_load(&img_bsod_right[1] ,DATA_PREFIX
986 "/images/shared/bsod-right-1.png",
989 texture_load(&img_bsod_right[2] ,DATA_PREFIX
990 "/images/shared/bsod-right-2.png",
993 texture_load(&img_bsod_right[3] ,DATA_PREFIX
994 "/images/shared/bsod-right-3.png",
997 texture_load(&img_bsod_squished_left ,DATA_PREFIX
998 "/images/shared/bsod-squished-left.png",
1001 texture_load(&img_bsod_squished_right ,DATA_PREFIX
1002 "/images/shared/bsod-squished-right.png",
1005 texture_load(&img_bsod_falling_left ,DATA_PREFIX
1006 "/images/shared/bsod-falling-left.png",
1009 texture_load(&img_bsod_falling_right ,DATA_PREFIX
1010 "/images/shared/bsod-falling-right.png",
1016 texture_load(&img_laptop_left[0] ,DATA_PREFIX
1017 "/images/shared/laptop-left-0.png",
1020 texture_load(&img_laptop_left[1] ,DATA_PREFIX
1021 "/images/shared/laptop-left-1.png",
1024 texture_load(&img_laptop_left[2] ,DATA_PREFIX
1025 "/images/shared/laptop-left-2.png",
1028 texture_load(&img_laptop_right[0] ,DATA_PREFIX
1029 "/images/shared/laptop-right-0.png",
1032 texture_load(&img_laptop_right[1] ,DATA_PREFIX
1033 "/images/shared/laptop-right-1.png",
1036 texture_load(&img_laptop_right[2] ,DATA_PREFIX
1037 "/images/shared/laptop-right-2.png",
1040 texture_load(&img_laptop_flat_left ,DATA_PREFIX
1041 "/images/shared/laptop-flat-left.png",
1044 texture_load(&img_laptop_flat_right ,DATA_PREFIX
1045 "/images/shared/laptop-flat-right.png",
1048 texture_load(&img_laptop_falling_left ,DATA_PREFIX
1049 "/images/shared/laptop-falling-left.png",
1052 texture_load(&img_laptop_falling_right ,DATA_PREFIX
1053 "/images/shared/laptop-falling-right.png",
1059 texture_load(&img_money_left[0] ,DATA_PREFIX
1060 "/images/shared/bag-left-0.png",
1063 texture_load(&img_money_left[1] ,DATA_PREFIX
1064 "/images/shared/bag-left-1.png",
1067 texture_load(&img_money_right[0] ,DATA_PREFIX
1068 "/images/shared/bag-right-0.png",
1071 texture_load(&img_money_right[1] ,DATA_PREFIX
1072 "/images/shared/bag-right-1.png",
1079 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1080 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1085 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1087 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1094 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1097 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1100 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1103 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1109 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1114 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1118 /* Super background: */
1120 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1124 /* Sound effects: */
1126 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1127 // initialize sounds[i] with the correct pointer's value:
1128 // NULL or something else. And it will be dangerous to
1129 // play with not-initialized pointers.
1130 // This is also true with if (use_music)
1131 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1133 for (i = 0; i < NUM_SOUNDS; i++)
1134 sounds[i] = load_sound(soundfilenames[i]);
1137 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1138 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
1140 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1142 herring_song = load_song(herring_song_path);
1144 free(herring_song_path);
1149 /* Free shared data: */
1151 void unloadshared(void)
1155 for (i = 0; i < 3; i++)
1157 texture_free(&tux_right[i]);
1158 texture_free(&tux_left[i]);
1159 texture_free(&bigtux_right[i]);
1160 texture_free(&bigtux_left[i]);
1163 texture_free(&bigtux_right_jump);
1164 texture_free(&bigtux_left_jump);
1166 for (i = 0; i < 2; i++)
1168 texture_free(&cape_right[i]);
1169 texture_free(&cape_left[i]);
1170 texture_free(&bigcape_right[i]);
1171 texture_free(&bigcape_left[i]);
1174 texture_free(&ducktux_left);
1175 texture_free(&ducktux_right);
1177 texture_free(&skidtux_left);
1178 texture_free(&skidtux_right);
1180 for (i = 0; i < 4; i++)
1182 texture_free(&img_bsod_left[i]);
1183 texture_free(&img_bsod_right[i]);
1186 texture_free(&img_bsod_squished_left);
1187 texture_free(&img_bsod_squished_right);
1189 texture_free(&img_bsod_falling_left);
1190 texture_free(&img_bsod_falling_right);
1192 for (i = 0; i < 3; i++)
1194 texture_free(&img_laptop_left[i]);
1195 texture_free(&img_laptop_right[i]);
1198 texture_free(&img_laptop_flat_left);
1199 texture_free(&img_laptop_flat_right);
1201 texture_free(&img_laptop_falling_left);
1202 texture_free(&img_laptop_falling_right);
1204 for (i = 0; i < 2; i++)
1206 texture_free(&img_money_left[i]);
1207 texture_free(&img_money_right[i]);
1210 texture_free(&img_box_full);
1211 texture_free(&img_box_empty);
1213 texture_free(&img_water);
1214 for (i = 0; i < 3; i++)
1215 texture_free(&img_waves[i]);
1217 texture_free(&img_pole);
1218 texture_free(&img_poletop);
1220 for (i = 0; i < 2; i++)
1221 texture_free(&img_flag[i]);
1223 texture_free(&img_mints);
1224 texture_free(&img_coffee);
1226 for (i = 0; i < 4; i++)
1228 texture_free(&img_distro[i]);
1229 texture_free(&img_cloud[0][i]);
1230 texture_free(&img_cloud[1][i]);
1233 texture_free(&img_golden_herring);
1235 for (i = 0; i < NUM_SOUNDS; i++)
1236 free_chunk(sounds[i]);
1238 /* free the herring song */
1239 free_music( herring_song );
1243 /* Draw a tile on the screen: */
1245 void drawshape(float x, float y, unsigned char c)
1249 if (c == 'X' || c == 'x')
1250 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1251 else if (c == 'Y' || c == 'y')
1252 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1253 else if (c == 'A' || c =='B' || c == '!')
1254 texture_draw(&img_box_full, x, y, NO_UPDATE);
1256 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1257 else if (c >= 'C' && c <= 'F')
1258 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1259 else if (c >= 'c' && c <= 'f')
1260 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1261 else if (c >= 'G' && c <= 'J')
1262 texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1263 else if (c >= 'g' && c <= 'j')
1264 texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1266 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1268 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1270 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1272 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1276 z = (frame / 2) % 6;
1279 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1281 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1283 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1287 z = (frame / 3) % 3;
1289 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1292 texture_draw(&img_poletop, x, y, NO_UPDATE);
1295 texture_draw(&img_pole, x, y, NO_UPDATE);
1297 /* Mark this as the end position of the level! */
1303 z = (frame / 3) % 2;
1305 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1308 texture_draw(&img_water, x, y, NO_UPDATE);
1312 /* What shape is at some position? */
1314 unsigned char shape(float x, float y)
1323 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1325 c = current_level.tiles[yy][xx];
1336 int issolid(float x, float y)
1338 if (isbrick(x, y) ||
1340 (shape(x, y) == '[') ||
1341 (shape(x, y) == '=') ||
1342 (shape(x, y) == ']') ||
1343 (shape(x, y) == 'A') ||
1344 (shape(x, y) == 'B') ||
1345 (shape(x, y) == '!') ||
1346 (shape(x, y) == 'a'))
1355 int issolid(float x, float y)
1357 if (isbrick(x, y) ||
1358 isbrick(x + 31, y) ||
1361 (shape(x, y) == '[' ||
1362 shape(x + 31, y) == '[') ||
1363 (shape(x, y) == '=' ||
1364 shape(x + 31, y) == '=') ||
1365 (shape(x, y) == ']' ||
1366 shape(x + 31, y) == ']') ||
1367 (shape(x, y) == 'A' ||
1368 shape(x + 31, y) == 'A') ||
1369 (shape(x, y) == 'B' ||
1370 shape(x + 31, y) == 'B') ||
1371 (shape(x, y) == '!' ||
1372 shape(x + 31, y) == '!') ||
1373 (shape(x, y) == 'a' ||
1374 shape(x + 31, y) == 'a'))
1383 /* Is it a brick? */
1385 int isbrick(float x, float y)
1387 if (shape(x, y) == 'X' ||
1388 shape(x, y) == 'x' ||
1389 shape(x, y) == 'Y' ||
1401 int isice(float x, float y)
1403 if (shape(x, y) == '#')
1412 /* Is it a full box? */
1414 int isfullbox(float x, float y)
1416 if (shape(x, y) == 'A' ||
1417 shape(x, y) == 'B' ||
1426 /* Break a brick: */
1428 void trybreakbrick(float x, float y)
1432 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1434 /* Get a distro from it: */
1436 add_bouncy_distro(((x + 1) / 32) * 32,
1437 (int)(y / 32) * 32);
1439 if (counting_distros == NO)
1441 counting_distros = YES;
1442 distro_counter = 50;
1445 if (distro_counter <= 0)
1446 level_change(¤t_level,x, y, 'a');
1448 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1449 score = score + SCORE_DISTRO;
1454 /* Get rid of it: */
1456 level_change(¤t_level,x, y,'.');
1460 /* Replace it with broken bits: */
1462 add_broken_brick(((x + 1) / 32) * 32,
1463 (int)(y / 32) * 32);
1466 /* Get some score: */
1468 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1469 score = score + SCORE_BRICK;
1474 /* Bounce a brick: */
1476 void bumpbrick(float x, float y)
1478 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1479 (int)(y / 32) * 32);
1481 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1487 void tryemptybox(float x, float y)
1489 if (isfullbox(x, y))
1491 if (shape(x, y) == 'A')
1494 DEBUG_MSG("Here I am");
1496 /* Box with a distro! */
1498 add_bouncy_distro(((x + 1) / 32) * 32,
1499 (int)(y / 32) * 32 - 32);
1501 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1502 score = score + SCORE_DISTRO;
1505 else if (shape(x, y) == 'B')
1507 /* Add an upgrade! */
1509 if (tux.size == SMALL)
1511 /* Tux is small, add mints! */
1513 add_upgrade(((x + 1) / 32) * 32,
1514 (int)(y / 32) * 32 - 32,
1519 /* Tux is big, add coffee: */
1521 add_upgrade(((x + 1) / 32) * 32,
1522 (int)(y / 32) * 32 - 32,
1526 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1528 else if (shape(x, y) == '!')
1530 /* Add a golden herring */
1532 add_upgrade(((x + 1) / 32) * 32,
1533 (int)(y / 32) * 32 - 32,
1537 /* Empty the box: */
1539 level_change(¤t_level,x, y, 'a');
1544 /* Try to grab a distro: */
1546 void trygrabdistro(float x, float y, int bounciness)
1548 if (shape(x, y) == '$')
1550 level_change(¤t_level,x, y, '.');
1551 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1553 if (bounciness == BOUNCE)
1555 add_bouncy_distro(((x + 1) / 32) * 32,
1556 (int)(y / 32) * 32);
1559 score = score + SCORE_DISTRO;
1564 /* Try to bump a bad guy from below: */
1566 void trybumpbadguy(float x, float y)
1573 for (i = 0; i < num_bad_guys; i++)
1575 if (bad_guys[i].base.alive &&
1576 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1577 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1579 if (bad_guys[i].kind == BAD_BSOD ||
1580 bad_guys[i].kind == BAD_LAPTOP)
1582 bad_guys[i].dying = FALLING;
1583 bad_guys[i].base.ym = -8;
1584 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1592 for (i = 0; i < num_upgrades; i++)
1594 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1595 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1596 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1598 upgrades[i].base.xm = -upgrades[i].base.xm;
1599 upgrades[i].base.ym = -8;
1600 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1606 void drawstatus(void)
1610 sprintf(str, "%d", score);
1611 text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1612 text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1614 if(st_gl_mode == ST_GL_PLAY)
1616 sprintf(str, "%d", hs_score);
1617 text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1618 text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1620 else if(st_gl_mode == ST_GL_TEST)
1622 text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1625 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1627 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1628 text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1629 text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1632 sprintf(str, "%d", distros);
1633 text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1634 text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1636 text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1640 sprintf(str, "%2.1f", fps_fps);
1641 text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1642 text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1645 for(i=0; i < tux.lives; ++i)
1647 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1652 void drawendscreen(void)
1656 clearscreen(0, 0, 0);
1658 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1660 sprintf(str, "SCORE: %d", score);
1661 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1663 sprintf(str, "DISTROS: %d", distros);
1664 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1670 void drawresultscreen(void)
1674 clearscreen(0, 0, 0);
1676 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1678 sprintf(str, "SCORE: %d", score);
1679 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1681 sprintf(str, "DISTROS: %d", distros);
1682 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1691 time_t current_time = time(NULL);
1692 struct tm* time_struct;
1695 time_struct = localtime(¤t_time);
1696 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);
1697 printf("%s",savefile);
1700 fi = fopen(savefile, "wb");
1704 fprintf(stderr, "Warning: I could not open the high score file ");
1709 fwrite(&level,4,1,fi);
1710 fwrite(&score,4,1,fi);
1711 fwrite(&distros,4,1,fi);
1712 fwrite(&tux.base.x,4,1,fi);
1713 fwrite(&tux.base.y,4,1,fi);
1714 fwrite(&scroll_x,4,1,fi);
1715 fwrite(¤t_level.time_left,4,1,fi);
1721 void loadgame(char* filename)
1725 time_t current_time = time(NULL);
1726 struct tm* time_struct;
1728 time_struct = localtime(¤t_time);
1729 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);
1730 printf("%s",savefile);
1733 fi = fopen(savefile, "rb");
1737 fprintf(stderr, "Warning: I could not open the high score file ");
1742 player_level_begin(&tux);
1744 level_free(¤t_level);
1745 if(level_load(¤t_level,level_subset,level) != 0)
1749 activate_bad_guys();
1751 level_load_gfx(¤t_level);
1753 level_load_song(¤t_level);
1757 fread(&level,4,1,fi);
1758 fread(&score,4,1,fi);
1759 fread(&distros,4,1,fi);
1760 fread(&tux.base.x,4,1,fi);
1761 fread(&tux.base.y,4,1,fi);
1762 fread(&scroll_x,4,1,fi);
1763 fread(¤t_level.time_left,4,1,fi);