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];
56 /* Local function prototypes: */
58 void levelintro(void);
60 void loadlevelsong(void);
61 void unloadlevelsong(void);
62 void loadshared(void);
63 void unloadshared(void);
64 void drawstatus(void);
65 void drawendscreen(void);
66 void drawresultscreen(void);
74 sprintf(str, "LEVEL %d", level);
75 drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1);
77 sprintf(str, "%s", current_level.name);
78 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
80 sprintf(str, "TUX x %d", tux.lives);
81 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
89 void start_timers(void)
91 timer_start(&time_left,current_level.time_left*1000);
94 void activate_bad_guys(void)
98 /* Activate bad guys: */
100 for (y = 0; y < 15; y++)
102 for (x = 0; x < current_level.width; x++)
104 if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
106 add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
107 current_level.tiles[y][x] = '.';
114 /* --- GAME EVENT! --- */
116 void game_event(void)
118 while (SDL_PollEvent(&event))
122 case SDL_QUIT: /* Quit event - quit: */
125 case SDL_KEYDOWN: /* A keypress! */
126 key = event.key.keysym.sym;
128 /* Check for menu-events, if the menu is shown */
134 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
144 tux.input.right = DOWN;
147 tux.input.left = DOWN;
153 tux.input.down = DOWN;
156 tux.input.fire = DOWN;
162 case SDL_KEYUP: /* A keyrelease! */
163 key = event.key.keysym.sym;
168 tux.input.right = UP;
192 if(debug_mode == YES)
193 tux.size = !tux.size;
196 if(debug_mode == YES)
200 if(debug_mode == YES)
204 if(debug_mode == YES)
208 if(debug_mode == YES)
209 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
216 case SDL_JOYAXISMOTION:
217 switch(event.jaxis.axis)
220 printf("X: %d\n", event.jaxis.value);
221 if (event.jaxis.value < -1024)
222 tux.input.left = DOWN;
223 else if (event.jaxis.value > 1024)
226 if (event.jaxis.value > 1024)
227 tux.input.right = DOWN;
228 else if (event.jaxis.value < -1024)
229 tux.input.right = UP;
232 if (event.jaxis.value > 1024)
233 tux.input.down = DOWN;
234 else if (event.jaxis.value < -1024)
237 /* Handle joystick for the menu */
240 if(tux.input.down == DOWN)
241 menuaction = MN_DOWN;
250 case SDL_JOYBUTTONDOWN:
251 if (event.jbutton.button == JOY_A)
253 else if (event.jbutton.button == JOY_B)
254 tux.input.fire = DOWN;
256 case SDL_JOYBUTTONUP:
257 if (event.jbutton.button == JOY_A)
259 else if (event.jbutton.button == JOY_B)
275 /* --- GAME ACTION! --- */
277 int game_action(void)
281 /* (tux_dying || next_level) */
282 if (tux.dying || next_level)
284 /* Tux either died, or reached the end of a level! */
293 /* End of a level! */
303 /* No more lives!? */
309 if (score > highscore)
316 } /* if (lives < 0) */
319 /* Either way, (re-)load the (next) level... */
321 player_level_begin(&tux);
323 loadlevel(¤t_level,"default",level);
328 loadlevelgfx(¤t_level);
337 /* Handle bouncy distros: */
339 for (i = 0; i < num_bouncy_distros; i++)
341 bouncy_distro_action(&bouncy_distros[i]);
345 /* Handle broken bricks: */
347 for (i = 0; i < num_broken_bricks; i++)
349 broken_brick_action(&broken_bricks[i]);
353 /* Handle distro counting: */
355 if (counting_distros == YES)
359 if (distro_counter <= 0)
360 counting_distros = -1;
364 /* Handle bouncy bricks: */
366 for (i = 0; i < num_bouncy_bricks; i++)
368 bouncy_brick_action(&bouncy_bricks[i]);
372 /* Handle floating scores: */
374 for (i = 0; i < num_floating_scores; i++)
376 floating_score_action(&floating_scores[i]);
380 /* Handle bullets: */
382 for (i = 0; i < num_bullets; ++i)
384 bullet_action(&bullets[i]);
387 /* Handle upgrades: */
389 for (i = 0; i < num_upgrades; i++)
391 upgrade_action(&upgrades[i]);
395 /* Handle bad guys: */
397 for (i = 0; i < num_bad_guys; i++)
399 badguy_action(&bad_guys[i]);
402 /* Handle all possible collisions. */
408 /* --- GAME DRAW! --- */
416 if (tux.dying && (frame % 4) == 0)
417 clearscreen(255, 255, 255);
420 if (timer_check(&super_bkgd_timer))
421 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
423 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
426 /* Draw background: */
428 for (y = 0; y < 15; y++)
430 for (x = 0; x < 21; x++)
432 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
433 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
438 /* (Bouncy bricks): */
440 for (i = 0; i < num_bouncy_bricks; i++)
442 bouncy_brick_draw(&bouncy_bricks[i]);
448 for (i = 0; i < num_bad_guys; i++)
450 badguy_draw(&bad_guys[i]);
459 for (i = 0; i < num_bullets; i++)
461 bullet_draw(&bullets[i]);
464 /* (Floating scores): */
466 for (i = 0; i < num_floating_scores; i++)
468 floating_score_draw(&floating_scores[i]);
474 for (i = 0; i < num_upgrades; i++)
476 upgrade_draw(&upgrades[i]);
480 /* (Bouncy distros): */
482 for (i = 0; i < num_bouncy_distros; i++)
484 bouncy_distro_draw(&bouncy_distros[i]);
488 /* (Broken bricks): */
490 for (i = 0; i < num_broken_bricks; i++)
492 broken_brick_draw(&broken_bricks[i]);
499 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE, 1);
504 /* (Update it all!) */
511 /* --- GAME LOOP! --- */
516 Uint32 last_time, now_time;
520 clearscreen(0, 0, 0);
528 menumenu = MENU_GAME;
533 loadlevel(¤t_level,"default",level);
534 loadlevelgfx(¤t_level);
537 highscore = load_hs();
544 /* --- MAIN GAME LOOP!!! --- */
554 last_time = SDL_GetTicks();
560 tux.input.old_fire = tux.input.fire;
565 /* Handle actions: */
567 if(!game_pause && !show_menu)
569 if (game_action() == 0)
571 /* == 0: no more lives */
572 /* == -1: continues */
579 /*Draw the current scene to the screen */
582 /* Time stops in pause mode */
583 if(game_pause || show_menu )
588 /* Pause til next frame: */
590 now_time = SDL_GetTicks();
591 /*if (now_time < last_time + FPS)
592 SDL_Delay(last_time + FPS - now_time);*/
598 if (timer_check(&time_left))
600 /* are we low on time ? */
601 if ((timer_get_left(&time_left) < TIME_WARNING)
602 && (current_music != HURRYUP_MUSIC))
604 current_music = HURRYUP_MUSIC;
605 /* stop the others music, prepare to play the fast music */
614 player_kill(&tux,KILL);
617 /* Keep playing the correct music: */
619 if (!playing_music())
621 play_current_music();
626 while (!done && !quit);
640 /* Initialize the game stuff: */
649 /* Free music data for this level: */
651 void unloadlevelsong(void)
653 free_music(level_song);
654 free_music(level_song_fast);
659 void loadlevelsong(void)
663 char * song_subtitle;
665 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
666 strlen(current_level.song_title) + 8));
667 sprintf(song_path, "%s/music/%s", DATA_PREFIX, current_level.song_title);
668 level_song = load_song(song_path);
672 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
673 strlen(current_level.song_title) + 8 + 5));
674 song_subtitle = strdup(current_level.song_title);
675 strcpy(strstr(song_subtitle, "."), "\0");
676 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(current_level.song_title, "."));
677 level_song_fast = load_song(song_path);
682 /* Load graphics/sounds shared between all levels: */
684 void loadshared(void)
687 char * herring_song_path; /* for loading herring song*/
691 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
692 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
693 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
695 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
696 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
697 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
699 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
700 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
701 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
703 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
704 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
705 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
708 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
711 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
714 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
717 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
720 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
723 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
726 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
729 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
731 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
734 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
737 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
740 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
742 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
745 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
748 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
751 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
754 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
757 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
760 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
763 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
765 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
768 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
771 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
774 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
776 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
779 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
782 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
785 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
789 texture_load(&ducktux_right ,DATA_PREFIX
790 "/images/shared/ducktux-right.png",
793 texture_load(&ducktux_left ,DATA_PREFIX
794 "/images/shared/ducktux-left.png",
797 texture_load(&skidtux_right ,DATA_PREFIX
798 "/images/shared/skidtux-right.png",
801 texture_load(&skidtux_left ,DATA_PREFIX
802 "/images/shared/skidtux-left.png",
805 texture_load(&duckfiretux_right ,DATA_PREFIX
806 "/images/shared/duckfiretux-right.png",
809 texture_load(&duckfiretux_left ,DATA_PREFIX
810 "/images/shared/duckfiretux-left.png",
813 texture_load(&skidfiretux_right ,DATA_PREFIX
814 "/images/shared/skidfiretux-right.png",
817 texture_load(&skidfiretux_left ,DATA_PREFIX
818 "/images/shared/skidfiretux-left.png",
824 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
826 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
833 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
835 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
838 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
841 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
847 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
848 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
854 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
856 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
862 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
865 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
868 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
871 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
875 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
878 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
881 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
884 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
892 texture_load(&img_bsod_left[0] ,DATA_PREFIX
893 "/images/shared/bsod-left-0.png",
896 texture_load(&img_bsod_left[1] ,DATA_PREFIX
897 "/images/shared/bsod-left-1.png",
900 texture_load(&img_bsod_left[2] ,DATA_PREFIX
901 "/images/shared/bsod-left-2.png",
904 texture_load(&img_bsod_left[3] ,DATA_PREFIX
905 "/images/shared/bsod-left-3.png",
908 texture_load(&img_bsod_right[0] ,DATA_PREFIX
909 "/images/shared/bsod-right-0.png",
912 texture_load(&img_bsod_right[1] ,DATA_PREFIX
913 "/images/shared/bsod-right-1.png",
916 texture_load(&img_bsod_right[2] ,DATA_PREFIX
917 "/images/shared/bsod-right-2.png",
920 texture_load(&img_bsod_right[3] ,DATA_PREFIX
921 "/images/shared/bsod-right-3.png",
924 texture_load(&img_bsod_squished_left ,DATA_PREFIX
925 "/images/shared/bsod-squished-left.png",
928 texture_load(&img_bsod_squished_right ,DATA_PREFIX
929 "/images/shared/bsod-squished-right.png",
932 texture_load(&img_bsod_falling_left ,DATA_PREFIX
933 "/images/shared/bsod-falling-left.png",
936 texture_load(&img_bsod_falling_right ,DATA_PREFIX
937 "/images/shared/bsod-falling-right.png",
943 texture_load(&img_laptop_left[0] ,DATA_PREFIX
944 "/images/shared/laptop-left-0.png",
947 texture_load(&img_laptop_left[1] ,DATA_PREFIX
948 "/images/shared/laptop-left-1.png",
951 texture_load(&img_laptop_left[2] ,DATA_PREFIX
952 "/images/shared/laptop-left-2.png",
955 texture_load(&img_laptop_right[0] ,DATA_PREFIX
956 "/images/shared/laptop-right-0.png",
959 texture_load(&img_laptop_right[1] ,DATA_PREFIX
960 "/images/shared/laptop-right-1.png",
963 texture_load(&img_laptop_right[2] ,DATA_PREFIX
964 "/images/shared/laptop-right-2.png",
967 texture_load(&img_laptop_flat_left ,DATA_PREFIX
968 "/images/shared/laptop-flat-left.png",
971 texture_load(&img_laptop_flat_right ,DATA_PREFIX
972 "/images/shared/laptop-flat-right.png",
975 texture_load(&img_laptop_falling_left ,DATA_PREFIX
976 "/images/shared/laptop-falling-left.png",
979 texture_load(&img_laptop_falling_right ,DATA_PREFIX
980 "/images/shared/laptop-falling-right.png",
986 texture_load(&img_money_left[0] ,DATA_PREFIX
987 "/images/shared/bag-left-0.png",
990 texture_load(&img_money_left[1] ,DATA_PREFIX
991 "/images/shared/bag-left-1.png",
994 texture_load(&img_money_right[0] ,DATA_PREFIX
995 "/images/shared/bag-right-0.png",
998 texture_load(&img_money_right[1] ,DATA_PREFIX
999 "/images/shared/bag-right-1.png",
1006 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1007 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1012 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1014 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1021 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1024 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1027 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1030 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1036 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1041 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1045 /* Super background: */
1047 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1051 /* Sound effects: */
1053 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1054 // initialize sounds[i] with the correct pointer's value:
1055 // NULL or something else. And it will be dangerous to
1056 // play with not-initialized pointers.
1057 // This is also true with if (use_music)
1058 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1060 for (i = 0; i < NUM_SOUNDS; i++)
1061 sounds[i] = load_sound(soundfilenames[i]);
1064 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1065 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
1067 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1069 herring_song = load_song(herring_song_path);
1071 free(herring_song_path);
1076 /* Free shared data: */
1078 void unloadshared(void)
1082 for (i = 0; i < 3; i++)
1084 texture_free(&tux_right[i]);
1085 texture_free(&tux_left[i]);
1086 texture_free(&bigtux_right[i]);
1087 texture_free(&bigtux_left[i]);
1090 texture_free(&bigtux_right_jump);
1091 texture_free(&bigtux_left_jump);
1093 for (i = 0; i < 2; i++)
1095 texture_free(&cape_right[i]);
1096 texture_free(&cape_left[i]);
1097 texture_free(&bigcape_right[i]);
1098 texture_free(&bigcape_left[i]);
1101 texture_free(&ducktux_left);
1102 texture_free(&ducktux_right);
1104 texture_free(&skidtux_left);
1105 texture_free(&skidtux_right);
1107 for (i = 0; i < 4; i++)
1109 texture_free(&img_bsod_left[i]);
1110 texture_free(&img_bsod_right[i]);
1113 texture_free(&img_bsod_squished_left);
1114 texture_free(&img_bsod_squished_right);
1116 texture_free(&img_bsod_falling_left);
1117 texture_free(&img_bsod_falling_right);
1119 for (i = 0; i < 3; i++)
1121 texture_free(&img_laptop_left[i]);
1122 texture_free(&img_laptop_right[i]);
1125 texture_free(&img_laptop_flat_left);
1126 texture_free(&img_laptop_flat_right);
1128 texture_free(&img_laptop_falling_left);
1129 texture_free(&img_laptop_falling_right);
1131 for (i = 0; i < 2; i++)
1133 texture_free(&img_money_left[i]);
1134 texture_free(&img_money_right[i]);
1137 texture_free(&img_box_full);
1138 texture_free(&img_box_empty);
1140 texture_free(&img_water);
1141 for (i = 0; i < 3; i++)
1142 texture_free(&img_waves[i]);
1144 texture_free(&img_pole);
1145 texture_free(&img_poletop);
1147 for (i = 0; i < 2; i++)
1148 texture_free(&img_flag[i]);
1150 texture_free(&img_mints);
1151 texture_free(&img_coffee);
1153 for (i = 0; i < 4; i++)
1155 texture_free(&img_distro[i]);
1156 texture_free(&img_cloud[0][i]);
1157 texture_free(&img_cloud[1][i]);
1160 texture_free(&img_golden_herring);
1162 for (i = 0; i < NUM_SOUNDS; i++)
1163 free_chunk(sounds[i]);
1165 /* free the herring song */
1166 free_music( herring_song );
1170 /* Draw a tile on the screen: */
1172 void drawshape(float x, float y, unsigned char c)
1176 if (c == 'X' || c == 'x')
1177 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1178 else if (c == 'Y' || c == 'y')
1179 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1180 else if (c == 'A' || c =='B' || c == '!')
1181 texture_draw(&img_box_full, x, y, NO_UPDATE);
1183 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1184 else if (c >= 'C' && c <= 'F')
1185 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1186 else if (c >= 'c' && c <= 'f')
1187 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1188 else if (c >= 'G' && c <= 'J')
1189 texture_draw(&img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
1190 else if (c >= 'g' && c <= 'j')
1191 texture_draw(&img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
1193 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1195 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1197 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1199 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1203 z = (frame / 2) % 6;
1206 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1208 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1210 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1214 z = (frame / 3) % 3;
1216 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1219 texture_draw(&img_poletop, x, y, NO_UPDATE);
1222 texture_draw(&img_pole, x, y, NO_UPDATE);
1224 /* Mark this as the end position of the level! */
1230 z = (frame / 3) % 2;
1232 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1235 texture_draw(&img_water, x, y, NO_UPDATE);
1239 /* What shape is at some position? */
1241 unsigned char shape(float x, float y)
1250 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1252 c = current_level.tiles[yy][xx];
1262 int issolid(float x, float y)
1264 if (isbrick(x, y) ||
1265 isbrick(x + 31, y) ||
1268 (shape(x, y) == '[' ||
1269 shape(x + 31, y) == '[') ||
1270 (shape(x, y) == '=' ||
1271 shape(x + 31, y) == '=') ||
1272 (shape(x, y) == ']' ||
1273 shape(x + 31, y) == ']') ||
1274 (shape(x, y) == 'A' ||
1275 shape(x + 31, y) == 'A') ||
1276 (shape(x, y) == 'B' ||
1277 shape(x + 31, y) == 'B') ||
1278 (shape(x, y) == '!' ||
1279 shape(x + 31, y) == '!') ||
1280 (shape(x, y) == 'a' ||
1281 shape(x + 31, y) == 'a'))
1290 /* Is it a brick? */
1292 int isbrick(float x, float y)
1294 if (shape(x, y) == 'X' ||
1295 shape(x, y) == 'x' ||
1296 shape(x, y) == 'Y' ||
1308 int isice(float x, float y)
1310 if (shape(x, y) == '#')
1319 /* Is it a full box? */
1321 int isfullbox(float x, float y)
1323 if (shape(x, y) == 'A' ||
1324 shape(x, y) == 'B' ||
1333 /* Break a brick: */
1335 void trybreakbrick(float x, float y)
1339 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1341 /* Get a distro from it: */
1343 add_bouncy_distro(((x + 1) / 32) * 32,
1344 (int)(y / 32) * 32);
1346 if (counting_distros == NO)
1348 counting_distros = YES;
1349 distro_counter = 50;
1352 if (distro_counter <= 0)
1353 level_change(¤t_level,x, y, 'a');
1355 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1356 score = score + SCORE_DISTRO;
1361 /* Get rid of it: */
1363 level_change(¤t_level,x, y,'.');
1367 /* Replace it with broken bits: */
1369 add_broken_brick(((x + 1) / 32) * 32,
1370 (int)(y / 32) * 32);
1373 /* Get some score: */
1375 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1376 score = score + SCORE_BRICK;
1381 /* Bounce a brick: */
1383 void bumpbrick(float x, float y)
1385 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1386 (int)(y / 32) * 32);
1388 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1394 void tryemptybox(float x, float y)
1396 if (isfullbox(x, y))
1398 if (shape(x, y) == 'A')
1400 /* Box with a distro! */
1402 add_bouncy_distro(((x + 1) / 32) * 32,
1403 (int)(y / 32) * 32 - 32);
1405 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1406 score = score + SCORE_DISTRO;
1409 else if (shape(x, y) == 'B')
1411 /* Add an upgrade! */
1413 if (tux.size == SMALL)
1415 /* Tux is small, add mints! */
1417 add_upgrade(((x + 1) / 32) * 32,
1418 (int)(y / 32) * 32 - 32,
1423 /* Tux is big, add coffee: */
1425 add_upgrade(((x + 1) / 32) * 32,
1426 (int)(y / 32) * 32 - 32,
1430 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1432 else if (shape(x, y) == '!')
1434 /* Add a golden herring */
1436 add_upgrade(((x + 1) / 32) * 32,
1437 (int)(y / 32) * 32 - 32,
1441 /* Empty the box: */
1443 level_change(¤t_level,x, y, 'a');
1448 /* Try to grab a distro: */
1450 void trygrabdistro(float x, float y, int bounciness)
1452 if (shape(x, y) == '$')
1454 level_change(¤t_level,x, y, '.');
1455 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1457 if (bounciness == BOUNCE)
1459 add_bouncy_distro(((x + 1) / 32) * 32,
1460 (int)(y / 32) * 32);
1463 score = score + SCORE_DISTRO;
1468 /* Try to bump a bad guy from below: */
1470 void trybumpbadguy(float x, float y)
1477 for (i = 0; i < num_bad_guys; i++)
1479 if (bad_guys[i].base.alive &&
1480 bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1481 bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1483 if (bad_guys[i].kind == BAD_BSOD ||
1484 bad_guys[i].kind == BAD_LAPTOP)
1486 bad_guys[i].dying = FALLING;
1487 bad_guys[i].base.ym = -8;
1488 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1496 for (i = 0; i < num_upgrades; i++)
1498 if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1499 upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1500 upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1502 upgrades[i].base.xm = -upgrades[i].base.xm;
1503 upgrades[i].base.ym = -8;
1504 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1510 void drawstatus(void)
1514 sprintf(str, "%d", score);
1515 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE, 1);
1516 drawtext(str, 96, 0, letters_gold, NO_UPDATE, 1);
1518 sprintf(str, "%d", highscore);
1519 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE, 1);
1520 drawtext(str, 96, 20, letters_gold, NO_UPDATE, 1);
1522 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1524 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1525 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE, 1);
1526 drawtext(str, 304, 0, letters_gold, NO_UPDATE, 1);
1529 sprintf(str, "%d", distros);
1530 drawtext("DISTROS", screen->h, 0, letters_blue, NO_UPDATE, 1);
1531 drawtext(str, 608, 0, letters_gold, NO_UPDATE, 1);
1533 drawtext("LIVES", screen->h, 20, letters_blue, NO_UPDATE, 1);
1535 for(i=0; i < tux.lives; ++i)
1537 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1542 void drawendscreen(void)
1546 clearscreen(0, 0, 0);
1548 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE, 1);
1550 sprintf(str, "SCORE: %d", score);
1551 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
1553 sprintf(str, "DISTROS: %d", distros);
1554 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
1560 void drawresultscreen(void)
1564 clearscreen(0, 0, 0);
1566 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE, 1);
1568 sprintf(str, "SCORE: %d", score);
1569 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
1571 sprintf(str, "DISTROS: %d", distros);
1572 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
1581 time_t current_time = time(NULL);
1582 struct tm* time_struct;
1585 time_struct = localtime(¤t_time);
1586 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);
1587 printf("%s",savefile);
1590 fi = fopen(savefile, "wb");
1594 fprintf(stderr, "Warning: I could not open the high score file ");
1599 fwrite(&level,4,1,fi);
1600 fwrite(&score,4,1,fi);
1601 fwrite(&distros,4,1,fi);
1602 fwrite(&tux.base.x,4,1,fi);
1603 fwrite(&tux.base.y,4,1,fi);
1604 fwrite(&scroll_x,4,1,fi);
1605 fwrite(¤t_level.time_left,4,1,fi);
1611 void loadgame(char* filename)
1615 time_t current_time = time(NULL);
1616 struct tm* time_struct;
1618 time_struct = localtime(¤t_time);
1619 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);
1620 printf("%s",savefile);
1623 fi = fopen(savefile, "rb");
1627 fprintf(stderr, "Warning: I could not open the high score file ");
1632 player_level_begin(&tux);
1634 loadlevel(¤t_level,"default",level);
1637 activate_bad_guys();
1639 loadlevelgfx(¤t_level);
1645 fread(&level,4,1,fi);
1646 fread(&score,4,1,fi);
1647 fread(&distros,4,1,fi);
1648 fread(&tux.base.x,4,1,fi);
1649 fread(&tux.base.y,4,1,fi);
1650 fread(&scroll_x,4,1,fi);
1651 fread(¤t_level.time_left,4,1,fi);