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)
119 while (SDL_PollEvent(&event))
122 if (event.type == SDL_QUIT)
124 /* Quit event - quit: */
128 else if (event.type == SDL_KEYDOWN)
132 key = event.key.keysym.sym;
134 /* Check for menu-events, if the menu is shown */
138 if (key == SDLK_ESCAPE)
140 /* Escape: Open/Close the menu: */
149 else if (key == SDLK_RIGHT)
151 tux.input.right = DOWN;
153 else if (key == SDLK_LEFT)
155 tux.input.left = DOWN;
157 else if (key == SDLK_UP)
161 else if (key == SDLK_DOWN)
163 tux.input.down = DOWN;
165 else if (key == SDLK_LCTRL)
167 tux.input.fire = DOWN;
170 else if (event.type == SDL_KEYUP)
174 key = event.key.keysym.sym;
176 if (key == SDLK_RIGHT)
178 tux.input.right = UP;
180 else if (key == SDLK_LEFT)
184 else if (key == SDLK_UP)
188 else if (key == SDLK_DOWN)
192 else if (key == SDLK_LCTRL)
196 else if (key == SDLK_p)
206 else if (key == SDLK_TAB && debug_mode == YES)
208 tux.size = !tux.size;
210 else if (key == SDLK_END && debug_mode == YES)
214 else if (key == SDLK_SPACE && debug_mode == YES)
218 else if (key == SDLK_DELETE && debug_mode == YES)
222 else if (key == SDLK_INSERT && debug_mode == YES)
224 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
228 else if (event.type == SDL_JOYAXISMOTION)
230 if (event.jaxis.axis == JOY_X)
232 if (event.jaxis.value < -256)
233 tux.input.left = DOWN;
237 if (event.jaxis.value > 256)
238 tux.input.right = DOWN;
240 tux.input.right = UP;
242 else if (event.jaxis.axis == JOY_Y)
244 if (event.jaxis.value > 256)
245 tux.input.down = DOWN;
249 /* Handle joystick for the menu */
252 if(tux.input.down == DOWN)
253 menuaction = MN_DOWN;
259 else if (event.type == SDL_JOYBUTTONDOWN)
261 if (event.jbutton.button == JOY_A)
263 else if (event.jbutton.button == JOY_B)
264 tux.input.fire = DOWN;
266 else if (event.type == SDL_JOYBUTTONUP)
268 if (event.jbutton.button == JOY_A)
270 else if (event.jbutton.button == JOY_B)
283 /* --- GAME ACTION! --- */
285 int game_action(void)
289 /* (tux_dying || next_level) */
290 if (tux.dying || next_level)
292 /* Tux either died, or reached the end of a level! */
301 /* End of a level! */
311 /* No more lives!? */
317 if (score > highscore)
323 } /* if (lives < 0) */
326 /* Either way, (re-)load the (next) level... */
328 player_level_begin(&tux);
330 loadlevel(¤t_level,"default",level);
333 loadlevelgfx(¤t_level);
342 /* Handle bouncy distros: */
344 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
346 bouncy_distro_action(&bouncy_distros[i]);
350 /* Handle broken bricks: */
352 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
354 broken_brick_action(&broken_bricks[i]);
358 /* Handle distro counting: */
360 if (counting_distros == YES)
364 if (distro_counter <= 0)
365 counting_distros = -1;
369 /* Handle bouncy bricks: */
371 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
373 bouncy_brick_action(&bouncy_bricks[i]);
377 /* Handle floating scores: */
379 for (i = 0; i < NUM_FLOATING_SCORES; i++)
381 floating_score_action(&floating_scores[i]);
385 /* Handle bullets: */
387 for (i = 0; i < NUM_BULLETS; ++i)
389 bullet_action(&bullets[i]);
393 /* Handle background timer: */
399 /* Handle upgrades: */
401 for (i = 0; i < NUM_UPGRADES; i++)
403 upgrade_action(&upgrades[i]);
404 } /* for (i = 0; i < NUM_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);
432 if (super_bkgd_time == 0)
433 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
435 texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
438 /* Draw background: */
440 for (y = 0; y < 15; y++)
442 for (x = 0; x < 21; x++)
444 drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
445 current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
450 /* (Bouncy bricks): */
452 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
454 bouncy_brick_draw(&bouncy_bricks[i]);
460 for (i = 0; i < NUM_BAD_GUYS; i++)
462 badguy_draw(&bad_guys[i]);
471 for (i = 0; i < NUM_BULLETS; i++)
473 bullet_draw(&bullets[i]);
476 /* (Floating scores): */
478 for (i = 0; i < NUM_FLOATING_SCORES; i++)
480 floating_score_draw(&floating_scores[i]);
486 for (i = 0; i < NUM_UPGRADES; i++)
488 upgrade_draw(&upgrades[i]);
492 /* (Bouncy distros): */
494 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
496 bouncy_distro_draw(&bouncy_distros[i]);
500 /* (Broken bricks): */
502 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
504 broken_brick_draw(&broken_bricks[i]);
511 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE, 1);
516 /* (Update it all!) */
523 /* --- GAME LOOP! --- */
528 Uint32 last_time, now_time;
532 clearscreen(0, 0, 0);
539 menumenu = MENU_GAME;
544 loadlevel(¤t_level,"default",level);
545 loadlevelgfx(¤t_level);
548 highscore = load_hs();
555 /* --- MAIN GAME LOOP!!! --- */
565 last_time = SDL_GetTicks();
571 tux.input.old_fire = tux.input.fire;
576 /* Handle actions: */
578 if(!game_pause && !show_menu)
580 if (game_action() == 0)
582 /* == 0: no more lives */
583 /* == -1: continues */
590 /*Draw the current scene to the screen */
593 /* Time stops in pause mode */
594 if(game_pause || show_menu )
599 /* Pause til next frame: */
601 now_time = SDL_GetTicks();
602 /*if (now_time < last_time + FPS)
603 SDL_Delay(last_time + FPS - now_time);*/
609 if (timer_check(&time_left))
611 /* are we low on time ? */
612 if ((timer_get_left(&time_left) < TIME_WARNING)
613 && (current_music != HURRYUP_MUSIC))
615 current_music = HURRYUP_MUSIC;
616 /* stop the others music, prepare to play the fast music */
625 player_kill(&tux,KILL);
628 /* Keep playing the correct music: */
630 if (!playing_music())
632 play_current_music();
637 while (!done && !quit);
650 /* Initialize the game stuff: */
659 /* Free music data for this level: */
661 void unloadlevelsong(void)
663 free_music(level_song);
664 free_music(level_song_fast);
669 void loadlevelsong(void)
673 char * song_subtitle;
675 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
676 strlen(current_level.song_title) + 8));
677 sprintf(song_path, "%s/music/%s", DATA_PREFIX, current_level.song_title);
678 level_song = load_song(song_path);
682 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
683 strlen(current_level.song_title) + 8 + 5));
684 song_subtitle = strdup(current_level.song_title);
685 strcpy(strstr(song_subtitle, "."), "\0");
686 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(current_level.song_title, "."));
687 level_song_fast = load_song(song_path);
692 /* Load graphics/sounds shared between all levels: */
694 void loadshared(void)
697 char * herring_song_path; /* for loading herring song*/
701 texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA);
702 texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA);
703 texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA);
705 texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA);
706 texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA);
707 texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA);
709 texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA);
710 texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA);
711 texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA);
713 texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA);
714 texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA);
715 texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA);
718 texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png",
721 texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png",
724 texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png",
727 texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png",
730 texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png",
733 texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png",
736 texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png",
739 texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
741 texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png",
744 texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png",
747 texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png",
750 texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
752 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
755 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
758 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
761 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
764 texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
767 texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
770 texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
773 texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
775 texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
778 texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
781 texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
784 texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
786 texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png",
789 texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png",
792 texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png",
795 texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png",
799 texture_load(&ducktux_right ,DATA_PREFIX
800 "/images/shared/ducktux-right.png",
803 texture_load(&ducktux_left ,DATA_PREFIX
804 "/images/shared/ducktux-left.png",
807 texture_load(&skidtux_right ,DATA_PREFIX
808 "/images/shared/skidtux-right.png",
811 texture_load(&skidtux_left ,DATA_PREFIX
812 "/images/shared/skidtux-left.png",
815 texture_load(&duckfiretux_right ,DATA_PREFIX
816 "/images/shared/duckfiretux-right.png",
819 texture_load(&duckfiretux_left ,DATA_PREFIX
820 "/images/shared/duckfiretux-left.png",
823 texture_load(&skidfiretux_right ,DATA_PREFIX
824 "/images/shared/skidfiretux-right.png",
827 texture_load(&skidfiretux_left ,DATA_PREFIX
828 "/images/shared/skidfiretux-left.png",
834 texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png",
836 texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png",
843 texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
845 texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png",
848 texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png",
851 texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png",
857 texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
858 texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png",
864 texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png",
866 texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png",
872 texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png",
875 texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png",
878 texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png",
881 texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png",
885 texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png",
888 texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png",
891 texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png",
894 texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png",
902 texture_load(&img_bsod_left[0] ,DATA_PREFIX
903 "/images/shared/bsod-left-0.png",
906 texture_load(&img_bsod_left[1] ,DATA_PREFIX
907 "/images/shared/bsod-left-1.png",
910 texture_load(&img_bsod_left[2] ,DATA_PREFIX
911 "/images/shared/bsod-left-2.png",
914 texture_load(&img_bsod_left[3] ,DATA_PREFIX
915 "/images/shared/bsod-left-3.png",
918 texture_load(&img_bsod_right[0] ,DATA_PREFIX
919 "/images/shared/bsod-right-0.png",
922 texture_load(&img_bsod_right[1] ,DATA_PREFIX
923 "/images/shared/bsod-right-1.png",
926 texture_load(&img_bsod_right[2] ,DATA_PREFIX
927 "/images/shared/bsod-right-2.png",
930 texture_load(&img_bsod_right[3] ,DATA_PREFIX
931 "/images/shared/bsod-right-3.png",
934 texture_load(&img_bsod_squished_left ,DATA_PREFIX
935 "/images/shared/bsod-squished-left.png",
938 texture_load(&img_bsod_squished_right ,DATA_PREFIX
939 "/images/shared/bsod-squished-right.png",
942 texture_load(&img_bsod_falling_left ,DATA_PREFIX
943 "/images/shared/bsod-falling-left.png",
946 texture_load(&img_bsod_falling_right ,DATA_PREFIX
947 "/images/shared/bsod-falling-right.png",
953 texture_load(&img_laptop_left[0] ,DATA_PREFIX
954 "/images/shared/laptop-left-0.png",
957 texture_load(&img_laptop_left[1] ,DATA_PREFIX
958 "/images/shared/laptop-left-1.png",
961 texture_load(&img_laptop_left[2] ,DATA_PREFIX
962 "/images/shared/laptop-left-2.png",
965 texture_load(&img_laptop_right[0] ,DATA_PREFIX
966 "/images/shared/laptop-right-0.png",
969 texture_load(&img_laptop_right[1] ,DATA_PREFIX
970 "/images/shared/laptop-right-1.png",
973 texture_load(&img_laptop_right[2] ,DATA_PREFIX
974 "/images/shared/laptop-right-2.png",
977 texture_load(&img_laptop_flat_left ,DATA_PREFIX
978 "/images/shared/laptop-flat-left.png",
981 texture_load(&img_laptop_flat_right ,DATA_PREFIX
982 "/images/shared/laptop-flat-right.png",
985 texture_load(&img_laptop_falling_left ,DATA_PREFIX
986 "/images/shared/laptop-falling-left.png",
989 texture_load(&img_laptop_falling_right ,DATA_PREFIX
990 "/images/shared/laptop-falling-right.png",
996 texture_load(&img_money_left[0] ,DATA_PREFIX
997 "/images/shared/bag-left-0.png",
1000 texture_load(&img_money_left[1] ,DATA_PREFIX
1001 "/images/shared/bag-left-1.png",
1004 texture_load(&img_money_right[0] ,DATA_PREFIX
1005 "/images/shared/bag-right-0.png",
1008 texture_load(&img_money_right[1] ,DATA_PREFIX
1009 "/images/shared/bag-right-1.png",
1016 texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
1017 texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
1022 texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
1024 texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png",
1031 texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png",
1034 texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png",
1037 texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png",
1040 texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png",
1046 texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png",
1051 texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png",
1055 /* Super background: */
1057 texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png",
1061 /* Sound effects: */
1063 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1064 // initialize sounds[i] with the correct pointer's value:
1065 // NULL or something else. And it will be dangerous to
1066 // play with not-initialized pointers.
1067 // This is also true with if (use_music)
1068 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1070 for (i = 0; i < NUM_SOUNDS; i++)
1071 sounds[i] = load_sound(soundfilenames[i]);
1074 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
1075 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
1077 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
1079 herring_song = load_song(herring_song_path);
1081 free(herring_song_path);
1086 /* Free shared data: */
1088 void unloadshared(void)
1092 for (i = 0; i < 3; i++)
1094 texture_free(&tux_right[i]);
1095 texture_free(&tux_left[i]);
1096 texture_free(&bigtux_right[i]);
1097 texture_free(&bigtux_left[i]);
1100 texture_free(&bigtux_right_jump);
1101 texture_free(&bigtux_left_jump);
1103 for (i = 0; i < 2; i++)
1105 texture_free(&cape_right[i]);
1106 texture_free(&cape_left[i]);
1107 texture_free(&bigcape_right[i]);
1108 texture_free(&bigcape_left[i]);
1111 texture_free(&ducktux_left);
1112 texture_free(&ducktux_right);
1114 texture_free(&skidtux_left);
1115 texture_free(&skidtux_right);
1117 for (i = 0; i < 4; i++)
1119 texture_free(&img_bsod_left[i]);
1120 texture_free(&img_bsod_right[i]);
1123 texture_free(&img_bsod_squished_left);
1124 texture_free(&img_bsod_squished_right);
1126 texture_free(&img_bsod_falling_left);
1127 texture_free(&img_bsod_falling_right);
1129 for (i = 0; i < 3; i++)
1131 texture_free(&img_laptop_left[i]);
1132 texture_free(&img_laptop_right[i]);
1135 texture_free(&img_laptop_flat_left);
1136 texture_free(&img_laptop_flat_right);
1138 texture_free(&img_laptop_falling_left);
1139 texture_free(&img_laptop_falling_right);
1141 for (i = 0; i < 2; i++)
1143 texture_free(&img_money_left[i]);
1144 texture_free(&img_money_right[i]);
1147 texture_free(&img_box_full);
1148 texture_free(&img_box_empty);
1150 texture_free(&img_water);
1151 for (i = 0; i < 3; i++)
1152 texture_free(&img_waves[i]);
1154 texture_free(&img_pole);
1155 texture_free(&img_poletop);
1157 for (i = 0; i < 2; i++)
1158 texture_free(&img_flag[i]);
1160 texture_free(&img_mints);
1161 texture_free(&img_coffee);
1163 for (i = 0; i < 4; i++)
1165 texture_free(&img_distro[i]);
1166 texture_free(&img_cloud[0][i]);
1167 texture_free(&img_cloud[1][i]);
1170 texture_free(&img_golden_herring);
1172 for (i = 0; i < NUM_SOUNDS; i++)
1173 free_chunk(sounds[i]);
1175 /* free the herring song */
1176 free_music( herring_song );
1180 /* Draw a tile on the screen: */
1182 void drawshape(float x, float y, unsigned char c)
1186 if (c == 'X' || c == 'x')
1187 texture_draw(&img_brick[0], x, y, NO_UPDATE);
1188 else if (c == 'Y' || c == 'y')
1189 texture_draw(&img_brick[1], x, y, NO_UPDATE);
1190 else if (c == 'A' || c =='B' || c == '!')
1191 texture_draw(&img_box_full, x, y, NO_UPDATE);
1193 texture_draw(&img_box_empty, x, y, NO_UPDATE);
1194 else if (c >= 'C' && c <= 'F')
1195 texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1196 else if (c >= 'c' && c <= 'f')
1197 texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1198 else if (c >= 'G' && c <= 'J')
1199 texture_draw(&img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
1200 else if (c >= 'g' && c <= 'j')
1201 texture_draw(&img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
1203 texture_draw(&img_solid[0], x, y, NO_UPDATE);
1205 texture_draw(&img_solid[1], x, y, NO_UPDATE);
1207 texture_draw(&img_solid[2], x, y, NO_UPDATE);
1209 texture_draw(&img_solid[3], x, y, NO_UPDATE);
1213 z = (frame / 2) % 6;
1216 texture_draw(&img_distro[z], x, y, NO_UPDATE);
1218 texture_draw(&img_distro[2], x, y, NO_UPDATE);
1220 texture_draw(&img_distro[1], x, y, NO_UPDATE);
1224 z = (frame / 3) % 3;
1226 texture_draw(&img_waves[z], x, y, NO_UPDATE);
1229 texture_draw(&img_poletop, x, y, NO_UPDATE);
1232 texture_draw(&img_pole, x, y, NO_UPDATE);
1234 /* Mark this as the end position of the level! */
1240 z = (frame / 3) % 2;
1242 texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1245 texture_draw(&img_water, x, y, NO_UPDATE);
1249 /* What shape is at some position? */
1251 unsigned char shape(float x, float y)
1260 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1262 c = current_level.tiles[yy][xx];
1272 int issolid(float x, float y)
1274 if (isbrick(x, y) ||
1275 isbrick(x + 31, y) ||
1278 (shape(x, y) == '[' ||
1279 shape(x + 31, y) == '[') ||
1280 (shape(x, y) == '=' ||
1281 shape(x + 31, y) == '=') ||
1282 (shape(x, y) == ']' ||
1283 shape(x + 31, y) == ']') ||
1284 (shape(x, y) == 'A' ||
1285 shape(x + 31, y) == 'A') ||
1286 (shape(x, y) == 'B' ||
1287 shape(x + 31, y) == 'B') ||
1288 (shape(x, y) == '!' ||
1289 shape(x + 31, y) == '!') ||
1290 (shape(x, y) == 'a' ||
1291 shape(x + 31, y) == 'a'))
1300 /* Is it a brick? */
1302 int isbrick(float x, float y)
1304 if (shape(x, y) == 'X' ||
1305 shape(x, y) == 'x' ||
1306 shape(x, y) == 'Y' ||
1318 int isice(float x, float y)
1320 if (shape(x, y) == '#')
1329 /* Is it a full box? */
1331 int isfullbox(float x, float y)
1333 if (shape(x, y) == 'A' ||
1334 shape(x, y) == 'B' ||
1343 /* Break a brick: */
1345 void trybreakbrick(float x, float y)
1349 if (shape(x, y) == 'x' || shape(x, y) == 'y')
1351 /* Get a distro from it: */
1353 add_bouncy_distro(((x + 1) / 32) * 32,
1354 (int)(y / 32) * 32);
1356 if (counting_distros == NO)
1358 counting_distros = YES;
1359 distro_counter = 50;
1362 if (distro_counter <= 0)
1363 level_change(¤t_level,x, y, 'a');
1365 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1366 score = score + SCORE_DISTRO;
1371 /* Get rid of it: */
1373 level_change(¤t_level,x, y,'.');
1377 /* Replace it with broken bits: */
1379 add_broken_brick(((x + 1) / 32) * 32,
1380 (int)(y / 32) * 32);
1383 /* Get some score: */
1385 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1386 score = score + SCORE_BRICK;
1391 /* Bounce a brick: */
1393 void bumpbrick(float x, float y)
1395 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1396 (int)(y / 32) * 32);
1398 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1404 void tryemptybox(float x, float y)
1406 if (isfullbox(x, y))
1408 if (shape(x, y) == 'A')
1410 /* Box with a distro! */
1412 add_bouncy_distro(((x + 1) / 32) * 32,
1413 (int)(y / 32) * 32 - 32);
1415 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1416 score = score + SCORE_DISTRO;
1419 else if (shape(x, y) == 'B')
1421 /* Add an upgrade! */
1423 if (tux.size == SMALL)
1425 /* Tux is small, add mints! */
1427 add_upgrade(((x + 1) / 32) * 32,
1428 (int)(y / 32) * 32 - 32,
1433 /* Tux is big, add coffee: */
1435 add_upgrade(((x + 1) / 32) * 32,
1436 (int)(y / 32) * 32 - 32,
1440 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1442 else if (shape(x, y) == '!')
1444 /* Add a golden herring */
1446 add_upgrade(((x + 1) / 32) * 32,
1447 (int)(y / 32) * 32 - 32,
1451 /* Empty the box: */
1453 level_change(¤t_level,x, y, 'a');
1458 /* Try to grab a distro: */
1460 void trygrabdistro(float x, float y, int bounciness)
1462 if (shape(x, y) == '$')
1464 level_change(¤t_level,x, y, '.');
1465 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1467 if (bounciness == BOUNCE)
1469 add_bouncy_distro(((x + 1) / 32) * 32,
1470 (int)(y / 32) * 32);
1473 score = score + SCORE_DISTRO;
1478 /* Try to bump a bad guy from below: */
1480 void trybumpbadguy(float x, float y)
1487 for (i = 0; i < NUM_BAD_GUYS; i++)
1489 if (bad_guys[i].alive &&
1490 bad_guys[i].x >= x - 32 && bad_guys[i].x <= x + 32 &&
1491 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
1493 if (bad_guys[i].kind == BAD_BSOD ||
1494 bad_guys[i].kind == BAD_LAPTOP)
1496 bad_guys[i].dying = FALLING;
1497 bad_guys[i].ym = -8;
1498 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1506 for (i = 0; i < NUM_UPGRADES; i++)
1508 if (upgrades[i].alive && upgrades[i].height == 32 &&
1509 upgrades[i].x >= x - 32 && upgrades[i].x <= x + 32 &&
1510 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
1512 upgrades[i].xm = -upgrades[i].xm;
1513 upgrades[i].ym = -8;
1514 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1520 /* Add an upgrade: */
1522 void add_upgrade(float x, float y, int kind)
1528 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
1530 if (!upgrades[i].alive)
1536 upgrades[found].alive = YES;
1537 upgrades[found].kind = kind;
1538 upgrades[found].x = x;
1539 upgrades[found].y = y;
1540 upgrades[found].xm = 2;
1541 upgrades[found].ym = -2;
1542 upgrades[found].height = 0;
1548 void add_bullet(float x, float y, float xm, int dir)
1552 printf("X: %f Y: %f -- YOOYOYOYO\n",x,y);
1556 for (i = 0; i < NUM_BULLETS && found == -1; i++)
1558 if (!bullets[i].alive)
1564 bullets[found].alive = YES;
1568 bullets[found].x = x + 32;
1569 bullets[found].xm = BULLET_XM + xm;
1573 bullets[found].x = x;
1574 bullets[found].xm = -BULLET_XM + xm;
1577 bullets[found].y = y;
1578 bullets[found].ym = BULLET_STARTING_YM;
1580 play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER);
1586 void drawstatus(void)
1590 sprintf(str, "%d", score);
1591 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE, 1);
1592 drawtext(str, 96, 0, letters_gold, NO_UPDATE, 1);
1594 sprintf(str, "%d", highscore);
1595 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE, 1);
1596 drawtext(str, 96, 20, letters_gold, NO_UPDATE, 1);
1598 if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1600 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1601 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE, 1);
1602 drawtext(str, 304, 0, letters_gold, NO_UPDATE, 1);
1605 sprintf(str, "%d", distros);
1606 drawtext("DISTROS", screen->h, 0, letters_blue, NO_UPDATE, 1);
1607 drawtext(str, 608, 0, letters_gold, NO_UPDATE, 1);
1609 drawtext("LIVES", screen->h, 20, letters_blue, NO_UPDATE, 1);
1611 for(i=0; i < tux.lives; ++i)
1613 texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1618 void drawendscreen(void)
1622 clearscreen(0, 0, 0);
1624 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE, 1);
1626 sprintf(str, "SCORE: %d", score);
1627 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
1629 sprintf(str, "DISTROS: %d", distros);
1630 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
1636 void drawresultscreen(void)
1640 clearscreen(0, 0, 0);
1642 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE, 1);
1644 sprintf(str, "SCORE: %d", score);
1645 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
1647 sprintf(str, "DISTROS: %d", distros);
1648 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
1657 time_t current_time = time(NULL);
1658 struct tm* time_struct;
1661 time_struct = localtime(¤t_time);
1662 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);
1663 printf("%s",savefile);
1666 fi = fopen(savefile, "wb");
1670 fprintf(stderr, "Warning: I could not open the high score file ");
1675 fwrite(&level,4,1,fi);
1676 fwrite(&score,4,1,fi);
1677 fwrite(&distros,4,1,fi);
1678 fwrite(&tux.x,4,1,fi);
1679 fwrite(&tux.y,4,1,fi);
1680 fwrite(&scroll_x,4,1,fi);
1681 fwrite(¤t_level.time_left,4,1,fi);
1687 void loadgame(char* filename)
1691 time_t current_time = time(NULL);
1692 struct tm* time_struct;
1694 time_struct = localtime(¤t_time);
1695 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);
1696 printf("%s",savefile);
1699 fi = fopen(savefile, "rb");
1703 fprintf(stderr, "Warning: I could not open the high score file ");
1708 player_level_begin(&tux);
1710 loadlevel(¤t_level,"default",level);
1711 activate_bad_guys();
1713 loadlevelgfx(¤t_level);
1719 fread(&level,4,1,fi);
1720 fread(&score,4,1,fi);
1721 fread(&distros,4,1,fi);
1722 fread(&tux.x,4,1,fi);
1723 fread(&tux.y,4,1,fi);
1724 fread(&scroll_x,4,1,fi);
1725 fread(¤t_level.time_left,4,1,fi);