7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - January 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];
46 /* Local variables: */
48 texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2];
49 texture_type img_cloud[2][4];
52 char level_subset[100];
57 /* Local function prototypes: */
59 void levelintro(void);
61 void loadlevelsong(void);
62 void unloadlevelsong(void);
63 void loadshared(void);
64 void unloadshared(void);
65 void drawstatus(void);
66 void drawendscreen(void);
67 void drawresultscreen(void);
75 sprintf(str, "LEVEL %d", level);
76 drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1);
78 sprintf(str, "%s", current_level.name);
79 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
81 sprintf(str, "TUX x %d", tux.lives);
82 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
90 void start_timers(void)
92 timer_start(&time_left,current_level.time_left*1000);
95 void activate_bad_guys(void)
99 /* Activate bad guys: */
101 for (y = 0; y < 15; y++)
103 for (x = 0; x < current_level.width; x++)
105 if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
107 add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
108 current_level.tiles[y][x] = '.';
115 /* --- GAME EVENT! --- */
117 void game_event(void)
119 while (SDL_PollEvent(&event))
123 case SDL_QUIT: /* Quit event - quit: */
126 case SDL_KEYDOWN: /* A keypress! */
127 key = event.key.keysym.sym;
129 /* Check for menu-events, if the menu is shown */
133 if(player_keydown_event(&tux,key))
138 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
151 case SDL_KEYUP: /* A keyrelease! */
152 key = event.key.keysym.sym;
154 if(player_keyup_event(&tux,key))
169 if(debug_mode == YES)
170 tux.size = !tux.size;
173 if(debug_mode == YES)
177 if(debug_mode == YES)
181 if(debug_mode == YES)
185 if(debug_mode == YES)
186 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
194 case SDL_JOYAXISMOTION:
195 switch(event.jaxis.axis)
198 printf("X: %d\n", event.jaxis.value);
199 if (event.jaxis.value < -1024)
200 tux.input.left = DOWN;
201 else if (event.jaxis.value > 1024)
204 if (event.jaxis.value > 1024)
205 tux.input.right = DOWN;
206 else if (event.jaxis.value < -1024)
207 tux.input.right = UP;
210 if (event.jaxis.value > 1024)
211 tux.input.down = DOWN;
212 else if (event.jaxis.value < -1024)
215 /* Handle joystick for the menu */
218 if(tux.input.down == DOWN)
219 menuaction = MN_DOWN;
228 case SDL_JOYBUTTONDOWN:
229 if (event.jbutton.button == JOY_A)
231 else if (event.jbutton.button == JOY_B)
232 tux.input.fire = DOWN;
234 case SDL_JOYBUTTONUP:
235 if (event.jbutton.button == JOY_A)
237 else if (event.jbutton.button == JOY_B)
253 /* --- GAME ACTION! --- */
255 int game_action(void)
259 /* (tux_dying || next_level) */
260 if (tux.dying || next_level)
262 /* Tux either died, or reached the end of a level! */
271 /* End of a level! */
275 player_level_begin(&tux);
282 /* No more lives!? */
288 if (score > highscore)
295 } /* if (lives < 0) */
298 /* Either way, (re-)load the (next) level... */
300 player_level_begin(&tux);
302 loadlevel(¤t_level,"default",level);
307 loadlevelgfx(¤t_level);
316 /* Handle bouncy distros: */
318 for (i = 0; i < num_bouncy_distros; i++)
320 bouncy_distro_action(&bouncy_distros[i]);
324 /* Handle broken bricks: */
326 for (i = 0; i < num_broken_bricks; i++)
328 broken_brick_action(&broken_bricks[i]);
332 /* Handle distro counting: */
334 if (counting_distros == YES)
338 if (distro_counter <= 0)
339 counting_distros = -1;
343 /* Handle bouncy bricks: */
345 for (i = 0; i < num_bouncy_bricks; i++)
347 bouncy_brick_action(&bouncy_bricks[i]);
351 /* Handle floating scores: */
353 for (i = 0; i < num_floating_scores; i++)
355 floating_score_action(&floating_scores[i]);
359 /* Handle bullets: */
361 for (i = 0; i < num_bullets; ++i)
363 bullet_action(&bullets[i]);
366 /* Handle upgrades: */
368 for (i = 0; i < num_upgrades; i++)
370 upgrade_action(&upgrades[i]);
374 /* Handle bad guys: */
376 for (i = 0; i < num_bad_guys; i++)
378 badguy_action(&bad_guys[i]);
381 /* Handle all possible collisions. */
387 /* --- GAME DRAW! --- */
395 if (tux.dying && (frame % 4) == 0)
396 clearscreen(255, 255, 255);
399 if (timer_check(&super_bkgd_timer))
400 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
402 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
405 /* Draw background: */
407 for (y = 0; y < 15; ++y)
409 for (x = 0; x < 21; ++x)
411 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
412 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
417 /* (Bouncy bricks): */
419 for (i = 0; i < num_bouncy_bricks; ++i)
421 bouncy_brick_draw(&bouncy_bricks[i]);
427 for (i = 0; i < num_bad_guys; ++i)
429 badguy_draw(&bad_guys[i]);
438 for (i = 0; i < num_bullets; ++i)
440 bullet_draw(&bullets[i]);
443 /* (Floating scores): */
445 for (i = 0; i < num_floating_scores; ++i)
447 floating_score_draw(&floating_scores[i]);
453 for (i = 0; i < num_upgrades; ++i)
455 upgrade_draw(&upgrades[i]);
459 /* (Bouncy distros): */
461 for (i = 0; i < num_bouncy_distros; ++i)
463 bouncy_distro_draw(&bouncy_distros[i]);
467 /* (Broken bricks): */
469 for (i = 0; i < num_broken_bricks; ++i)
471 broken_brick_draw(&broken_bricks[i]);
478 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE, 1);
483 /* (Update it all!) */
490 /* --- GAME LOOP! --- */
495 /*Uint32 last_time, now_time*/
497 timer_type fps_timer, frame_timer;
501 clearscreen(0, 0, 0);
509 menumenu = MENU_GAME;
514 loadlevel(¤t_level,"default",level);
515 loadlevelgfx(¤t_level);
518 highscore = load_hs();
525 /* --- MAIN GAME LOOP!!! --- */
531 timer_init(&fps_timer);
532 timer_init(&frame_timer);
538 /*last_time = SDL_GetTicks();*/
539 if(!timer_check(&frame_timer))
541 timer_start(&frame_timer,25);
548 tux.input.old_fire = tux.input.fire;
553 /* Handle actions: */
555 if(!game_pause && !show_menu)
557 if (game_action() == 0)
559 /* == 0: no more lives */
560 /* == -1: continues */
567 /*Draw the current scene to the screen */
570 /* Time stops in pause mode */
571 if(game_pause || show_menu )
576 /* Pause til next frame: */
578 /*now_time = SDL_GetTicks();
579 if (now_time < last_time + FPS)
580 SDL_Delay(last_time + FPS - now_time);*/
581 /*printf("%d",timer_get_left(&frame_timer));*/
582 /*SDL_Delay(timer_get_left(&frame_timer) );*/
589 if (timer_check(&time_left))
591 /* are we low on time ? */
592 if ((timer_get_left(&time_left) < TIME_WARNING)
593 && (current_music != HURRYUP_MUSIC))
595 current_music = HURRYUP_MUSIC;
596 /* stop the others music, prepare to play the fast music */
605 player_kill(&tux,KILL);
608 /* Keep playing the correct music: */
610 if (!playing_music())
612 play_current_music();
615 /* Calculate frames per second */
618 fps_fps = ((float)1000 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
621 if(!timer_check(&fps_timer))
623 timer_start(&fps_timer,1000);
629 while (!done && !quit);
643 /* Initialize the game stuff: */
652 /* Free music data for this level: */
654 void unloadlevelsong(void)
656 free_music(level_song);
657 free_music(level_song_fast);
662 void loadlevelsong(void)
666 char * song_subtitle;
668 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
669 strlen(current_level.song_title) + 8));
670 sprintf(song_path, "%s/music/%s", DATA_PREFIX, current_level.song_title);
671 level_song = load_song(song_path);
675 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
676 strlen(current_level.song_title) + 8 + 5));
677 song_subtitle = strdup(current_level.song_title);
678 strcpy(strstr(song_subtitle, "."), "\0");
679 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(current_level.song_title, "."));
680 level_song_fast = load_song(song_path);
685 /* Load graphics/sounds shared between all levels: */
687 void loadshared(void)
690 char * herring_song_path; /* for loading herring song*/
694 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
695 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
696 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
698 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
699 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
700 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
702 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
703 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
704 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
706 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
707 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
708 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
711 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
714 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
717 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
720 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
723 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
726 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
729 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
732 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
734 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
737 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
740 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
743 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
745 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
748 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
751 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
754 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
757 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
760 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
763 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
766 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
768 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
771 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
774 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
777 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
779 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
782 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
785 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
788 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
792 texture_load(&ducktux_right ,DATA_PREFIX
793 "/images/shared/ducktux-right.png",
796 texture_load(&ducktux_left ,DATA_PREFIX
797 "/images/shared/ducktux-left.png",
800 texture_load(&skidtux_right ,DATA_PREFIX
801 "/images/shared/skidtux-right.png",
804 texture_load(&skidtux_left ,DATA_PREFIX
805 "/images/shared/skidtux-left.png",
808 texture_load(&duckfiretux_right ,DATA_PREFIX
809 "/images/shared/duckfiretux-right.png",
812 texture_load(&duckfiretux_left ,DATA_PREFIX
813 "/images/shared/duckfiretux-left.png",
816 texture_load(&skidfiretux_right ,DATA_PREFIX
817 "/images/shared/skidfiretux-right.png",
820 texture_load(&skidfiretux_left ,DATA_PREFIX
821 "/images/shared/skidfiretux-left.png",
827 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
829 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
836 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
838 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
841 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
844 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
850 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
851 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
857 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
859 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
865 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
868 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
871 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
874 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
878 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
881 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
884 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
887 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
895 texture_load(&img_bsod_left[0] ,DATA_PREFIX
896 "/images/shared/bsod-left-0.png",
899 texture_load(&img_bsod_left[1] ,DATA_PREFIX
900 "/images/shared/bsod-left-1.png",
903 texture_load(&img_bsod_left[2] ,DATA_PREFIX
904 "/images/shared/bsod-left-2.png",
907 texture_load(&img_bsod_left[3] ,DATA_PREFIX
908 "/images/shared/bsod-left-3.png",
911 texture_load(&img_bsod_right[0] ,DATA_PREFIX
912 "/images/shared/bsod-right-0.png",
915 texture_load(&img_bsod_right[1] ,DATA_PREFIX
916 "/images/shared/bsod-right-1.png",
919 texture_load(&img_bsod_right[2] ,DATA_PREFIX
920 "/images/shared/bsod-right-2.png",
923 texture_load(&img_bsod_right[3] ,DATA_PREFIX
924 "/images/shared/bsod-right-3.png",
927 texture_load(&img_bsod_squished_left ,DATA_PREFIX
928 "/images/shared/bsod-squished-left.png",
931 texture_load(&img_bsod_squished_right ,DATA_PREFIX
932 "/images/shared/bsod-squished-right.png",
935 texture_load(&img_bsod_falling_left ,DATA_PREFIX
936 "/images/shared/bsod-falling-left.png",
939 texture_load(&img_bsod_falling_right ,DATA_PREFIX
940 "/images/shared/bsod-falling-right.png",
946 texture_load(&img_laptop_left[0] ,DATA_PREFIX
947 "/images/shared/laptop-left-0.png",
950 texture_load(&img_laptop_left[1] ,DATA_PREFIX
951 "/images/shared/laptop-left-1.png",
954 texture_load(&img_laptop_left[2] ,DATA_PREFIX
955 "/images/shared/laptop-left-2.png",
958 texture_load(&img_laptop_right[0] ,DATA_PREFIX
959 "/images/shared/laptop-right-0.png",
962 texture_load(&img_laptop_right[1] ,DATA_PREFIX
963 "/images/shared/laptop-right-1.png",
966 texture_load(&img_laptop_right[2] ,DATA_PREFIX
967 "/images/shared/laptop-right-2.png",
970 texture_load(&img_laptop_flat_left ,DATA_PREFIX
971 "/images/shared/laptop-flat-left.png",
974 texture_load(&img_laptop_flat_right ,DATA_PREFIX
975 "/images/shared/laptop-flat-right.png",
978 texture_load(&img_laptop_falling_left ,DATA_PREFIX
979 "/images/shared/laptop-falling-left.png",
982 texture_load(&img_laptop_falling_right ,DATA_PREFIX
983 "/images/shared/laptop-falling-right.png",
989 texture_load(&img_money_left[0] ,DATA_PREFIX
990 "/images/shared/bag-left-0.png",
993 texture_load(&img_money_left[1] ,DATA_PREFIX
994 "/images/shared/bag-left-1.png",
997 texture_load(&img_money_right[0] ,DATA_PREFIX
998 "/images/shared/bag-right-0.png",
1001 texture_load(&img_money_right[1] ,DATA_PREFIX
1002 "/images/shared/bag-right-1.png",
1009 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1010 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1015 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1017 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1024 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1027 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1030 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1033 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1039 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1044 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1048 /* Super background: */
1050 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1054 /* Sound effects: */
1056 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1057 // initialize sounds[i] with the correct pointer's value:
1058 // NULL or something else. And it will be dangerous to
1059 // play with not-initialized pointers.
1060 // This is also true with if (use_music)
1061 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1063 for (i = 0; i < NUM_SOUNDS; i++)
1064 sounds[i] = load_sound(soundfilenames[i]);
1067 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1068 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
1070 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1072 herring_song = load_song(herring_song_path);
1074 free(herring_song_path);
1079 /* Free shared data: */
1081 void unloadshared(void)
1085 for (i = 0; i < 3; i++)
1087 texture_free(&tux_right[i]);
1088 texture_free(&tux_left[i]);
1089 texture_free(&bigtux_right[i]);
1090 texture_free(&bigtux_left[i]);
1093 texture_free(&bigtux_right_jump);
1094 texture_free(&bigtux_left_jump);
1096 for (i = 0; i < 2; i++)
1098 texture_free(&cape_right[i]);
1099 texture_free(&cape_left[i]);
1100 texture_free(&bigcape_right[i]);
1101 texture_free(&bigcape_left[i]);
1104 texture_free(&ducktux_left);
1105 texture_free(&ducktux_right);
1107 texture_free(&skidtux_left);
1108 texture_free(&skidtux_right);
1110 for (i = 0; i < 4; i++)
1112 texture_free(&img_bsod_left[i]);
1113 texture_free(&img_bsod_right[i]);
1116 texture_free(&img_bsod_squished_left);
1117 texture_free(&img_bsod_squished_right);
1119 texture_free(&img_bsod_falling_left);
1120 texture_free(&img_bsod_falling_right);
1122 for (i = 0; i < 3; i++)
1124 texture_free(&img_laptop_left[i]);
1125 texture_free(&img_laptop_right[i]);
1128 texture_free(&img_laptop_flat_left);
1129 texture_free(&img_laptop_flat_right);
1131 texture_free(&img_laptop_falling_left);
1132 texture_free(&img_laptop_falling_right);
1134 for (i = 0; i < 2; i++)
1136 texture_free(&img_money_left[i]);
1137 texture_free(&img_money_right[i]);
1140 texture_free(&img_box_full);
1141 texture_free(&img_box_empty);
1143 texture_free(&img_water);
1144 for (i = 0; i < 3; i++)
1145 texture_free(&img_waves[i]);
1147 texture_free(&img_pole);
1148 texture_free(&img_poletop);
1150 for (i = 0; i < 2; i++)
1151 texture_free(&img_flag[i]);
1153 texture_free(&img_mints);
1154 texture_free(&img_coffee);
1156 for (i = 0; i < 4; i++)
1158 texture_free(&img_distro[i]);
1159 texture_free(&img_cloud[0][i]);
1160 texture_free(&img_cloud[1][i]);
1163 texture_free(&img_golden_herring);
1165 for (i = 0; i < NUM_SOUNDS; i++)
1166 free_chunk(sounds[i]);
1168 /* free the herring song */
1169 free_music( herring_song );
1173 /* Draw a tile on the screen: */
1175 void drawshape(float x, float y, unsigned char c)
1179 if (c == 'X' || c == 'x')
1180 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1181 else if (c == 'Y' || c == 'y')
1182 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1183 else if (c == 'A' || c =='B' || c == '!')
1184 texture_draw(&img_box_full, x, y, NO_UPDATE);
1186 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1187 else if (c >= 'C' && c <= 'F')
1188 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1189 else if (c >= 'c' && c <= 'f')
1190 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1191 else if (c >= 'G' && c <= 'J')
1192 texture_draw(&img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
1193 else if (c >= 'g' && c <= 'j')
1194 texture_draw(&img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
1196 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1198 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1200 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1202 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1206 z = (frame / 2) % 6;
1209 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1211 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1213 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1217 z = (frame / 3) % 3;
1219 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1222 texture_draw(&img_poletop, x, y, NO_UPDATE);
1225 texture_draw(&img_pole, x, y, NO_UPDATE);
1227 /* Mark this as the end position of the level! */
1233 z = (frame / 3) % 2;
1235 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1238 texture_draw(&img_water, x, y, NO_UPDATE);
1242 /* What shape is at some position? */
1244 unsigned char shape(float x, float y)
1253 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1255 c = current_level.tiles[yy][xx];
1265 int issolid(float x, float y)
1267 if (isbrick(x, y) ||
1268 isbrick(x + 31, y) ||
1271 (shape(x, y) == '[' ||
1272 shape(x + 31, y) == '[') ||
1273 (shape(x, y) == '=' ||
1274 shape(x + 31, y) == '=') ||
1275 (shape(x, y) == ']' ||
1276 shape(x + 31, y) == ']') ||
1277 (shape(x, y) == 'A' ||
1278 shape(x + 31, y) == 'A') ||
1279 (shape(x, y) == 'B' ||
1280 shape(x + 31, y) == 'B') ||
1281 (shape(x, y) == '!' ||
1282 shape(x + 31, y) == '!') ||
1283 (shape(x, y) == 'a' ||
1284 shape(x + 31, y) == 'a'))
1293 /* Is it a brick? */
1295 int isbrick(float x, float y)
1297 if (shape(x, y) == 'X' ||
1298 shape(x, y) == 'x' ||
1299 shape(x, y) == 'Y' ||
1311 int isice(float x, float y)
1313 if (shape(x, y) == '#')
1322 /* Is it a full box? */
1324 int isfullbox(float x, float y)
1326 if (shape(x, y) == 'A' ||
1327 shape(x, y) == 'B' ||
1336 /* Break a brick: */
1338 void trybreakbrick(float x, float y)
1342 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1344 /* Get a distro from it: */
1346 add_bouncy_distro(((x + 1) / 32) * 32,
1347 (int)(y / 32) * 32);
1349 if (counting_distros == NO)
1351 counting_distros = YES;
1352 distro_counter = 50;
1355 if (distro_counter <= 0)
1356 level_change(¤t_level,x, y, 'a');
1358 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1359 score = score + SCORE_DISTRO;
1364 /* Get rid of it: */
1366 level_change(¤t_level,x, y,'.');
1370 /* Replace it with broken bits: */
1372 add_broken_brick(((x + 1) / 32) * 32,
1373 (int)(y / 32) * 32);
1376 /* Get some score: */
1378 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1379 score = score + SCORE_BRICK;
1384 /* Bounce a brick: */
1386 void bumpbrick(float x, float y)
1388 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1389 (int)(y / 32) * 32);
1391 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1397 void tryemptybox(float x, float y)
1399 if (isfullbox(x, y))
1401 if (shape(x, y) == 'A')
1403 /* Box with a distro! */
1405 add_bouncy_distro(((x + 1) / 32) * 32,
1406 (int)(y / 32) * 32 - 32);
1408 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1409 score = score + SCORE_DISTRO;
1412 else if (shape(x, y) == 'B')
1414 /* Add an upgrade! */
1416 if (tux.size == SMALL)
1418 /* Tux is small, add mints! */
1420 add_upgrade(((x + 1) / 32) * 32,
1421 (int)(y / 32) * 32 - 32,
1426 /* Tux is big, add coffee: */
1428 add_upgrade(((x + 1) / 32) * 32,
1429 (int)(y / 32) * 32 - 32,
1433 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1435 else if (shape(x, y) == '!')
1437 /* Add a golden herring */
1439 add_upgrade(((x + 1) / 32) * 32,
1440 (int)(y / 32) * 32 - 32,
1444 /* Empty the box: */
1446 level_change(¤t_level,x, y, 'a');
1451 /* Try to grab a distro: */
1453 void trygrabdistro(float x, float y, int bounciness)
1455 if (shape(x, y) == '$')
1457 level_change(¤t_level,x, y, '.');
1458 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1460 if (bounciness == BOUNCE)
1462 add_bouncy_distro(((x + 1) / 32) * 32,
1463 (int)(y / 32) * 32);
1466 score = score + SCORE_DISTRO;
1471 /* Try to bump a bad guy from below: */
1473 void trybumpbadguy(float x, float y)
1480 for (i = 0; i < num_bad_guys; i++)
1482 if (bad_guys[i].base.alive &&
1483 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1484 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1486 if (bad_guys[i].kind == BAD_BSOD ||
1487 bad_guys[i].kind == BAD_LAPTOP)
1489 bad_guys[i].dying = FALLING;
1490 bad_guys[i].base.ym = -8;
1491 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1499 for (i = 0; i < num_upgrades; i++)
1501 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1502 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1503 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1505 upgrades[i].base.xm = -upgrades[i].base.xm;
1506 upgrades[i].base.ym = -8;
1507 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1513 void drawstatus(void)
1517 sprintf(str, "%d", score);
1518 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE, 1);
1519 drawtext(str, 96, 0, letters_gold, NO_UPDATE, 1);
1521 sprintf(str, "%d", highscore);
1522 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE, 1);
1523 drawtext(str, 96, 20, letters_gold, NO_UPDATE, 1);
1525 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1527 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1528 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE, 1);
1529 drawtext(str, 304, 0, letters_gold, NO_UPDATE, 1);
1532 sprintf(str, "%d", distros);
1533 drawtext("DISTROS", screen->h, 0, letters_blue, NO_UPDATE, 1);
1534 drawtext(str, 608, 0, letters_gold, NO_UPDATE, 1);
1536 drawtext("LIVES", screen->h, 20, letters_blue, NO_UPDATE, 1);
1540 drawtext("FPS", screen->h, 40, letters_blue, NO_UPDATE, 1);
1541 sprintf(str, "%f", fps_fps);
1542 if(use_gl) /* FIXME: We need this check as text doesn't work in OpenGl mode. */
1543 printf("%f\n",fps_fps);
1544 drawtext(str, screen->h + 60, 40, letters_gold, NO_UPDATE, 1);
1547 for(i=0; i < tux.lives; ++i)
1549 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1554 void drawendscreen(void)
1558 clearscreen(0, 0, 0);
1560 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE, 1);
1562 sprintf(str, "SCORE: %d", score);
1563 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
1565 sprintf(str, "DISTROS: %d", distros);
1566 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
1572 void drawresultscreen(void)
1576 clearscreen(0, 0, 0);
1578 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE, 1);
1580 sprintf(str, "SCORE: %d", score);
1581 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
1583 sprintf(str, "DISTROS: %d", distros);
1584 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
1593 time_t current_time = time(NULL);
1594 struct tm* time_struct;
1597 time_struct = localtime(¤t_time);
1598 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);
1599 printf("%s",savefile);
1602 fi = fopen(savefile, "wb");
1606 fprintf(stderr, "Warning: I could not open the high score file ");
1611 fwrite(&level,4,1,fi);
1612 fwrite(&score,4,1,fi);
1613 fwrite(&distros,4,1,fi);
1614 fwrite(&tux.base.x,4,1,fi);
1615 fwrite(&tux.base.y,4,1,fi);
1616 fwrite(&scroll_x,4,1,fi);
1617 fwrite(¤t_level.time_left,4,1,fi);
1623 void loadgame(char* filename)
1627 time_t current_time = time(NULL);
1628 struct tm* time_struct;
1630 time_struct = localtime(¤t_time);
1631 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);
1632 printf("%s",savefile);
1635 fi = fopen(savefile, "rb");
1639 fprintf(stderr, "Warning: I could not open the high score file ");
1644 player_level_begin(&tux);
1646 loadlevel(¤t_level,"default",level);
1649 activate_bad_guys();
1651 loadlevelgfx(¤t_level);
1657 fread(&level,4,1,fi);
1658 fread(&score,4,1,fi);
1659 fread(&distros,4,1,fi);
1660 fread(&tux.base.x,4,1,fi);
1661 fread(&tux.base.y,4,1,fi);
1662 fread(&scroll_x,4,1,fi);
1663 fread(¤t_level.time_left,4,1,fi);