7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 29, 2003
23 #include <sys/types.h>
32 #include "high_scores.h"
38 /* extern variables */
40 extern char* soundfilenames[NUM_SOUNDS];
42 /* Local variables: */
44 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
45 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
46 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
47 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
48 super_bkgd_time, time_left, tux_invincible_time, endpos,
49 counting_distros, distro_counter;
50 int bkgd_red, bkgd_green, bkgd_blue, level_width;
51 int left, right, up, down, fire, old_fire;
52 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
53 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
54 SDL_Surface * img_bkgd[2][4];
55 SDL_Surface * img_golden_herring;
56 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
57 * img_laptop_left[3], * img_laptop_right[3],
58 * img_money_left[2], * img_money_right[2];
59 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
60 * img_bsod_falling_left, * img_bsod_falling_right,
61 * img_laptop_flat_left, * img_laptop_flat_right,
62 * img_laptop_falling_left, * img_laptop_falling_right;
63 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
64 * img_super_bkgd, * img_bullet, * img_red_glow;
65 SDL_Surface * img_cloud[2][4];
66 SDL_Surface * tux_life,
67 * tux_right[3], * tux_left[3],
68 * bigtux_right[3], * bigtux_left[3],
69 * bigtux_right_jump, * bigtux_left_jump,
70 * ducktux_right, * ducktux_left,
71 * skidtux_right, * skidtux_left,
72 * firetux_right[3], * firetux_left[3],
73 * bigfiretux_right[3], * bigfiretux_left[3],
74 * bigfiretux_right_jump, * bigfiretux_left_jump,
75 * duckfiretux_right, * duckfiretux_left,
76 * skidfiretux_right, * skidfiretux_left,
77 * cape_right[2], * cape_left[2],
78 * bigcape_right[2], * bigcape_left[2];
82 unsigned char * tiles[15];
83 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
84 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
85 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
86 bad_guy_type bad_guys[NUM_BAD_GUYS];
87 floating_score_type floating_scores[NUM_FLOATING_SCORES];
88 upgrade_type upgrades[NUM_UPGRADES];
89 bullet_type bullets[NUM_BULLETS];
96 /* Local function prototypes: */
100 void loadlevelgfx(void);
101 void loadlevelsong(void);
102 void unloadlevelgfx(void);
103 void unloadlevelsong(void);
104 void loadshared(void);
105 void unloadshared(void);
106 void drawshape(int x, int y, unsigned char c);
107 unsigned char shape(int x, int y, int sx);
108 int issolid(int x, int y, int sx);
109 int isbrick(int x, int y, int sx);
110 int isice(int x, int y, int sx);
111 int isfullbox(int x, int y, int sx);
112 void change(int x, int y, int sx, unsigned char c);
113 void trybreakbrick(int x, int y, int sx);
114 void bumpbrick(int x, int y, int sx);
115 void tryemptybox(int x, int y, int sx);
116 void trygrabdistro(int x, int y, int sx, int bounciness);
117 void add_bouncy_distro(int x, int y);
118 void add_broken_brick(int x, int y);
119 void add_broken_brick_piece(int x, int y, int xm, int ym);
120 void add_bouncy_brick(int x, int y);
121 void add_bad_guy(int x, int y, int kind);
122 void add_score(int x, int y, int s);
123 void trybumpbadguy(int x, int y, int sx);
124 void add_upgrade(int x, int y, int kind);
125 void killtux(int mode);
126 void add_bullet(int x, int y, int dir, int xm);
127 void drawendscreen(void);
128 void drawresultscreen(void);
130 /* --- GAME EVENT! --- */
132 void game_event(void)
135 while (SDL_PollEvent(&event))
138 if (event.type == SDL_QUIT)
140 /* Quit event - quit: */
144 else if (event.type == SDL_KEYDOWN)
148 key = event.key.keysym.sym;
150 /* Check for menu-events, if the menu is shown */
154 if (key == SDLK_ESCAPE)
156 /* Escape: Open/Close the menu: */
165 else if (key == SDLK_RIGHT)
169 else if (key == SDLK_LEFT)
173 else if (key == SDLK_UP)
177 else if (key == SDLK_DOWN)
181 else if (key == SDLK_LCTRL)
186 else if (event.type == SDL_KEYUP)
190 key = event.key.keysym.sym;
192 if (key == SDLK_RIGHT)
196 else if (key == SDLK_LEFT)
200 else if (key == SDLK_UP)
204 else if (key == SDLK_DOWN)
208 else if (key == SDLK_LCTRL)
212 else if (key == SDLK_p)
222 else if (key == SDLK_TAB && debug_mode == YES)
224 tux_size = !tux_size;
226 else if (key == SDLK_END && debug_mode == YES)
230 else if (key == SDLK_SPACE && debug_mode == YES)
236 else if (event.type == SDL_JOYAXISMOTION)
238 if (event.jaxis.axis == JOY_X)
240 if (event.jaxis.value < -256)
245 if (event.jaxis.value > 256)
250 else if (event.jaxis.axis == JOY_Y)
252 if (event.jaxis.value > 256)
257 /* Handle joystick for the menu */
261 menuaction = MN_DOWN;
267 else if (event.type == SDL_JOYBUTTONDOWN)
269 if (event.jbutton.button == JOY_A)
271 else if (event.jbutton.button == JOY_B)
274 else if (event.type == SDL_JOYBUTTONUP)
276 if (event.jbutton.button == JOY_A)
278 else if (event.jbutton.button == JOY_B)
291 /* --- GAME ACTION! --- */
293 int game_action(void)
297 /* --- HANDLE TUX! --- */
299 /* Handle key and joystick state: */
301 if (!(tux_dying || next_level))
303 if (right == DOWN && left == UP)
307 if (tux_xm < -SKID_XM && !tux_skidding &&
310 tux_skidding = SKID_TIME;
312 play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
318 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
326 if (tux_dir == RIGHT)
328 /* Facing the direction we're jumping? Go full-speed: */
332 tux_xm = tux_xm + WALK_SPEED;
334 if (tux_xm > MAX_WALK_XM)
335 tux_xm = MAX_WALK_XM;
337 else if (fire == DOWN)
339 tux_xm = tux_xm + RUN_SPEED;
341 if (tux_xm > MAX_RUN_XM)
347 /* Not facing the direction we're jumping?
350 tux_xm = tux_xm + WALK_SPEED / 2;
352 if (tux_xm > MAX_WALK_XM / 2)
353 tux_xm = MAX_WALK_XM / 2;
357 else if (left == DOWN && right == UP)
361 if (tux_xm > SKID_XM && !tux_skidding &&
364 tux_skidding = SKID_TIME;
365 play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
370 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
380 /* Facing the direction we're jumping? Go full-speed: */
384 tux_xm = tux_xm - WALK_SPEED;
386 if (tux_xm < -MAX_WALK_XM)
387 tux_xm = -MAX_WALK_XM;
389 else if (fire == DOWN)
391 tux_xm = tux_xm - RUN_SPEED;
393 if (tux_xm < -MAX_RUN_XM)
394 tux_xm = -MAX_RUN_XM;
399 /* Not facing the direction we're jumping?
402 tux_xm = tux_xm - WALK_SPEED / 2;
404 if (tux_xm < -MAX_WALK_XM / 2)
405 tux_xm = -MAX_WALK_XM / 2;
413 if (tux_x >= endpos && endpos != 0)
423 if (jump_counter == 0)
427 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
430 /* If they're not on the ground, or are currently moving
431 vertically, don't jump! */
433 jump_counter = MAX_JUMP_COUNT;
437 /* Make sure we're not standing back up into a solid! */
439 if (tux_size == SMALL || tux_duck == NO ||
440 !issolid(tux_x, tux_y, scroll_x))
444 if (tux_size == SMALL)
445 play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
447 play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
453 /* Keep jumping for a while: */
455 if (jump_counter < MAX_JUMP_COUNT)
457 tux_ym = tux_ym - JUMP_SPEED;
467 if (fire == DOWN && old_fire == UP && tux_got_coffee)
469 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
482 if (tux_size == BIG && tux_duck == YES)
484 /* Make sure we're not standing back up into a solid! */
486 if (!issolid(tux_x, tux_y - 32, scroll_x))
492 } /* (tux_dying || next_level) */
495 /* Tux either died, or reached the end of a level! */
504 /* End of a level! */
512 tux_ym = tux_ym + GRAVITY;
520 /* No more lives!? */
526 if (score > highscore)
533 } /* if (lives < 0) */
536 /* Either way, (re-)load the (next) level... */
547 tux_x = tux_x + tux_xm;
548 tux_y = tux_y + tux_ym;
551 /* Keep tux in bounds: */
554 else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
556 scroll_x = scroll_x - ( 160 - tux_x);
563 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
565 /* Scroll the screen in past center: */
567 scroll_x = scroll_x + (tux_x - 320);
570 if (scroll_x > ((level_width * 32) - 640))
571 scroll_x = ((level_width * 32) - 640);
573 else if (tux_x > 608)
575 /* ... unless there's no more to scroll! */
585 if (issolid(tux_x, tux_y + 31, scroll_x) &&
586 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
588 while (issolid(tux_x, tux_y + 31, scroll_x))
599 if (issolid(tux_x, tux_y, scroll_x) &&
600 !issolid(tux_x - tux_xm, tux_y, scroll_x))
602 while (issolid(tux_x, tux_y, scroll_x))
613 if (issolid(tux_x, tux_y + 31, scroll_x))
615 /* Set down properly: */
617 while (issolid(tux_x, tux_y + 31, scroll_x))
626 /* Reset score multiplier (for mutli-hits): */
629 score_multiplier = 1;
639 /* Bump into things: */
641 if (issolid(tux_x, tux_y, scroll_x) ||
642 (tux_size == BIG && !tux_duck &&
643 (issolid(tux_x, tux_y - 32, scroll_x))))
645 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
646 (tux_size == SMALL || tux_duck ||
647 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
649 tux_x = tux_x - tux_xm;
652 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
653 (tux_size == SMALL || tux_duck ||
654 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
662 /* Break bricks and empty boxes: */
666 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
667 isfullbox(tux_x, tux_y - 32, scroll_x))
669 trygrabdistro(tux_x, tux_y - 64, scroll_x,
671 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
673 if (isfullbox(tux_x, tux_y - 32,
676 bumpbrick(tux_x, tux_y - 32,
680 trybreakbrick(tux_x, tux_y - 32, scroll_x);
681 tryemptybox(tux_x, tux_y - 32, scroll_x);
684 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
685 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
687 trygrabdistro(tux_x + 31,
691 trybumpbadguy(tux_x + 31,
695 if (isfullbox(tux_x + 31, tux_y - 32,
698 bumpbrick(tux_x + 31, tux_y - 32,
702 trybreakbrick(tux_x + 31,
705 tryemptybox(tux_x + 31,
712 if (isbrick(tux_x, tux_y, scroll_x) ||
713 isfullbox(tux_x, tux_y, scroll_x))
715 trygrabdistro(tux_x, tux_y - 32, scroll_x,
717 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
718 if (isfullbox(tux_x, tux_y, scroll_x))
719 bumpbrick(tux_x, tux_y, scroll_x);
720 trybreakbrick(tux_x, tux_y, scroll_x);
721 tryemptybox(tux_x, tux_y, scroll_x);
724 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
725 isfullbox(tux_x + 31, tux_y, scroll_x))
727 trygrabdistro(tux_x + 31,
731 trybumpbadguy(tux_x + 31,
734 if (isfullbox(tux_x + 31, tux_y, scroll_x))
735 bumpbrick(tux_x + 31, tux_y, scroll_x);
736 trybreakbrick(tux_x + 31, tux_y, scroll_x);
737 tryemptybox(tux_x + 31, tux_y, scroll_x);
743 /* It's a brick and we're small, make the brick
744 bounce, and grab any distros above it: */
746 if (isbrick(tux_x, tux_y, scroll_x) ||
747 isfullbox(tux_x, tux_y, scroll_x))
749 trygrabdistro(tux_x, tux_y - 32, scroll_x,
751 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
752 bumpbrick(tux_x, tux_y, scroll_x);
753 tryemptybox(tux_x, tux_y, scroll_x);
756 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
757 isfullbox(tux_x + 31, tux_y, scroll_x))
759 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
761 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
762 bumpbrick(tux_x + 31, tux_y, scroll_x);
763 tryemptybox(tux_x + 31, tux_y, scroll_x);
767 /* Get a distro from a brick? */
769 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
770 shape(tux_x, tux_y, scroll_x) == 'y')
772 add_bouncy_distro(((tux_x + scroll_x + 1)
776 if (counting_distros == NO)
778 counting_distros = YES;
779 distro_counter = 100;
782 if (distro_counter <= 0)
783 change(tux_x, tux_y, scroll_x, 'a');
785 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
786 score = score + SCORE_DISTRO;
789 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
790 shape(tux_x + 31, tux_y, scroll_x) == 'y')
792 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
796 if (counting_distros == NO)
798 counting_distros = YES;
799 distro_counter = 100;
802 if (distro_counter <= 0)
803 change(tux_x + 31, tux_y, scroll_x, 'a');
805 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
806 score = score + SCORE_DISTRO;
814 tux_y = (tux_y / 32) * 32 + 30;
820 tux_y = (tux_y / 32) * 32 - 32;
825 jump_counter = MAX_JUMP_COUNT;
835 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
836 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
838 if (tux_size == BIG && !tux_duck)
840 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
841 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
846 /* Enough distros for a One-up? */
848 if (distros >= DISTROS_LIFEUP)
850 distros = distros - DISTROS_LIFEUP;
851 if(lives < MAX_LIVES)
853 /*We want to hear the sound even, if MAX_LIVES is reached*/
854 play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
858 /* Keep in-bounds, vertically: */
862 else if (tux_y > 480)
868 /* Slow down horizontally: */
872 if (right == UP && left == UP)
874 if (isice(tux_x, tux_y + 32, scroll_x) ||
875 !issolid(tux_x, tux_y + 32, scroll_x))
877 /* Slowly on ice or in air: */
886 /* Quickly, otherwise: */
893 /* Drop vertically: */
895 if (!issolid(tux_x, tux_y + 32, scroll_x))
897 tux_ym = tux_ym + GRAVITY;
909 /* ---- DONE HANDLING TUX! --- */
912 /* Handle bouncy distros: */
914 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
916 if (bouncy_distros[i].alive)
918 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
920 bouncy_distros[i].ym++;
922 if (bouncy_distros[i].ym >= 0)
923 bouncy_distros[i].alive = NO;
928 /* Handle broken bricks: */
930 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
932 if (broken_bricks[i].alive)
934 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
935 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
937 broken_bricks[i].ym++;
939 if (broken_bricks[i].ym >= 0)
940 broken_bricks[i].alive = NO;
945 /* Handle distro counting: */
947 if (counting_distros == YES)
951 if (distro_counter <= 0)
952 counting_distros = -1;
956 /* Handle bouncy bricks: */
958 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
960 if (bouncy_bricks[i].alive)
962 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
963 bouncy_bricks[i].offset_m);
967 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
968 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
973 if (bouncy_bricks[i].offset == 0)
974 bouncy_bricks[i].alive = NO;
979 /* Handle floating scores: */
981 for (i = 0; i < NUM_FLOATING_SCORES; i++)
983 if (floating_scores[i].alive)
985 floating_scores[i].y = floating_scores[i].y - 2;
986 floating_scores[i].timer--;
988 if (floating_scores[i].timer <= 0)
989 floating_scores[i].alive = NO;
994 /* Handle bullets: */
996 for (i = 0; i < NUM_BULLETS; i++)
998 if (bullets[i].alive)
1000 bullets[i].x = bullets[i].x + bullets[i].xm;
1001 bullets[i].y = bullets[i].y + bullets[i].ym;
1003 if (issolid(bullets[i].x, bullets[i].y, 0))
1005 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1006 bullets[i].alive = NO;
1009 if (bullets[i].ym >= 0)
1011 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1013 bullets[i].ym = -bullets[i].ym;
1017 bullets[i].ym = bullets[i].ym + GRAVITY;
1019 if (bullets[i].x < scroll_x ||
1020 bullets[i].x > scroll_x + 640)
1022 bullets[i].alive = NO;
1027 if (bullets[i].alive)
1029 for (j = 0; j < NUM_BAD_GUYS; j++)
1031 if (bad_guys[j].alive && !bad_guys[j].dying)
1033 if (bullets[i].x >= bad_guys[j].x - 4 &&
1034 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1035 bullets[i].y >= bad_guys[j].y - 4 &&
1036 bullets[i].y <= bad_guys[j].y + 32 + 4)
1038 /* Kill the bad guy! */
1040 bullets[i].alive = 0;
1041 bad_guys[j].dying = FALLING;
1042 bad_guys[j].ym = -8;
1045 /* Gain some points: */
1047 if (bad_guys[j].kind == BAD_BSOD)
1049 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1050 50 * score_multiplier);
1052 else if (bad_guys[j].kind == BAD_LAPTOP)
1054 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1055 25 * score_multiplier);
1059 /* Play death sound: */
1060 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1068 /* Handle background timer: */
1070 if (super_bkgd_time)
1074 /* Handle invincibility timer: */
1077 if (tux_invincible_time > 50)
1079 tux_invincible_time--;
1082 if (!playing_music())
1083 play_music( herring_song, 1 );
1087 if (current_music == HERRING_MUSIC)
1089 /* stop the herring_song, now play the level_song ! */
1090 current_music = LEVEL_MUSIC;
1094 if (!playing_music())
1096 if (time_left <= TIME_WARNING)
1097 play_music( level_song_fast, 1 );
1099 play_music( level_song, 1 );
1102 if (tux_invincible_time > 0)
1103 tux_invincible_time--;
1107 /* Handle upgrades: */
1109 for (i = 0; i < NUM_UPGRADES; i++)
1111 if (upgrades[i].alive)
1113 if (upgrades[i].height < 32)
1117 upgrades[i].height++;
1123 if (upgrades[i].kind == UPGRADE_MINTS ||
1124 upgrades[i].kind == UPGRADE_HERRING)
1126 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1127 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1129 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1130 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1132 if (upgrades[i].ym > 0)
1134 if (upgrades[i].kind == UPGRADE_MINTS)
1138 else if (upgrades[i].kind == UPGRADE_HERRING)
1140 upgrades[i].ym = -24;
1143 upgrades[i].y = (upgrades[i].y / 32) * 32;
1147 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1149 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1151 upgrades[i].xm = -upgrades[i].xm;
1156 /* Off the screen? Kill it! */
1158 if (upgrades[i].x < scroll_x)
1159 upgrades[i].alive = NO;
1162 /* Did the player grab it? */
1164 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1165 tux_x + scroll_x <= upgrades[i].x + 32 &&
1166 tux_y >= upgrades[i].y - 32 &&
1167 tux_y <= upgrades[i].y + 32)
1169 /* Remove the upgrade: */
1171 upgrades[i].alive = NO;
1174 /* Affect the player: */
1176 if (upgrades[i].kind == UPGRADE_MINTS)
1178 play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
1180 super_bkgd_time = 8;
1182 else if (upgrades[i].kind == UPGRADE_COFFEE)
1184 play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
1185 tux_got_coffee = YES;
1186 super_bkgd_time = 4;
1188 else if (upgrades[i].kind == UPGRADE_HERRING)
1190 play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
1191 tux_invincible_time = TUX_INVINCIBLE_TIME;
1192 super_bkgd_time = 4;
1193 /* play the herring song ^^ */
1194 current_music = HERRING_MUSIC;
1195 if (playing_music())
1197 play_music( herring_song, 1 );
1205 /* Handle bad guys: */
1207 for (i = 0; i < NUM_BAD_GUYS; i++)
1209 if (bad_guys[i].alive)
1211 if (bad_guys[i].seen)
1213 if (bad_guys[i].kind == BAD_BSOD)
1215 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1217 /* Move left/right: */
1219 if (bad_guys[i].dying == NO ||
1220 bad_guys[i].dying == FALLING)
1222 if (bad_guys[i].dir == RIGHT)
1223 bad_guys[i].x = bad_guys[i].x + 4;
1224 else if (bad_guys[i].dir == LEFT)
1225 bad_guys[i].x = bad_guys[i].x - 4;
1229 /* Move vertically: */
1231 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1234 /* Bump into things horizontally: */
1236 if (!bad_guys[i].dying)
1238 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1239 bad_guys[i].dir = !bad_guys[i].dir;
1243 /* Bump into other bad guys: */
1245 for (j = 0; j < NUM_BAD_GUYS; j++)
1247 if (j != i && bad_guys[j].alive &&
1248 !bad_guys[j].dying && !bad_guys[i].dying &&
1249 bad_guys[i].x >= bad_guys[j].x - 32 &&
1250 bad_guys[i].x <= bad_guys[j].x + 32 &&
1251 bad_guys[i].y >= bad_guys[j].y - 32 &&
1252 bad_guys[i].y <= bad_guys[j].y + 32)
1254 bad_guys[i].dir = !bad_guys[i].dir;
1259 /* Fall if we get off the ground: */
1261 if (bad_guys[i].dying != FALLING)
1263 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1264 bad_guys[i].ym < MAX_YM)
1266 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1272 if (bad_guys[i].ym > 0)
1274 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1280 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1282 if (bad_guys[i].y > 480)
1283 bad_guys[i].alive = NO;
1285 else if (bad_guys[i].kind == BAD_LAPTOP)
1287 /* --- LAPTOP MONSTER: --- */
1289 /* Move left/right: */
1291 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1293 if (bad_guys[i].dying == NO ||
1294 bad_guys[i].dying == FALLING)
1296 if (bad_guys[i].dir == RIGHT)
1297 bad_guys[i].x = bad_guys[i].x + 4;
1298 else if (bad_guys[i].dir == LEFT)
1299 bad_guys[i].x = bad_guys[i].x - 4;
1302 else if (bad_guys[i].mode == KICK)
1304 if (bad_guys[i].dir == RIGHT)
1305 bad_guys[i].x = bad_guys[i].x + 16;
1306 else if (bad_guys[i].dir == LEFT)
1307 bad_guys[i].x = bad_guys[i].x - 16;
1311 /* Move vertically: */
1313 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1316 /* Bump into things horizontally: */
1318 if (!bad_guys[i].dying)
1320 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1322 bad_guys[i].dir = !bad_guys[i].dir;
1324 if (bad_guys[i].mode == KICK)
1326 /* handle stereo sound */
1327 if (tux_x + scroll_x > bad_guys[i].x)
1328 play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
1329 else if (tux_x + scroll_x < bad_guys[i].x)
1330 play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
1332 play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
1338 /* Bump into other bad guys: */
1340 for (j = 0; j < NUM_BAD_GUYS; j++)
1342 if (j != i && bad_guys[j].alive &&
1343 !bad_guys[j].dying && !bad_guys[i].dying &&
1344 bad_guys[i].x >= bad_guys[j].x - 32 &&
1345 bad_guys[i].x <= bad_guys[j].x + 32 &&
1346 bad_guys[i].y >= bad_guys[j].y - 32 &&
1347 bad_guys[i].y <= bad_guys[j].y + 32)
1349 if (bad_guys[i].mode != KICK)
1350 bad_guys[i].dir = !bad_guys[i].dir;
1353 /* We're in kick mode, kill the other guy: */
1355 bad_guys[j].dying = FALLING;
1356 bad_guys[j].ym = -8;
1357 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1359 add_score(bad_guys[i].x - scroll_x,
1360 bad_guys[i].y, 100);
1366 /* Fall if we get off the ground: */
1368 if (bad_guys[i].dying != FALLING)
1370 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1371 bad_guys[i].ym < MAX_YM)
1373 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1379 if (bad_guys[i].ym > 0)
1381 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1387 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1389 if (bad_guys[i].y > 480)
1390 bad_guys[i].alive = NO;
1392 else if (bad_guys[i].kind == BAD_MONEY)
1394 /* --- MONEY BAGS: --- */
1397 /* Move vertically: */
1399 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1402 /* Fall if we get off the ground: */
1404 if (bad_guys[i].dying != FALLING)
1406 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1408 if (bad_guys[i].ym < MAX_YM)
1410 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1417 if (bad_guys[i].ym > 0)
1419 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1420 bad_guys[i].ym = -MAX_YM;
1425 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1427 if (bad_guys[i].y > 480)
1428 bad_guys[i].alive = NO;
1430 else if (bad_guys[i].kind == -1)
1434 /* Kill it if the player jumped on it: */
1436 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1437 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1438 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1439 tux_y >= bad_guys[i].y - 32 &&
1440 tux_y <= bad_guys[i].y - 8
1444 if (bad_guys[i].kind == BAD_BSOD)
1446 bad_guys[i].dying = SQUISHED;
1447 bad_guys[i].timer = 16;
1448 tux_ym = -KILL_BOUNCE_YM;
1450 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1451 50 * score_multiplier);
1453 play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
1455 else if (bad_guys[i].kind == BAD_LAPTOP)
1457 if (bad_guys[i].mode != FLAT)
1461 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1462 bad_guys[i].mode = FLAT;
1464 bad_guys[i].timer = 64;
1472 bad_guys[i].mode = KICK;
1473 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1475 if (tux_x + scroll_x <= bad_guys[i].x)
1476 bad_guys[i].dir = RIGHT;
1478 bad_guys[i].dir = LEFT;
1480 bad_guys[i].timer = 8;
1483 tux_ym = -KILL_BOUNCE_YM;
1485 add_score(bad_guys[i].x - scroll_x,
1487 25 * score_multiplier);
1489 /* play_sound(sounds[SND_SQUISH]); */
1491 else if (bad_guys[i].kind == -1)
1498 /* Hurt the player if he just touched it: */
1500 if (!bad_guys[i].dying && !tux_dying &&
1502 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1503 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1504 tux_y >= bad_guys[i].y - 32 &&
1505 tux_y <= bad_guys[i].y + 32)
1507 if (bad_guys[i].mode == FLAT)
1511 bad_guys[i].mode = KICK;
1512 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1514 if (tux_x + scroll_x <= bad_guys[i].x)
1516 bad_guys[i].dir = RIGHT;
1517 bad_guys[i].x = bad_guys[i].x + 16;
1521 bad_guys[i].dir = LEFT;
1522 bad_guys[i].x = bad_guys[i].x - 16;
1525 bad_guys[i].timer = 8;
1527 else if (bad_guys[i].mode == KICK)
1529 if (tux_y < bad_guys[i].y - 16 &&
1530 bad_guys[i].timer == 0)
1532 /* Step on (stop being kicked) */
1534 bad_guys[i].mode = FLAT;
1535 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1536 bad_guys[i].timer = 64;
1540 /* Hurt if you get hit by kicked laptop: */
1542 if (bad_guys[i].timer == 0)
1544 if (tux_invincible_time == 0)
1550 bad_guys[i].dying = FALLING;
1551 bad_guys[i].ym = -8;
1552 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1559 if (tux_invincible_time == 0)
1565 bad_guys[i].dying = FALLING;
1566 bad_guys[i].ym = -8;
1567 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1573 /* Handle mode timer: */
1575 if (bad_guys[i].mode == FLAT)
1577 bad_guys[i].timer--;
1579 if (bad_guys[i].timer <= 0)
1580 bad_guys[i].mode = NORMAL;
1582 else if (bad_guys[i].mode == KICK)
1584 if (bad_guys[i].timer > 0)
1585 bad_guys[i].timer--;
1589 /* Handle dying timer: */
1591 if (bad_guys[i].dying == SQUISHED)
1593 bad_guys[i].timer--;
1596 /* Remove it if time's up: */
1598 if (bad_guys[i].timer <= 0)
1599 bad_guys[i].alive = NO;
1603 /* Remove if it's far off the screen: */
1605 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1606 bad_guys[i].alive = NO;
1610 /* Once it's on screen, it's activated! */
1612 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1613 bad_guys[i].seen = YES;
1619 /* Handle skidding: */
1621 if (tux_skidding > 0)
1629 /* --- GAME DRAW! --- */
1637 if (tux_dying && (frame % 4) == 0)
1638 clearscreen(255, 255, 255);
1641 if (super_bkgd_time == 0)
1642 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1644 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1648 /* Draw background: */
1650 for (y = 0; y < 15; y++)
1652 for (x = 0; x < 21; x++)
1654 drawshape(x * 32 - (scroll_x % 32), y * 32,
1655 tiles[y][x + (scroll_x / 32)]);
1660 /* (Bouncy bricks): */
1662 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1664 if (bouncy_bricks[i].alive)
1666 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1667 bouncy_bricks[i].x <= scroll_x + 640)
1669 dest.x = bouncy_bricks[i].x - scroll_x;
1670 dest.y = bouncy_bricks[i].y;
1674 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1679 drawshape(bouncy_bricks[i].x - scroll_x,
1680 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1681 bouncy_bricks[i].shape);
1689 for (i = 0; i < NUM_BAD_GUYS; i++)
1691 if (bad_guys[i].alive &&
1692 bad_guys[i].x > scroll_x - 32 &&
1693 bad_guys[i].x < scroll_x + 640)
1695 if (bad_guys[i].kind == BAD_BSOD)
1697 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1699 if (bad_guys[i].dying == NO)
1703 if (bad_guys[i].dir == LEFT)
1705 drawimage(img_bsod_left[(frame / 5) % 4],
1706 bad_guys[i].x - scroll_x,
1712 drawimage(img_bsod_right[(frame / 5) % 4],
1713 bad_guys[i].x - scroll_x,
1718 else if (bad_guys[i].dying == FALLING)
1722 if (bad_guys[i].dir == LEFT)
1724 drawimage(img_bsod_falling_left,
1725 bad_guys[i].x - scroll_x,
1731 drawimage(img_bsod_falling_right,
1732 bad_guys[i].x - scroll_x,
1737 else if (bad_guys[i].dying == SQUISHED)
1739 /* Dying - Squished: */
1741 if (bad_guys[i].dir == LEFT)
1743 drawimage(img_bsod_squished_left,
1744 bad_guys[i].x - scroll_x,
1750 drawimage(img_bsod_squished_right,
1751 bad_guys[i].x - scroll_x,
1757 else if (bad_guys[i].kind == BAD_LAPTOP)
1759 /* --- LAPTOP MONSTER: --- */
1761 if (bad_guys[i].dying == NO)
1765 if (bad_guys[i].mode == NORMAL)
1769 if (bad_guys[i].dir == LEFT)
1771 drawimage(img_laptop_left[(frame / 5) % 3],
1772 bad_guys[i].x - scroll_x,
1778 drawimage(img_laptop_right[(frame / 5) % 3],
1779 bad_guys[i].x - scroll_x,
1788 if (bad_guys[i].dir == LEFT)
1790 drawimage(img_laptop_flat_left,
1791 bad_guys[i].x - scroll_x,
1797 drawimage(img_laptop_flat_right,
1798 bad_guys[i].x - scroll_x,
1804 else if (bad_guys[i].dying == FALLING)
1808 if (bad_guys[i].dir == LEFT)
1810 drawimage(img_laptop_falling_left,
1811 bad_guys[i].x - scroll_x,
1817 drawimage(img_laptop_falling_right,
1818 bad_guys[i].x - scroll_x,
1824 else if (bad_guys[i].kind == BAD_MONEY)
1826 if (bad_guys[i].ym > -16)
1828 if (bad_guys[i].dir == LEFT)
1830 drawimage(img_money_left[0],
1831 bad_guys[i].x - scroll_x,
1837 drawimage(img_money_right[0],
1838 bad_guys[i].x - scroll_x,
1845 if (bad_guys[i].dir == LEFT)
1847 drawimage(img_money_left[1],
1848 bad_guys[i].x - scroll_x,
1854 drawimage(img_money_right[1],
1855 bad_guys[i].x - scroll_x,
1861 else if (bad_guys[i].kind == -1)
1869 if (right == UP && left == UP)
1876 if ((fire == DOWN && (frame % 2) == 0) ||
1878 tux_frame_main = (tux_frame_main + 1) % 4;
1880 tux_frame = tux_frame_main;
1887 if (tux_safe == 0 || (frame % 2) == 0)
1889 if (tux_size == SMALL)
1891 if (tux_invincible_time)
1895 if (tux_dir == RIGHT)
1897 drawimage(cape_right[frame % 2],
1903 drawimage(cape_left[frame % 2],
1910 if (!tux_got_coffee)
1912 if (tux_dir == RIGHT)
1914 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1918 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1923 /* Tux got coffee! */
1925 if (tux_dir == RIGHT)
1927 drawimage(firetux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1931 drawimage(firetux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1937 if (tux_invincible_time)
1941 if (tux_dir == RIGHT)
1943 drawimage(bigcape_right[frame % 2],
1944 tux_x - 8 - 16, tux_y - 32,
1949 drawimage(bigcape_left[frame % 2],
1950 tux_x - 8, tux_y - 32,
1955 if (!tux_got_coffee)
1961 if (!jumping || tux_ym > 0)
1963 if (tux_dir == RIGHT)
1965 drawimage(bigtux_right[tux_frame],
1966 tux_x - 8, tux_y - 32,
1971 drawimage(bigtux_left[tux_frame],
1972 tux_x - 8, tux_y - 32,
1978 if (tux_dir == RIGHT)
1980 drawimage(bigtux_right_jump,
1981 tux_x - 8, tux_y - 32,
1986 drawimage(bigtux_left_jump,
1987 tux_x - 8, tux_y - 32,
1994 if (tux_dir == RIGHT)
1996 drawimage(skidtux_right,
1997 tux_x - 8, tux_y - 32,
2002 drawimage(skidtux_left,
2003 tux_x - 8, tux_y - 32,
2010 if (tux_dir == RIGHT)
2012 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2017 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2024 /* Tux has coffee! */
2030 if (!jumping || tux_ym > 0)
2032 if (tux_dir == RIGHT)
2034 drawimage(bigfiretux_right[tux_frame],
2035 tux_x - 8, tux_y - 32,
2040 drawimage(bigfiretux_left[tux_frame],
2041 tux_x - 8, tux_y - 32,
2047 if (tux_dir == RIGHT)
2049 drawimage(bigfiretux_right_jump,
2050 tux_x - 8, tux_y - 32,
2055 drawimage(bigfiretux_left_jump,
2056 tux_x - 8, tux_y - 32,
2063 if (tux_dir == RIGHT)
2065 drawimage(skidfiretux_right,
2066 tux_x - 8, tux_y - 32,
2071 drawimage(skidfiretux_left,
2072 tux_x - 8, tux_y - 32,
2079 if (tux_dir == RIGHT)
2081 drawimage(duckfiretux_right, tux_x - 8, tux_y - 16,
2086 drawimage(duckfiretux_left, tux_x - 8, tux_y - 16,
2097 for (i = 0; i < NUM_BULLETS; i++)
2099 if (bullets[i].alive &&
2100 bullets[i].x >= scroll_x - 4 &&
2101 bullets[i].x <= scroll_x + 640)
2103 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2109 /* (Floating scores): */
2111 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2113 if (floating_scores[i].alive)
2115 sprintf(str, "%d", floating_scores[i].value);
2117 floating_scores[i].x + 16 - strlen(str) * 8,
2118 floating_scores[i].y,
2119 letters_gold, NO_UPDATE, 1);
2126 for (i = 0; i < NUM_UPGRADES; i++)
2128 if (upgrades[i].alive)
2130 if (upgrades[i].height < 32)
2134 dest.x = upgrades[i].x - scroll_x;
2135 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2137 dest.h = upgrades[i].height;
2142 src.h = upgrades[i].height;
2144 if (upgrades[i].kind == UPGRADE_MINTS)
2145 SDL_BlitSurface(img_mints, &src, screen, &dest);
2146 else if (upgrades[i].kind == UPGRADE_COFFEE)
2147 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2148 else if (upgrades[i].kind == UPGRADE_HERRING)
2149 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2153 if (upgrades[i].kind == UPGRADE_MINTS)
2155 drawimage(img_mints,
2156 upgrades[i].x - scroll_x, upgrades[i].y,
2159 else if (upgrades[i].kind == UPGRADE_COFFEE)
2161 drawimage(img_coffee,
2162 upgrades[i].x - scroll_x, upgrades[i].y,
2165 else if (upgrades[i].kind == UPGRADE_HERRING)
2167 drawimage(img_golden_herring,
2168 upgrades[i].x - scroll_x, upgrades[i].y,
2176 /* (Bouncy distros): */
2178 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2180 if (bouncy_distros[i].alive)
2182 drawimage(img_distro[0],
2183 bouncy_distros[i].x - scroll_x,
2184 bouncy_distros[i].y,
2190 /* (Broken bricks): */
2192 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2194 if (broken_bricks[i].alive)
2196 src.x = rand() % 16;
2197 src.y = rand() % 16;
2201 dest.x = broken_bricks[i].x - scroll_x;
2202 dest.y = broken_bricks[i].y;
2206 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2213 sprintf(str, "%d", score);
2214 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE, 1);
2215 drawtext(str, 96, 0, letters_gold, NO_UPDATE, 1);
2217 sprintf(str, "%d", highscore);
2218 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE, 1);
2219 drawtext(str, 96, 20, letters_gold, NO_UPDATE, 1);
2221 if (time_left >= TIME_WARNING || (frame % 10) < 5)
2223 sprintf(str, "%d", time_left);
2224 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE, 1);
2225 drawtext(str, 304, 0, letters_gold, NO_UPDATE, 1);
2228 sprintf(str, "%d", distros);
2229 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE, 1);
2230 drawtext(str, 608, 0, letters_gold, NO_UPDATE, 1);
2232 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE, 1);
2234 for(i=0; i < lives; ++i)
2236 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2240 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE, 1);
2245 /* (Update it all!) */
2252 /* --- GAME LOOP! --- */
2257 Uint32 last_time, now_time;
2261 clearscreen(0, 0, 0);
2265 /* Init the game: */
2268 menumenu = MENU_GAME;
2274 highscore = load_hs();
2277 /* --- MAIN GAME LOOP!!! --- */
2289 last_time = SDL_GetTicks();
2293 /* Handle events: */
2299 /* Handle actions: */
2301 if(!game_pause && !show_menu)
2303 if (game_action() == 0)
2305 /* == 0: no more lives */
2306 /* == -1: continues */
2313 /*Draw the current scene to the screen */
2316 /* Keep playing music: */
2319 if (!playing_music())
2321 switch (current_music)
2324 if (time_left <= TIME_WARNING)
2325 play_music(level_song_fast, 1);
2327 play_music(level_song, 1);
2330 play_music(herring_song, 1);
2332 case HURRYUP_MUSIC: // keep the compiler happy
2333 case NO_MUSIC: // keep the compiler happy for the moment :-)
2339 /* Time stops in pause mode */
2340 if(game_pause || show_menu )
2345 /* Pause til next frame: */
2347 now_time = SDL_GetTicks();
2348 if (now_time < last_time + FPS)
2349 SDL_Delay(last_time + FPS - now_time);
2354 if ((frame % 10) == 0 && time_left > 0)
2358 /* Stop the music; it will start again, faster! */
2359 if (time_left == TIME_WARNING)
2366 while (!done && !quit);
2368 if (playing_music())
2379 /* Initialize the game stuff: */
2391 /* Load data for this level: */
2393 void loadlevel(void)
2404 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2405 bouncy_distros[i].alive = NO;
2407 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2408 broken_bricks[i].alive = NO;
2410 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2411 bouncy_bricks[i].alive = NO;
2413 for (i = 0; i < NUM_BAD_GUYS; i++)
2414 bad_guys[i].alive = NO;
2416 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2417 floating_scores[i].alive = NO;
2419 for (i = 0; i < NUM_UPGRADES; i++)
2420 upgrades[i].alive = NO;
2422 for (i = 0; i < NUM_BULLETS; i++)
2423 bullets[i].alive = NO;
2426 /* Load data file: */
2428 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2429 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2430 fi = fopen(filename, "r");
2441 /* Load header info: */
2446 strcpy(levelname, str);
2447 levelname[strlen(levelname)-1] = '\0';
2451 strcpy(leveltheme, str);
2452 leveltheme[strlen(leveltheme)-1] = '\0';
2456 /* (Time to beat level) */
2458 time_left = atoi(str);
2460 /* (Song file for this level) */
2461 fgets(str, sizeof(song_title), fi);
2462 strcpy(song_title, str);
2463 song_title[strlen(song_title)-1] = '\0';
2467 /* (Level background color) */
2469 bkgd_red = atoi(str);
2471 bkgd_green= atoi(str);
2473 bkgd_blue = atoi(str);
2477 level_width = atoi(str);
2480 /* Allocate some space for the line-reading! */
2482 line = (char *) malloc(sizeof(char) * (level_width + 5));
2485 fprintf(stderr, "Couldn't allocate space to load level data!");
2490 /* Load the level lines: */
2492 for (y = 0; y < 15; y++)
2494 if(fgets(line, level_width + 5, fi) == NULL)
2496 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2499 line[strlen(line) - 1] = '\0';
2500 tiles[y] = strdup(line);
2506 /* Activate bad guys: */
2508 for (y = 0; y < 15; y++)
2510 for (x = 0; x < level_width; x++)
2512 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2514 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2529 tux_got_coffee = NO;
2530 tux_invincible_time = 0;
2534 tux_safe = TUX_SAFE_TIME;
2550 score_multiplier = 1;
2551 super_bkgd_time = 0;
2553 counting_distros = NO;
2558 /* set current song/music */
2559 current_music = LEVEL_MUSIC;
2563 clearscreen(0, 0, 0);
2565 sprintf(str, "LEVEL %d", level);
2566 drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1);
2568 sprintf(str, "%s", levelname);
2569 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
2571 sprintf(str, "TUX x %d", lives);
2572 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
2582 /* Load a level-specific graphic... */
2584 SDL_Surface * load_level_image(char * file, int use_alpha)
2588 snprintf(fname, 1024, "%s/images/themes/%s/%s", DATA_PREFIX, leveltheme, file);
2590 return(load_image(fname, use_alpha));
2594 /* Load graphics: */
2596 void loadlevelgfx(void)
2598 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2599 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2601 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2602 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2603 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2604 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2606 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2607 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2608 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2609 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2611 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2612 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2613 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2614 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2620 void loadlevelsong(void)
2624 char * song_subtitle;
2626 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2627 strlen(song_title) + 8));
2628 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2629 level_song = load_song(song_path);
2633 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2634 strlen(song_title) + 8 + 5));
2635 song_subtitle = strdup(song_title);
2636 strcpy(strstr(song_subtitle, "."), "\0");
2637 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(song_title, "."));
2638 level_song_fast = load_song(song_path);
2639 free(song_subtitle);
2644 /* Free graphics data for this level: */
2646 void unloadlevelgfx(void)
2650 for (i = 0; i < 2; i++)
2652 SDL_FreeSurface(img_brick[i]);
2654 for (i = 0; i < 4; i++)
2656 SDL_FreeSurface(img_solid[i]);
2657 SDL_FreeSurface(img_bkgd[0][i]);
2658 SDL_FreeSurface(img_bkgd[1][i]);
2663 /* Free music data for this level: */
2665 void unloadlevelsong(void)
2667 free_music(level_song);
2671 /* Load graphics/sounds shared between all levels: */
2673 void loadshared(void)
2676 char * herring_song_path; /* for loading herring song*/
2680 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2683 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2686 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2689 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2692 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2695 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2698 firetux_right[0] = load_image(DATA_PREFIX "/images/shared/firetux-right-0.png",
2701 firetux_right[1] = load_image(DATA_PREFIX "/images/shared/firetux-right-1.png",
2704 firetux_right[2] = load_image(DATA_PREFIX "/images/shared/firetux-right-2.png",
2707 firetux_left[0] = load_image(DATA_PREFIX "/images/shared/firetux-left-0.png",
2710 firetux_left[1] = load_image(DATA_PREFIX "/images/shared/firetux-left-1.png",
2713 firetux_left[2] = load_image(DATA_PREFIX "/images/shared/firetux-left-2.png",
2716 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2719 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2722 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2725 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2728 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2731 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2734 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2738 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2740 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2743 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2746 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2750 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2753 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2757 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2761 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2765 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2768 bigfiretux_right[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
2771 bigfiretux_right[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
2774 bigfiretux_right[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
2777 bigfiretux_right_jump =
2778 load_image(DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
2780 bigfiretux_left[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
2783 bigfiretux_left[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
2786 bigfiretux_left[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
2789 bigfiretux_left_jump =
2790 load_image(DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
2793 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2797 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2801 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2805 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2809 ducktux_right = load_image(DATA_PREFIX
2810 "/images/shared/ducktux-right.png",
2813 ducktux_left = load_image(DATA_PREFIX
2814 "/images/shared/ducktux-left.png",
2817 skidtux_right = load_image(DATA_PREFIX
2818 "/images/shared/skidtux-right.png",
2821 skidtux_left = load_image(DATA_PREFIX
2822 "/images/shared/skidtux-left.png",
2825 duckfiretux_right = load_image(DATA_PREFIX
2826 "/images/shared/duckfiretux-right.png",
2829 duckfiretux_left = load_image(DATA_PREFIX
2830 "/images/shared/duckfiretux-left.png",
2833 skidfiretux_right = load_image(DATA_PREFIX
2834 "/images/shared/skidfiretux-right.png",
2837 skidfiretux_left = load_image(DATA_PREFIX
2838 "/images/shared/skidfiretux-left.png",
2844 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2846 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2853 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2855 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2858 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2861 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2867 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2868 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2874 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2876 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2882 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2885 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2888 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2891 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2895 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2898 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2901 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2904 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2912 img_bsod_left[0] = load_image(DATA_PREFIX
2913 "/images/shared/bsod-left-0.png",
2916 img_bsod_left[1] = load_image(DATA_PREFIX
2917 "/images/shared/bsod-left-1.png",
2920 img_bsod_left[2] = load_image(DATA_PREFIX
2921 "/images/shared/bsod-left-2.png",
2924 img_bsod_left[3] = load_image(DATA_PREFIX
2925 "/images/shared/bsod-left-3.png",
2928 img_bsod_right[0] = load_image(DATA_PREFIX
2929 "/images/shared/bsod-right-0.png",
2932 img_bsod_right[1] = load_image(DATA_PREFIX
2933 "/images/shared/bsod-right-1.png",
2936 img_bsod_right[2] = load_image(DATA_PREFIX
2937 "/images/shared/bsod-right-2.png",
2940 img_bsod_right[3] = load_image(DATA_PREFIX
2941 "/images/shared/bsod-right-3.png",
2944 img_bsod_squished_left = load_image(DATA_PREFIX
2945 "/images/shared/bsod-squished-left.png",
2948 img_bsod_squished_right = load_image(DATA_PREFIX
2949 "/images/shared/bsod-squished-right.png",
2952 img_bsod_falling_left = load_image(DATA_PREFIX
2953 "/images/shared/bsod-falling-left.png",
2956 img_bsod_falling_right = load_image(DATA_PREFIX
2957 "/images/shared/bsod-falling-right.png",
2963 img_laptop_left[0] = load_image(DATA_PREFIX
2964 "/images/shared/laptop-left-0.png",
2967 img_laptop_left[1] = load_image(DATA_PREFIX
2968 "/images/shared/laptop-left-1.png",
2971 img_laptop_left[2] = load_image(DATA_PREFIX
2972 "/images/shared/laptop-left-2.png",
2975 img_laptop_right[0] = load_image(DATA_PREFIX
2976 "/images/shared/laptop-right-0.png",
2979 img_laptop_right[1] = load_image(DATA_PREFIX
2980 "/images/shared/laptop-right-1.png",
2983 img_laptop_right[2] = load_image(DATA_PREFIX
2984 "/images/shared/laptop-right-2.png",
2987 img_laptop_flat_left = load_image(DATA_PREFIX
2988 "/images/shared/laptop-flat-left.png",
2991 img_laptop_flat_right = load_image(DATA_PREFIX
2992 "/images/shared/laptop-flat-right.png",
2995 img_laptop_falling_left =
2996 load_image(DATA_PREFIX
2997 "/images/shared/laptop-falling-left.png",
3000 img_laptop_falling_right =
3001 load_image(DATA_PREFIX
3002 "/images/shared/laptop-falling-right.png",
3008 img_money_left[0] = load_image(DATA_PREFIX
3009 "/images/shared/bag-left-0.png",
3012 img_money_left[1] = load_image(DATA_PREFIX
3013 "/images/shared/bag-left-1.png",
3016 img_money_right[0] = load_image(DATA_PREFIX
3017 "/images/shared/bag-right-0.png",
3020 img_money_right[1] = load_image(DATA_PREFIX
3021 "/images/shared/bag-right-1.png",
3028 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
3029 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
3034 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
3036 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
3043 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
3046 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
3049 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
3052 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
3058 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
3063 img_golden_herring =
3064 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
3068 /* Super background: */
3070 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
3074 /* Sound effects: */
3076 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
3077 // initialize sounds[i] with the correct pointer's value:
3078 // NULL or something else. And it will be dangerous to
3079 // play with not-initialized pointers.
3080 // This is also true with if (use_music)
3081 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
3083 for (i = 0; i < NUM_SOUNDS; i++)
3084 sounds[i] = load_sound(soundfilenames[i]);
3087 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
3088 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
3090 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
3092 herring_song = load_song(herring_song_path);
3094 free(herring_song_path);
3099 /* Free shared data: */
3101 void unloadshared(void)
3105 for (i = 0; i < 3; i++)
3107 SDL_FreeSurface(tux_right[i]);
3108 SDL_FreeSurface(tux_left[i]);
3109 SDL_FreeSurface(bigtux_right[i]);
3110 SDL_FreeSurface(bigtux_left[i]);
3113 SDL_FreeSurface(bigtux_right_jump);
3114 SDL_FreeSurface(bigtux_left_jump);
3116 for (i = 0; i < 2; i++)
3118 SDL_FreeSurface(cape_right[i]);
3119 SDL_FreeSurface(cape_left[i]);
3120 SDL_FreeSurface(bigcape_right[i]);
3121 SDL_FreeSurface(bigcape_left[i]);
3124 SDL_FreeSurface(ducktux_left);
3125 SDL_FreeSurface(ducktux_right);
3127 SDL_FreeSurface(skidtux_left);
3128 SDL_FreeSurface(skidtux_right);
3130 for (i = 0; i < 4; i++)
3132 SDL_FreeSurface(img_bsod_left[i]);
3133 SDL_FreeSurface(img_bsod_right[i]);
3136 SDL_FreeSurface(img_bsod_squished_left);
3137 SDL_FreeSurface(img_bsod_squished_right);
3139 SDL_FreeSurface(img_bsod_falling_left);
3140 SDL_FreeSurface(img_bsod_falling_right);
3142 for (i = 0; i < 3; i++)
3144 SDL_FreeSurface(img_laptop_left[i]);
3145 SDL_FreeSurface(img_laptop_right[i]);
3148 SDL_FreeSurface(img_laptop_flat_left);
3149 SDL_FreeSurface(img_laptop_flat_right);
3151 SDL_FreeSurface(img_laptop_falling_left);
3152 SDL_FreeSurface(img_laptop_falling_right);
3154 for (i = 0; i < 2; i++)
3156 SDL_FreeSurface(img_money_left[i]);
3157 SDL_FreeSurface(img_money_right[i]);
3160 SDL_FreeSurface(img_box_full);
3161 SDL_FreeSurface(img_box_empty);
3163 SDL_FreeSurface(img_water);
3164 for (i = 0; i < 3; i++)
3165 SDL_FreeSurface(img_waves[i]);
3167 SDL_FreeSurface(img_pole);
3168 SDL_FreeSurface(img_poletop);
3170 for (i = 0; i < 2; i++)
3171 SDL_FreeSurface(img_flag[i]);
3173 SDL_FreeSurface(img_mints);
3174 SDL_FreeSurface(img_coffee);
3176 for (i = 0; i < 4; i++)
3178 SDL_FreeSurface(img_distro[i]);
3179 SDL_FreeSurface(img_cloud[0][i]);
3180 SDL_FreeSurface(img_cloud[1][i]);
3183 SDL_FreeSurface(img_golden_herring);
3185 for (i = 0; i < NUM_SOUNDS; i++)
3186 free_chunk(sounds[i]);
3188 /* free the herring song */
3189 free_music( herring_song );
3193 /* Draw a tile on the screen: */
3195 void drawshape(int x, int y, unsigned char c)
3199 if (c == 'X' || c == 'x')
3200 drawimage(img_brick[0], x, y, NO_UPDATE);
3201 else if (c == 'Y' || c == 'y')
3202 drawimage(img_brick[1], x, y, NO_UPDATE);
3203 else if (c == 'A' || c =='B' || c == '!')
3204 drawimage(img_box_full, x, y, NO_UPDATE);
3206 drawimage(img_box_empty, x, y, NO_UPDATE);
3207 else if (c >= 'C' && c <= 'F')
3208 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3209 else if (c >= 'c' && c <= 'f')
3210 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3211 else if (c >= 'G' && c <= 'J')
3212 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3213 else if (c >= 'g' && c <= 'j')
3214 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3216 drawimage(img_solid[0], x, y, NO_UPDATE);
3218 drawimage(img_solid[1], x, y, NO_UPDATE);
3220 drawimage(img_solid[2], x, y, NO_UPDATE);
3222 drawimage(img_solid[3], x, y, NO_UPDATE);
3225 z = (frame / 2) % 6;
3228 drawimage(img_distro[z], x, y, NO_UPDATE);
3230 drawimage(img_distro[2], x, y, NO_UPDATE);
3232 drawimage(img_distro[1], x, y, NO_UPDATE);
3236 z = (frame / 3) % 3;
3238 drawimage(img_waves[z], x, y, NO_UPDATE);
3241 drawimage(img_poletop, x, y, NO_UPDATE);
3244 drawimage(img_pole, x, y, NO_UPDATE);
3246 /* Mark this as the end position of the level! */
3252 z = (frame / 3) % 2;
3254 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3257 drawimage(img_water, x, y, NO_UPDATE);
3261 /* What shape is at some position? */
3263 unsigned char shape(int x, int y, int sx)
3269 xx = ((x + sx) / 32);
3271 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3282 int issolid(int x, int y, int sx)
3288 if (isbrick(x, y, sx) ||
3289 isbrick(x + 31, y, sx) ||
3291 isice(x + 31, y, sx) ||
3292 (shape(x, y, sx) == '[' ||
3293 shape(x + 31, y, sx) == '[') ||
3294 (shape(x, y, sx) == '=' ||
3295 shape(x + 31, y, sx) == '=') ||
3296 (shape(x, y, sx) == ']' ||
3297 shape(x + 31, y, sx) == ']') ||
3298 (shape(x, y, sx) == 'A' ||
3299 shape(x + 31, y, sx) == 'A') ||
3300 (shape(x, y, sx) == 'B' ||
3301 shape(x + 31, y, sx) == 'B') ||
3302 (shape(x, y, sx) == '!' ||
3303 shape(x + 31, y, sx) == '!') ||
3304 (shape(x, y, sx) == 'a' ||
3305 shape(x + 31, y, sx) == 'a'))
3314 /* Is it a brick? */
3316 int isbrick(int x, int y, int sx)
3322 if (shape(x, y, sx) == 'X' ||
3323 shape(x, y, sx) == 'x' ||
3324 shape(x, y, sx) == 'Y' ||
3325 shape(x, y, sx) == 'y')
3336 int isice(int x, int y, int sx)
3342 if (shape(x, y, sx) == '#')
3351 /* Is it a full box? */
3353 int isfullbox(int x, int y, int sx)
3359 if (shape(x, y, sx) == 'A' ||
3360 shape(x, y, sx) == 'B' ||
3361 shape(x, y, sx) == '!')
3370 /* Edit a piece of the map! */
3372 void change(int x, int y, int sx, unsigned char c)
3377 xx = ((x + sx) / 32);
3379 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3384 /* Break a brick: */
3386 void trybreakbrick(int x, int y, int sx)
3388 if (isbrick(x, y, sx))
3390 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3392 /* Get a distro from it: */
3394 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3397 if (counting_distros == NO)
3399 counting_distros = YES;
3400 distro_counter = 50;
3403 if (distro_counter <= 0)
3404 change(x, y, sx, 'a');
3406 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3407 score = score + SCORE_DISTRO;
3412 /* Get rid of it: */
3414 change(x, y, sx, '.');
3418 /* Replace it with broken bits: */
3420 add_broken_brick(((x + sx + 1) / 32) * 32,
3424 /* Get some score: */
3426 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
3427 score = score + SCORE_BRICK;
3432 /* Bounce a brick: */
3434 void bumpbrick(int x, int y, int sx)
3436 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3439 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
3445 void tryemptybox(int x, int y, int sx)
3447 if (isfullbox(x, y, sx))
3449 if (shape(x, y, sx) == 'A')
3451 /* Box with a distro! */
3453 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3454 (y / 32) * 32 - 32);
3456 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3457 score = score + SCORE_DISTRO;
3460 else if (shape(x, y, sx) == 'B')
3462 /* Add an upgrade! */
3464 if (tux_size == SMALL)
3466 /* Tux is small, add mints! */
3468 add_upgrade(((x + sx + 1) / 32) * 32,
3474 /* Tux is big, add coffee: */
3476 add_upgrade(((x + sx + 1) / 32) * 32,
3481 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
3483 else if (shape(x, y, sx) == '!')
3485 /* Add a golden herring */
3487 add_upgrade(((x + sx + 1) / 32) * 32,
3492 /* Empty the box: */
3494 change(x, y, sx, 'a');
3499 /* Try to grab a distro: */
3501 void trygrabdistro(int x, int y, int sx, int bounciness)
3503 if (shape(x, y, sx) == '$')
3505 change(x, y, sx, '.');
3506 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3508 if (bounciness == BOUNCE)
3510 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3514 score = score + SCORE_DISTRO;
3520 /* Add a bouncy distro: */
3522 void add_bouncy_distro(int x, int y)
3528 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3530 if (!bouncy_distros[i].alive)
3536 bouncy_distros[found].alive = YES;
3537 bouncy_distros[found].x = x;
3538 bouncy_distros[found].y = y;
3539 bouncy_distros[found].ym = -6;
3544 /* Add broken brick pieces: */
3546 void add_broken_brick(int x, int y)
3548 add_broken_brick_piece(x, y, -4, -16);
3549 add_broken_brick_piece(x, y + 16, -6, -12);
3551 add_broken_brick_piece(x + 16, y, 4, -16);
3552 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3556 /* Add a broken brick piece: */
3558 void add_broken_brick_piece(int x, int y, int xm, int ym)
3564 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3566 if (!broken_bricks[i].alive)
3572 broken_bricks[found].alive = YES;
3573 broken_bricks[found].x = x;
3574 broken_bricks[found].y = y;
3575 broken_bricks[found].xm = xm;
3576 broken_bricks[found].ym = ym;
3581 /* Add a bouncy brick piece: */
3583 void add_bouncy_brick(int x, int y)
3589 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3591 if (!bouncy_bricks[i].alive)
3597 bouncy_bricks[found].alive = YES;
3598 bouncy_bricks[found].x = x;
3599 bouncy_bricks[found].y = y;
3600 bouncy_bricks[found].offset = 0;
3601 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3602 bouncy_bricks[found].shape = shape(x, y, 0);
3607 /* Add a bad guy: */
3609 void add_bad_guy(int x, int y, int kind)
3615 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3617 if (!bad_guys[i].alive)
3623 bad_guys[found].alive = YES;
3624 bad_guys[found].mode = NORMAL;
3625 bad_guys[found].dying = NO;
3626 bad_guys[found].timer = 0;
3627 bad_guys[found].kind = kind;
3628 bad_guys[found].x = x;
3629 bad_guys[found].y = y;
3630 bad_guys[found].xm = 0;
3631 bad_guys[found].ym = 0;
3632 bad_guys[found].dir = LEFT;
3633 bad_guys[found].seen = NO;
3640 void add_score(int x, int y, int s)
3645 /* Add the score: */
3650 /* Add a floating score thing to the game: */
3654 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3656 if (!floating_scores[i].alive)
3663 floating_scores[found].alive = YES;
3664 floating_scores[found].x = x;
3665 floating_scores[found].y = y - 16;
3666 floating_scores[found].timer = 8;
3667 floating_scores[found].value = s;
3672 /* Try to bump a bad guy from below: */
3674 void trybumpbadguy(int x, int y, int sx)
3681 for (i = 0; i < NUM_BAD_GUYS; i++)
3683 if (bad_guys[i].alive &&
3684 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3685 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3687 if (bad_guys[i].kind == BAD_BSOD ||
3688 bad_guys[i].kind == BAD_LAPTOP)
3690 bad_guys[i].dying = FALLING;
3691 bad_guys[i].ym = -8;
3692 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
3700 for (i = 0; i < NUM_UPGRADES; i++)
3702 if (upgrades[i].alive && upgrades[i].height == 32 &&
3703 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3704 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3706 upgrades[i].xm = -upgrades[i].xm;
3707 upgrades[i].ym = -8;
3708 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
3714 /* Add an upgrade: */
3716 void add_upgrade(int x, int y, int kind)
3722 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3724 if (!upgrades[i].alive)
3730 upgrades[found].alive = YES;
3731 upgrades[found].kind = kind;
3732 upgrades[found].x = x;
3733 upgrades[found].y = y;
3734 upgrades[found].xm = 4;
3735 upgrades[found].ym = -4;
3736 upgrades[found].height = 0;
3743 void killtux(int mode)
3747 play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
3749 if (tux_dir == RIGHT)
3751 else if (tux_dir == LEFT)
3754 if (mode == SHRINK && tux_size == BIG)
3757 tux_got_coffee = NO;
3761 tux_safe = TUX_SAFE_TIME;
3772 void add_bullet(int x, int y, int dir, int xm)
3778 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3780 if (!bullets[i].alive)
3786 bullets[found].alive = YES;
3790 bullets[found].x = x + 32;
3791 bullets[found].xm = BULLET_XM + xm;
3795 bullets[found].x = x;
3796 bullets[found].xm = -BULLET_XM + xm;
3799 bullets[found].y = y;
3800 bullets[found].ym = BULLET_STARTING_YM;
3802 play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER);
3807 void drawendscreen(void)
3811 clearscreen(0, 0, 0);
3813 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE, 1);
3815 sprintf(str, "SCORE: %d", score);
3816 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
3818 sprintf(str, "DISTROS: %d", distros);
3819 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
3825 void drawresultscreen(void)
3829 clearscreen(0, 0, 0);
3831 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE, 1);
3833 sprintf(str, "SCORE: %d", score);
3834 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
3836 sprintf(str, "DISTROS: %d", distros);
3837 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
3840 /*SDL_Delay(2000);*/
3847 time_t current_time = time(NULL);
3848 struct tm* time_struct;
3851 time_struct = localtime(¤t_time);
3852 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);
3853 printf("%s",savefile);
3856 fi = fopen(savefile, "wb");
3860 fprintf(stderr, "Warning: I could not open the high score file ");
3865 fwrite(&level,4,1,fi);
3866 fwrite(&score,4,1,fi);
3867 fwrite(&distros,4,1,fi);
3868 fwrite(&tux_x,4,1,fi);
3869 fwrite(&tux_y,4,1,fi);
3870 fwrite(&scroll_x,4,1,fi);
3876 void loadgame(char* filename)
3880 time_t current_time = time(NULL);
3881 struct tm* time_struct;
3882 time_struct = localtime(¤t_time);
3883 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);
3884 printf("%s",savefile);
3888 fi = fopen(savefile, "rb");
3892 fprintf(stderr, "Warning: I could not open the high score file ");
3897 fread(&level,4,1,fi);
3898 fread(&score,4,1,fi);
3899 fread(&distros,4,1,fi);
3900 fread(&tux_x,4,1,fi);
3901 fread(&tux_y,4,1,fi);
3902 fread(&scroll_x,4,1,fi);