7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 9, 2003
22 #include <sys/types.h>
32 #include "high_scores.h"
60 char * soundfilenames[NUM_SOUNDS] = {
61 DATA_PREFIX "/sounds/jump.wav",
62 DATA_PREFIX "/sounds/bigjump.wav",
63 DATA_PREFIX "/sounds/skid.wav",
64 DATA_PREFIX "/sounds/distro.wav",
65 DATA_PREFIX "/sounds/herring.wav",
66 DATA_PREFIX "/sounds/brick.wav",
67 DATA_PREFIX "/sounds/hurt.wav",
68 DATA_PREFIX "/sounds/squish.wav",
69 DATA_PREFIX "/sounds/fall.wav",
70 DATA_PREFIX "/sounds/ricochet.wav",
71 DATA_PREFIX "/sounds/bump-upgrade.wav",
72 DATA_PREFIX "/sounds/upgrade.wav",
73 DATA_PREFIX "/sounds/excellent.wav",
74 DATA_PREFIX "/sounds/coffee.wav",
75 DATA_PREFIX "/sounds/shoot.wav",
76 DATA_PREFIX "/sounds/lifeup.wav"
80 /* Local variables: */
82 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
83 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
84 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
85 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
86 super_bkgd_time, time_left, tux_invincible_time, endpos,
87 counting_distros, distro_counter;
88 int bkgd_red, bkgd_green, bkgd_blue, level_width;
89 int left, right, up, down, fire, old_fire;
90 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
91 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
92 SDL_Surface * img_bkgd[2][4];
93 SDL_Surface * img_golden_herring;
94 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
95 * img_laptop_left[3], * img_laptop_right[3],
96 * img_money_left[2], * img_money_right[2];
97 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
98 * img_bsod_falling_left, * img_bsod_falling_right,
99 * img_laptop_flat_left, * img_laptop_flat_right,
100 * img_laptop_falling_left, * img_laptop_falling_right;
101 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
102 * img_super_bkgd, * img_bullet, * img_red_glow;
103 SDL_Surface * img_cloud[2][4];
104 SDL_Surface * tux_right[3], * tux_left[3],
105 * bigtux_right[3], * bigtux_left[3],
106 * bigtux_right_jump, * bigtux_left_jump,
107 * cape_right[2], * cape_left[2],
108 * bigcape_right[2], * bigcape_left[2],
109 * ducktux_right, * ducktux_left,
110 * skidtux_right, * skidtux_left, * tux_life;
114 unsigned char * tiles[15];
115 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
116 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
117 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
118 bad_guy_type bad_guys[NUM_BAD_GUYS];
119 floating_score_type floating_scores[NUM_FLOATING_SCORES];
120 upgrade_type upgrades[NUM_UPGRADES];
121 bullet_type bullets[NUM_BULLETS];
129 /* Local function prototypes: */
132 void loadlevel(void);
133 void loadlevelgfx(void);
134 void loadlevelsong(void);
135 void unloadlevelgfx(void);
136 void unloadlevelsong(void);
137 void loadshared(void);
138 void unloadshared(void);
139 void drawshape(int x, int y, unsigned char c);
141 unsigned char shape(int x, int y, int sx);
142 int issolid(int x, int y, int sx);
143 int isbrick(int x, int y, int sx);
144 int isice(int x, int y, int sx);
145 int isfullbox(int x, int y, int sx);
146 void change(int x, int y, int sx, unsigned char c);
147 void trybreakbrick(int x, int y, int sx);
148 void bumpbrick(int x, int y, int sx);
149 void tryemptybox(int x, int y, int sx);
150 void trygrabdistro(int x, int y, int sx, int bounciness);
151 void add_bouncy_distro(int x, int y);
152 void add_broken_brick(int x, int y);
153 void add_broken_brick_piece(int x, int y, int xm, int ym);
154 void add_bouncy_brick(int x, int y);
155 void add_bad_guy(int x, int y, int kind);
156 void add_score(int x, int y, int s);
157 void trybumpbadguy(int x, int y, int sx);
158 void add_upgrade(int x, int y, int kind);
159 void killtux(int mode);
160 void add_bullet(int x, int y, int dir, int xm);
161 void drawendscreen(void);
162 void drawresultscreen(void);
164 /* --- GAME EVENT! --- */
166 void game_event(void)
169 while (SDL_PollEvent(&event))
172 if (event.type == SDL_QUIT)
174 /* Quit event - quit: */
178 else if (event.type == SDL_KEYDOWN)
182 key = event.key.keysym.sym;
184 /* Check for menu-events, if the menu is shown */
188 if (key == SDLK_ESCAPE)
190 /* Escape: Open/Close the menu: */
199 else if (key == SDLK_RIGHT)
203 else if (key == SDLK_LEFT)
207 else if (key == SDLK_UP)
211 else if (key == SDLK_DOWN)
215 else if (key == SDLK_LCTRL)
220 else if (event.type == SDL_KEYUP)
224 key = event.key.keysym.sym;
226 if (key == SDLK_RIGHT)
230 else if (key == SDLK_LEFT)
234 else if (key == SDLK_UP)
238 else if (key == SDLK_DOWN)
242 else if (key == SDLK_LCTRL)
246 else if (key == SDLK_p)
256 else if (key == SDLK_TAB && debug_mode == YES)
258 tux_size = !tux_size;
260 else if (key == SDLK_END && debug_mode == YES)
264 else if (key == SDLK_SPACE && debug_mode == YES)
270 else if (event.type == SDL_JOYAXISMOTION)
272 if (event.jaxis.axis == JOY_X)
274 if (event.jaxis.value < -256)
279 if (event.jaxis.value > 256)
284 else if (event.jaxis.axis == JOY_Y)
286 if (event.jaxis.value > 256)
291 /* Handle joystick for the menu */
295 menuaction = MN_DOWN;
301 else if (event.type == SDL_JOYBUTTONDOWN)
303 if (event.jbutton.button == JOY_A)
305 else if (event.jbutton.button == JOY_B)
308 else if (event.type == SDL_JOYBUTTONUP)
310 if (event.jbutton.button == JOY_A)
312 else if (event.jbutton.button == JOY_B)
325 /* --- GAME ACTION! --- */
327 int game_action(void)
331 /* --- HANDLE TUX! --- */
333 /* Handle key and joystick state: */
335 if (!(tux_dying || next_level))
337 if (right == DOWN && left == UP)
341 if (tux_xm < -SKID_XM && !tux_skidding &&
344 tux_skidding = SKID_TIME;
346 play_sound(sounds[SND_SKID]);
352 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
360 if (tux_dir == RIGHT)
362 /* Facing the direction we're jumping? Go full-speed: */
366 tux_xm = tux_xm + WALK_SPEED;
368 if (tux_xm > MAX_WALK_XM)
369 tux_xm = MAX_WALK_XM;
371 else if (fire == DOWN)
373 tux_xm = tux_xm + RUN_SPEED;
375 if (tux_xm > MAX_RUN_XM)
381 /* Not facing the direction we're jumping?
384 tux_xm = tux_xm + WALK_SPEED / 2;
386 if (tux_xm > MAX_WALK_XM / 2)
387 tux_xm = MAX_WALK_XM / 2;
391 else if (left == DOWN && right == UP)
395 if (tux_xm > SKID_XM && !tux_skidding &&
398 tux_skidding = SKID_TIME;
399 play_sound(sounds[SND_SKID]);
404 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
414 /* Facing the direction we're jumping? Go full-speed: */
418 tux_xm = tux_xm - WALK_SPEED;
420 if (tux_xm < -MAX_WALK_XM)
421 tux_xm = -MAX_WALK_XM;
423 else if (fire == DOWN)
425 tux_xm = tux_xm - RUN_SPEED;
427 if (tux_xm < -MAX_RUN_XM)
428 tux_xm = -MAX_RUN_XM;
433 /* Not facing the direction we're jumping?
436 tux_xm = tux_xm - WALK_SPEED / 2;
438 if (tux_xm < -MAX_WALK_XM / 2)
439 tux_xm = -MAX_WALK_XM / 2;
447 if (tux_x >= endpos && endpos != 0)
457 if (jump_counter == 0)
461 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
464 /* If they're not on the ground, or are currently moving
465 vertically, don't jump! */
467 jump_counter = MAX_JUMP_COUNT;
471 /* Make sure we're not standing back up into a solid! */
473 if (tux_size == SMALL || tux_duck == NO ||
474 !issolid(tux_x, tux_y, scroll_x))
478 if (tux_size == SMALL)
479 play_sound(sounds[SND_JUMP]);
481 play_sound(sounds[SND_BIGJUMP]);
487 /* Keep jumping for a while: */
489 if (jump_counter < MAX_JUMP_COUNT)
491 tux_ym = tux_ym - JUMP_SPEED;
501 if (fire == DOWN && old_fire == UP && tux_got_coffee)
503 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
516 if (tux_size == BIG && tux_duck == YES)
518 /* Make sure we're not standing back up into a solid! */
520 if (!issolid(tux_x, tux_y - 32, scroll_x))
526 } /* (tux_dying || next_level) */
529 /* Tux either died, or reached the end of a level! */
538 /* End of a level! */
546 tux_ym = tux_ym + GRAVITY;
554 /* No more lives!? */
560 if (score > highscore)
567 } /* if (lives < 0) */
570 /* Either way, (re-)load the (next) level... */
581 tux_x = tux_x + tux_xm;
582 tux_y = tux_y + tux_ym;
585 /* Keep tux in bounds: */
588 else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
590 scroll_x = scroll_x - ( 160 - tux_x);
597 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
599 /* Scroll the screen in past center: */
601 scroll_x = scroll_x + (tux_x - 320);
604 if (scroll_x > ((level_width * 32) - 640))
605 scroll_x = ((level_width * 32) - 640);
607 else if (tux_x > 608)
609 /* ... unless there's no more to scroll! */
619 if (issolid(tux_x, tux_y + 31, scroll_x) &&
620 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
622 while (issolid(tux_x, tux_y + 31, scroll_x))
633 if (issolid(tux_x, tux_y, scroll_x) &&
634 !issolid(tux_x - tux_xm, tux_y, scroll_x))
636 while (issolid(tux_x, tux_y, scroll_x))
647 if (issolid(tux_x, tux_y + 31, scroll_x))
649 /* Set down properly: */
651 while (issolid(tux_x, tux_y + 31, scroll_x))
660 /* Reset score multiplier (for mutli-hits): */
663 score_multiplier = 1;
673 /* Bump into things: */
675 if (issolid(tux_x, tux_y, scroll_x) ||
676 (tux_size == BIG && !tux_duck &&
677 (issolid(tux_x, tux_y - 32, scroll_x))))
679 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
680 (tux_size == SMALL || tux_duck ||
681 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
683 tux_x = tux_x - tux_xm;
686 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
687 (tux_size == SMALL || tux_duck ||
688 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
696 /* Break bricks and empty boxes: */
700 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
701 isfullbox(tux_x, tux_y - 32, scroll_x))
703 trygrabdistro(tux_x, tux_y - 64, scroll_x,
705 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
707 if (isfullbox(tux_x, tux_y - 32,
710 bumpbrick(tux_x, tux_y - 32,
714 trybreakbrick(tux_x, tux_y - 32, scroll_x);
715 tryemptybox(tux_x, tux_y - 32, scroll_x);
718 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
719 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
721 trygrabdistro(tux_x + 31,
725 trybumpbadguy(tux_x + 31,
729 if (isfullbox(tux_x + 31, tux_y - 32,
732 bumpbrick(tux_x + 31, tux_y - 32,
736 trybreakbrick(tux_x + 31,
739 tryemptybox(tux_x + 31,
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 if (isfullbox(tux_x, tux_y, scroll_x))
753 bumpbrick(tux_x, tux_y, scroll_x);
754 trybreakbrick(tux_x, tux_y, scroll_x);
755 tryemptybox(tux_x, tux_y, scroll_x);
758 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
759 isfullbox(tux_x + 31, tux_y, scroll_x))
761 trygrabdistro(tux_x + 31,
765 trybumpbadguy(tux_x + 31,
768 if (isfullbox(tux_x + 31, tux_y, scroll_x))
769 bumpbrick(tux_x + 31, tux_y, scroll_x);
770 trybreakbrick(tux_x + 31, tux_y, scroll_x);
771 tryemptybox(tux_x + 31, tux_y, scroll_x);
777 /* It's a brick and we're small, make the brick
778 bounce, and grab any distros above it: */
780 if (isbrick(tux_x, tux_y, scroll_x) ||
781 isfullbox(tux_x, tux_y, scroll_x))
783 trygrabdistro(tux_x, tux_y - 32, scroll_x,
785 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
786 bumpbrick(tux_x, tux_y, scroll_x);
787 tryemptybox(tux_x, tux_y, scroll_x);
790 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
791 isfullbox(tux_x + 31, tux_y, scroll_x))
793 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
795 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
796 bumpbrick(tux_x + 31, tux_y, scroll_x);
797 tryemptybox(tux_x + 31, tux_y, scroll_x);
801 /* Get a distro from a brick? */
803 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
804 shape(tux_x, tux_y, scroll_x) == 'y')
806 add_bouncy_distro(((tux_x + scroll_x + 1)
810 if (counting_distros == NO)
812 counting_distros = YES;
813 distro_counter = 100;
816 if (distro_counter <= 0)
817 change(tux_x, tux_y, scroll_x, 'a');
819 play_sound(sounds[SND_DISTRO]);
820 score = score + SCORE_DISTRO;
823 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
824 shape(tux_x + 31, tux_y, scroll_x) == 'y')
826 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
830 if (counting_distros == NO)
832 counting_distros = YES;
833 distro_counter = 100;
836 if (distro_counter <= 0)
837 change(tux_x + 31, tux_y, scroll_x, 'a');
839 play_sound(sounds[SND_DISTRO]);
840 score = score + SCORE_DISTRO;
848 tux_y = (tux_y / 32) * 32 + 30;
854 tux_y = (tux_y / 32) * 32 - 32;
859 jump_counter = MAX_JUMP_COUNT;
869 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
870 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
872 if (tux_size == BIG && !tux_duck)
874 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
875 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
880 /* Enough distros for a One-up? */
882 if (distros >= DISTROS_LIFEUP)
884 distros = distros - DISTROS_LIFEUP;
885 if(lives < MAX_LIVES)
887 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
891 /* Keep in-bounds, vertically: */
895 else if (tux_y > 480)
901 /* Slow down horizontally: */
905 if (right == UP && left == UP)
907 if (isice(tux_x, tux_y + 32, scroll_x) ||
908 !issolid(tux_x, tux_y + 32, scroll_x))
910 /* Slowly on ice or in air: */
919 /* Quickly, otherwise: */
926 /* Drop vertically: */
928 if (!issolid(tux_x, tux_y + 32, scroll_x))
930 tux_ym = tux_ym + GRAVITY;
942 /* ---- DONE HANDLING TUX! --- */
945 /* Handle bouncy distros: */
947 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
949 if (bouncy_distros[i].alive)
951 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
953 bouncy_distros[i].ym++;
955 if (bouncy_distros[i].ym >= 0)
956 bouncy_distros[i].alive = NO;
961 /* Handle broken bricks: */
963 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
965 if (broken_bricks[i].alive)
967 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
968 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
970 broken_bricks[i].ym++;
972 if (broken_bricks[i].ym >= 0)
973 broken_bricks[i].alive = NO;
978 /* Handle distro counting: */
980 if (counting_distros == YES)
984 if (distro_counter <= 0)
985 counting_distros = -1;
989 /* Handle bouncy bricks: */
991 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
993 if (bouncy_bricks[i].alive)
995 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
996 bouncy_bricks[i].offset_m);
1000 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
1001 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
1004 /* Stop bouncing? */
1006 if (bouncy_bricks[i].offset == 0)
1007 bouncy_bricks[i].alive = NO;
1012 /* Handle floating scores: */
1014 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1016 if (floating_scores[i].alive)
1018 floating_scores[i].y = floating_scores[i].y - 2;
1019 floating_scores[i].timer--;
1021 if (floating_scores[i].timer <= 0)
1022 floating_scores[i].alive = NO;
1027 /* Handle bullets: */
1029 for (i = 0; i < NUM_BULLETS; i++)
1031 if (bullets[i].alive)
1033 bullets[i].x = bullets[i].x + bullets[i].xm;
1034 bullets[i].y = bullets[i].y + bullets[i].ym;
1036 if (issolid(bullets[i].x, bullets[i].y, 0))
1038 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1039 bullets[i].alive = NO;
1042 if (bullets[i].ym >= 0)
1044 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1046 bullets[i].ym = -bullets[i].ym;
1050 bullets[i].ym = bullets[i].ym + GRAVITY;
1052 if (bullets[i].x < scroll_x ||
1053 bullets[i].x > scroll_x + 640)
1055 bullets[i].alive = NO;
1060 if (bullets[i].alive)
1062 for (j = 0; j < NUM_BAD_GUYS; j++)
1064 if (bad_guys[j].alive && !bad_guys[j].dying)
1066 if (bullets[i].x >= bad_guys[j].x - 4 &&
1067 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1068 bullets[i].y >= bad_guys[j].y - 4 &&
1069 bullets[i].y <= bad_guys[j].y + 32 + 4)
1071 /* Kill the bad guy! */
1073 bullets[i].alive = 0;
1074 bad_guys[j].dying = FALLING;
1075 bad_guys[j].ym = -8;
1078 /* Gain some points: */
1080 if (bad_guys[j].kind == BAD_BSOD)
1082 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1083 50 * score_multiplier);
1085 else if (bad_guys[j].kind == BAD_LAPTOP)
1087 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1088 25 * score_multiplier);
1092 /* Play death sound: */
1093 play_sound(sounds[SND_FALL]);
1101 /* Handle background timer: */
1103 if (super_bkgd_time)
1107 /* Handle invincibility timer: */
1110 if (tux_invincible_time > 50)
1112 tux_invincible_time--;
1115 if (!playing_music())
1116 play_music( herring_song, 1 );
1120 if (current_music == HERRING_MUSIC)
1122 /* stop the herring_song, now play the level_song ! */
1123 current_music = LEVEL_MUSIC;
1127 if (!playing_music())
1129 play_music( level_song, 1 );
1133 if (tux_invincible_time > 0)
1134 tux_invincible_time--;
1136 if (current_music == LEVEL_MUSIC && time_left < 250)
1138 if ((frame % 10) == 0)
1140 set_music_position(sound_pos);
1151 /* Handle upgrades: */
1153 for (i = 0; i < NUM_UPGRADES; i++)
1155 if (upgrades[i].alive)
1157 if (upgrades[i].height < 32)
1161 upgrades[i].height++;
1167 if (upgrades[i].kind == UPGRADE_MINTS ||
1168 upgrades[i].kind == UPGRADE_HERRING)
1170 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1171 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1173 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1174 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1176 if (upgrades[i].ym > 0)
1178 if (upgrades[i].kind == UPGRADE_MINTS)
1182 else if (upgrades[i].kind == UPGRADE_HERRING)
1184 upgrades[i].ym = -24;
1187 upgrades[i].y = (upgrades[i].y / 32) * 32;
1191 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1193 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1195 upgrades[i].xm = -upgrades[i].xm;
1200 /* Off the screen? Kill it! */
1202 if (upgrades[i].x < scroll_x)
1203 upgrades[i].alive = NO;
1206 /* Did the player grab it? */
1208 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1209 tux_x + scroll_x <= upgrades[i].x + 32 &&
1210 tux_y >= upgrades[i].y - 32 &&
1211 tux_y <= upgrades[i].y + 32)
1213 /* Remove the upgrade: */
1215 upgrades[i].alive = NO;
1218 /* Affect the player: */
1220 if (upgrades[i].kind == UPGRADE_MINTS)
1222 play_sound(sounds[SND_EXCELLENT]);
1224 super_bkgd_time = 8;
1226 else if (upgrades[i].kind == UPGRADE_COFFEE)
1228 play_sound(sounds[SND_COFFEE]);
1229 tux_got_coffee = YES;
1230 super_bkgd_time = 4;
1232 else if (upgrades[i].kind == UPGRADE_HERRING)
1234 play_sound(sounds[SND_HERRING]);
1235 tux_invincible_time = TUX_INVINCIBLE_TIME;
1236 super_bkgd_time = 4;
1237 /* play the herring song ^^ */
1238 current_music = HERRING_MUSIC;
1239 if (playing_music())
1241 play_music( herring_song, 1 );
1249 /* Handle bad guys: */
1251 for (i = 0; i < NUM_BAD_GUYS; i++)
1253 if (bad_guys[i].alive)
1255 if (bad_guys[i].seen)
1257 if (bad_guys[i].kind == BAD_BSOD)
1259 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1261 /* Move left/right: */
1263 if (bad_guys[i].dying == NO ||
1264 bad_guys[i].dying == FALLING)
1266 if (bad_guys[i].dir == RIGHT)
1267 bad_guys[i].x = bad_guys[i].x + 4;
1268 else if (bad_guys[i].dir == LEFT)
1269 bad_guys[i].x = bad_guys[i].x - 4;
1273 /* Move vertically: */
1275 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1278 /* Bump into things horizontally: */
1280 if (!bad_guys[i].dying)
1282 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1283 bad_guys[i].dir = !bad_guys[i].dir;
1287 /* Bump into other bad guys: */
1289 for (j = 0; j < NUM_BAD_GUYS; j++)
1291 if (j != i && bad_guys[j].alive &&
1292 !bad_guys[j].dying && !bad_guys[i].dying &&
1293 bad_guys[i].x >= bad_guys[j].x - 32 &&
1294 bad_guys[i].x <= bad_guys[j].x + 32 &&
1295 bad_guys[i].y >= bad_guys[j].y - 32 &&
1296 bad_guys[i].y <= bad_guys[j].y + 32)
1298 bad_guys[i].dir = !bad_guys[i].dir;
1303 /* Fall if we get off the ground: */
1305 if (bad_guys[i].dying != FALLING)
1307 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1308 bad_guys[i].ym < MAX_YM)
1310 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1316 if (bad_guys[i].ym > 0)
1318 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1324 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1326 if (bad_guys[i].y > 480)
1327 bad_guys[i].alive = NO;
1329 else if (bad_guys[i].kind == BAD_LAPTOP)
1331 /* --- LAPTOP MONSTER: --- */
1333 /* Move left/right: */
1335 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1337 if (bad_guys[i].dying == NO ||
1338 bad_guys[i].dying == FALLING)
1340 if (bad_guys[i].dir == RIGHT)
1341 bad_guys[i].x = bad_guys[i].x + 4;
1342 else if (bad_guys[i].dir == LEFT)
1343 bad_guys[i].x = bad_guys[i].x - 4;
1346 else if (bad_guys[i].mode == KICK)
1348 if (bad_guys[i].dir == RIGHT)
1349 bad_guys[i].x = bad_guys[i].x + 16;
1350 else if (bad_guys[i].dir == LEFT)
1351 bad_guys[i].x = bad_guys[i].x - 16;
1355 /* Move vertically: */
1357 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1360 /* Bump into things horizontally: */
1362 if (!bad_guys[i].dying)
1364 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1366 bad_guys[i].dir = !bad_guys[i].dir;
1368 if (bad_guys[i].mode == KICK)
1369 play_sound(sounds[SND_RICOCHET]);
1374 /* Bump into other bad guys: */
1376 for (j = 0; j < NUM_BAD_GUYS; j++)
1378 if (j != i && bad_guys[j].alive &&
1379 !bad_guys[j].dying && !bad_guys[i].dying &&
1380 bad_guys[i].x >= bad_guys[j].x - 32 &&
1381 bad_guys[i].x <= bad_guys[j].x + 32 &&
1382 bad_guys[i].y >= bad_guys[j].y - 32 &&
1383 bad_guys[i].y <= bad_guys[j].y + 32)
1385 if (bad_guys[i].mode != KICK)
1386 bad_guys[i].dir = !bad_guys[i].dir;
1389 /* We're in kick mode, kill the other guy: */
1391 bad_guys[j].dying = FALLING;
1392 bad_guys[j].ym = -8;
1393 play_sound(sounds[SND_FALL]);
1395 add_score(bad_guys[i].x - scroll_x,
1396 bad_guys[i].y, 100);
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) &&
1407 bad_guys[i].ym < MAX_YM)
1409 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1415 if (bad_guys[i].ym > 0)
1417 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1423 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1425 if (bad_guys[i].y > 480)
1426 bad_guys[i].alive = NO;
1428 else if (bad_guys[i].kind == BAD_MONEY)
1430 /* --- MONEY BAGS: --- */
1433 /* Move vertically: */
1435 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1438 /* Fall if we get off the ground: */
1440 if (bad_guys[i].dying != FALLING)
1442 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1444 if (bad_guys[i].ym < MAX_YM)
1446 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1453 if (bad_guys[i].ym > 0)
1455 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1456 bad_guys[i].ym = -MAX_YM;
1461 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1463 if (bad_guys[i].y > 480)
1464 bad_guys[i].alive = NO;
1466 else if (bad_guys[i].kind == -1)
1470 /* Kill it if the player jumped on it: */
1472 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1473 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1474 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1475 tux_y >= bad_guys[i].y - 32 &&
1476 tux_y <= bad_guys[i].y - 8
1480 if (bad_guys[i].kind == BAD_BSOD)
1482 bad_guys[i].dying = SQUISHED;
1483 bad_guys[i].timer = 16;
1484 tux_ym = -KILL_BOUNCE_YM;
1486 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1487 50 * score_multiplier);
1489 play_sound(sounds[SND_SQUISH]);
1491 else if (bad_guys[i].kind == BAD_LAPTOP)
1493 if (bad_guys[i].mode != FLAT)
1497 bad_guys[i].mode = FLAT;
1499 bad_guys[i].timer = 64;
1507 bad_guys[i].mode = KICK;
1509 if (tux_x + scroll_x <= bad_guys[i].x)
1510 bad_guys[i].dir = RIGHT;
1512 bad_guys[i].dir = LEFT;
1514 bad_guys[i].timer = 8;
1517 tux_ym = -KILL_BOUNCE_YM;
1519 add_score(bad_guys[i].x - scroll_x,
1521 25 * score_multiplier);
1523 /* play_sound(sounds[SND_SQUISH]); */
1525 else if (bad_guys[i].kind == -1)
1532 /* Hurt the player if he just touched it: */
1534 if (!bad_guys[i].dying && !tux_dying &&
1536 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1537 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1538 tux_y >= bad_guys[i].y - 32 &&
1539 tux_y <= bad_guys[i].y + 32)
1541 if (bad_guys[i].mode == FLAT)
1545 bad_guys[i].mode = KICK;
1547 if (tux_x + scroll_x <= bad_guys[i].x)
1549 bad_guys[i].dir = RIGHT;
1550 bad_guys[i].x = bad_guys[i].x + 16;
1554 bad_guys[i].dir = LEFT;
1555 bad_guys[i].x = bad_guys[i].x - 16;
1558 bad_guys[i].timer = 8;
1560 else if (bad_guys[i].mode == KICK)
1562 if (tux_y < bad_guys[i].y - 16 &&
1563 bad_guys[i].timer == 0)
1565 /* Step on (stop being kicked) */
1567 bad_guys[i].mode = FLAT;
1568 bad_guys[i].timer = 64;
1572 /* Hurt if you get hit by kicked laptop: */
1574 if (bad_guys[i].timer == 0)
1576 if (tux_invincible_time == 0)
1582 bad_guys[i].dying = FALLING;
1583 bad_guys[i].ym = -8;
1584 play_sound(sounds[SND_FALL]);
1591 if (tux_invincible_time == 0)
1597 bad_guys[i].dying = FALLING;
1598 bad_guys[i].ym = -8;
1599 play_sound(sounds[SND_FALL]);
1605 /* Handle mode timer: */
1607 if (bad_guys[i].mode == FLAT)
1609 bad_guys[i].timer--;
1611 if (bad_guys[i].timer <= 0)
1612 bad_guys[i].mode = NORMAL;
1614 else if (bad_guys[i].mode == KICK)
1616 if (bad_guys[i].timer > 0)
1617 bad_guys[i].timer--;
1621 /* Handle dying timer: */
1623 if (bad_guys[i].dying == SQUISHED)
1625 bad_guys[i].timer--;
1628 /* Remove it if time's up: */
1630 if (bad_guys[i].timer <= 0)
1631 bad_guys[i].alive = NO;
1635 /* Remove if it's far off the screen: */
1637 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1638 bad_guys[i].alive = NO;
1642 /* Once it's on screen, it's activated! */
1644 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1645 bad_guys[i].seen = YES;
1651 /* Handle skidding: */
1653 if (tux_skidding > 0)
1661 /* --- GAME DRAW! --- */
1669 if (tux_dying && (frame % 4) == 0)
1670 clearscreen(255, 255, 255);
1673 if (super_bkgd_time == 0)
1674 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1676 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1680 /* Draw background: */
1682 for (y = 0; y < 15; y++)
1684 for (x = 0; x < 21; x++)
1686 drawshape(x * 32 - (scroll_x % 32), y * 32,
1687 tiles[y][x + (scroll_x / 32)]);
1692 /* (Bouncy bricks): */
1694 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1696 if (bouncy_bricks[i].alive)
1698 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1699 bouncy_bricks[i].x <= scroll_x + 640)
1701 dest.x = bouncy_bricks[i].x - scroll_x;
1702 dest.y = bouncy_bricks[i].y;
1706 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1711 drawshape(bouncy_bricks[i].x - scroll_x,
1712 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1713 bouncy_bricks[i].shape);
1721 for (i = 0; i < NUM_BAD_GUYS; i++)
1723 if (bad_guys[i].alive &&
1724 bad_guys[i].x > scroll_x - 32 &&
1725 bad_guys[i].x < scroll_x + 640)
1727 if (bad_guys[i].kind == BAD_BSOD)
1729 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1731 if (bad_guys[i].dying == NO)
1735 if (bad_guys[i].dir == LEFT)
1737 drawimage(img_bsod_left[(frame / 5) % 4],
1738 bad_guys[i].x - scroll_x,
1744 drawimage(img_bsod_right[(frame / 5) % 4],
1745 bad_guys[i].x - scroll_x,
1750 else if (bad_guys[i].dying == FALLING)
1754 if (bad_guys[i].dir == LEFT)
1756 drawimage(img_bsod_falling_left,
1757 bad_guys[i].x - scroll_x,
1763 drawimage(img_bsod_falling_right,
1764 bad_guys[i].x - scroll_x,
1769 else if (bad_guys[i].dying == SQUISHED)
1771 /* Dying - Squished: */
1773 if (bad_guys[i].dir == LEFT)
1775 drawimage(img_bsod_squished_left,
1776 bad_guys[i].x - scroll_x,
1782 drawimage(img_bsod_squished_right,
1783 bad_guys[i].x - scroll_x,
1789 else if (bad_guys[i].kind == BAD_LAPTOP)
1791 /* --- LAPTOP MONSTER: --- */
1793 if (bad_guys[i].dying == NO)
1797 if (bad_guys[i].mode == NORMAL)
1801 if (bad_guys[i].dir == LEFT)
1803 drawimage(img_laptop_left[(frame / 5) % 3],
1804 bad_guys[i].x - scroll_x,
1810 drawimage(img_laptop_right[(frame / 5) % 3],
1811 bad_guys[i].x - scroll_x,
1820 if (bad_guys[i].dir == LEFT)
1822 drawimage(img_laptop_flat_left,
1823 bad_guys[i].x - scroll_x,
1829 drawimage(img_laptop_flat_right,
1830 bad_guys[i].x - scroll_x,
1836 else if (bad_guys[i].dying == FALLING)
1840 if (bad_guys[i].dir == LEFT)
1842 drawimage(img_laptop_falling_left,
1843 bad_guys[i].x - scroll_x,
1849 drawimage(img_laptop_falling_right,
1850 bad_guys[i].x - scroll_x,
1856 else if (bad_guys[i].kind == BAD_MONEY)
1858 if (bad_guys[i].ym > -16)
1860 if (bad_guys[i].dir == LEFT)
1862 drawimage(img_money_left[0],
1863 bad_guys[i].x - scroll_x,
1869 drawimage(img_money_right[0],
1870 bad_guys[i].x - scroll_x,
1877 if (bad_guys[i].dir == LEFT)
1879 drawimage(img_money_left[1],
1880 bad_guys[i].x - scroll_x,
1886 drawimage(img_money_right[1],
1887 bad_guys[i].x - scroll_x,
1893 else if (bad_guys[i].kind == -1)
1901 if (right == UP && left == UP)
1908 if ((fire == DOWN && (frame % 2) == 0) ||
1910 tux_frame_main = (tux_frame_main + 1) % 4;
1912 tux_frame = tux_frame_main;
1919 if (tux_got_coffee && (frame % 2) == 1)
1923 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1927 if (tux_safe == 0 || (frame % 2) == 0)
1929 if (tux_size == SMALL)
1931 if (tux_invincible_time)
1935 if (tux_dir == RIGHT)
1937 drawimage(cape_right[frame % 2],
1943 drawimage(cape_left[frame % 2],
1950 if (tux_dir == RIGHT)
1952 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1956 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1961 if (tux_invincible_time)
1965 if (tux_dir == RIGHT)
1967 drawimage(bigcape_right[frame % 2],
1968 tux_x - 8 - 16, tux_y - 32,
1973 drawimage(bigcape_left[frame % 2],
1974 tux_x - 8, tux_y - 32,
1983 if (!jumping || tux_ym > 0)
1985 if (tux_dir == RIGHT)
1987 drawimage(bigtux_right[tux_frame],
1988 tux_x - 8, tux_y - 32,
1993 drawimage(bigtux_left[tux_frame],
1994 tux_x - 8, tux_y - 32,
2000 if (tux_dir == RIGHT)
2002 drawimage(bigtux_right_jump,
2003 tux_x - 8, tux_y - 32,
2008 drawimage(bigtux_left_jump,
2009 tux_x - 8, tux_y - 32,
2016 if (tux_dir == RIGHT)
2018 drawimage(skidtux_right,
2019 tux_x - 8, tux_y - 32,
2024 drawimage(skidtux_left,
2025 tux_x - 8, tux_y - 32,
2032 if (tux_dir == RIGHT)
2034 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2039 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2049 for (i = 0; i < NUM_BULLETS; i++)
2051 if (bullets[i].alive &&
2052 bullets[i].x >= scroll_x - 4 &&
2053 bullets[i].x <= scroll_x + 640)
2055 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2061 /* (Floating scores): */
2063 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2065 if (floating_scores[i].alive)
2067 sprintf(str, "%d", floating_scores[i].value);
2069 floating_scores[i].x + 16 - strlen(str) * 8,
2070 floating_scores[i].y,
2071 letters_gold, NO_UPDATE);
2078 for (i = 0; i < NUM_UPGRADES; i++)
2080 if (upgrades[i].alive)
2082 if (upgrades[i].height < 32)
2086 dest.x = upgrades[i].x - scroll_x;
2087 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2089 dest.h = upgrades[i].height;
2094 src.h = upgrades[i].height;
2096 if (upgrades[i].kind == UPGRADE_MINTS)
2097 SDL_BlitSurface(img_mints, &src, screen, &dest);
2098 else if (upgrades[i].kind == UPGRADE_COFFEE)
2099 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2100 else if (upgrades[i].kind == UPGRADE_HERRING)
2101 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2105 if (upgrades[i].kind == UPGRADE_MINTS)
2107 drawimage(img_mints,
2108 upgrades[i].x - scroll_x, upgrades[i].y,
2111 else if (upgrades[i].kind == UPGRADE_COFFEE)
2113 drawimage(img_coffee,
2114 upgrades[i].x - scroll_x, upgrades[i].y,
2117 else if (upgrades[i].kind == UPGRADE_HERRING)
2119 drawimage(img_golden_herring,
2120 upgrades[i].x - scroll_x, upgrades[i].y,
2128 /* (Bouncy distros): */
2130 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2132 if (bouncy_distros[i].alive)
2134 drawimage(img_distro[0],
2135 bouncy_distros[i].x - scroll_x,
2136 bouncy_distros[i].y,
2142 /* (Broken bricks): */
2144 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2146 if (broken_bricks[i].alive)
2148 src.x = rand() % 16;
2149 src.y = rand() % 16;
2153 dest.x = broken_bricks[i].x - scroll_x;
2154 dest.y = broken_bricks[i].y;
2158 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2165 sprintf(str, "%d", score);
2166 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2167 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2169 sprintf(str, "%d", highscore);
2170 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2171 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2173 if (time_left >= 50 || (frame % 10) < 5)
2175 sprintf(str, "%d", time_left);
2176 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2177 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2180 sprintf(str, "%d", distros);
2181 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2182 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2184 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE);
2186 for(i=0; i < lives; ++i)
2188 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2192 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2197 /* (Update it all!) */
2204 /* --- GAME LOOP! --- */
2209 Uint32 last_time, now_time;
2213 clearscreen(0, 0, 0);
2217 /* Init the game: */
2225 highscore = load_hs();
2228 /* --- MAIN GAME LOOP!!! --- */
2240 last_time = SDL_GetTicks();
2244 /* Handle events: */
2250 /* Handle actions: */
2252 if(!game_pause && !show_menu)
2254 if (game_action() == 0)
2256 /* == 0: no more lives */
2257 /* == -1: continues */
2264 /*Draw the current scene to the screen */
2267 /* Keep playing music: */
2270 if (!playing_music())
2272 switch (current_music)
2275 play_music(level_song, 1);
2278 play_music(herring_song, 1);
2280 case HURRYUP_MUSIC: // keep the compiler happy
2281 case NO_MUSIC: // keep the compiler happy for the moment :-)
2287 /* Time stops in pause mode */
2288 if(game_pause || show_menu )
2293 /* Pause til next frame: */
2295 now_time = SDL_GetTicks();
2296 if (now_time < last_time + FPS)
2297 SDL_Delay(last_time + FPS - now_time);
2302 if ((frame % 10) == 0 && time_left > 0)
2310 while (!done && !quit);
2312 if (playing_music())
2323 /* Initialize the game stuff: */
2335 /* Load data for this level: */
2337 void loadlevel(void)
2348 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2349 bouncy_distros[i].alive = NO;
2351 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2352 broken_bricks[i].alive = NO;
2354 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2355 bouncy_bricks[i].alive = NO;
2357 for (i = 0; i < NUM_BAD_GUYS; i++)
2358 bad_guys[i].alive = NO;
2360 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2361 floating_scores[i].alive = NO;
2363 for (i = 0; i < NUM_UPGRADES; i++)
2364 upgrades[i].alive = NO;
2366 for (i = 0; i < NUM_BULLETS; i++)
2367 bullets[i].alive = NO;
2370 /* Load data file: */
2372 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2373 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2374 fi = fopen(filename, "r");
2385 /* Load header info: */
2390 strcpy(levelname, str);
2391 levelname[strlen(levelname)-1] = '\0';
2395 strcpy(leveltheme, str);
2396 leveltheme[strlen(leveltheme)-1] = '\0';
2400 /* (Time to beat level) */
2402 time_left = atoi(str);
2404 /* (Song file for this level) */
2406 strcpy(song_title, str);
2407 song_title[strlen(song_title)-1] = '\0';
2411 /* (Level background color) */
2413 bkgd_red = atoi(str);
2415 bkgd_green= atoi(str);
2417 bkgd_blue = atoi(str);
2421 level_width = atoi(str);
2424 /* Allocate some space for the line-reading! */
2426 line = (char *) malloc(sizeof(char) * (level_width + 5));
2429 fprintf(stderr, "Couldn't allocate space to load level data!");
2434 /* Load the level lines: */
2436 for (y = 0; y < 15; y++)
2438 if(fgets(line, level_width + 5, fi) == NULL)
2440 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2443 line[strlen(line) - 1] = '\0';
2444 tiles[y] = strdup(line);
2450 /* Activate bad guys: */
2452 for (y = 0; y < 15; y++)
2454 for (x = 0; x < level_width; x++)
2456 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2458 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2473 tux_got_coffee = NO;
2474 tux_invincible_time = 0;
2478 tux_safe = TUX_SAFE_TIME;
2494 score_multiplier = 1;
2495 super_bkgd_time = 0;
2497 counting_distros = NO;
2502 /* set current song/music */
2503 current_music = LEVEL_MUSIC;
2507 clearscreen(0, 0, 0);
2509 sprintf(str, "LEVEL %d", level);
2510 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2512 sprintf(str, "%s", levelname);
2513 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2515 sprintf(str, "TUX x %d", lives);
2516 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2526 /* Load a level-specific graphic... */
2528 SDL_Surface * load_level_image(char * file, int use_alpha)
2532 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2534 return(load_image(fname, use_alpha));
2538 /* Load graphics: */
2540 void loadlevelgfx(void)
2542 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2543 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2545 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2546 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2547 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2548 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2550 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2551 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2552 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2553 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2555 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2556 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2557 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2558 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2564 void loadlevelsong(void)
2569 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2570 strlen(song_title) + 8));
2572 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2574 level_song = load_song(song_path);
2580 /* Free graphics data for this level: */
2582 void unloadlevelgfx(void)
2586 for (i = 0; i < 2; i++)
2588 SDL_FreeSurface(img_brick[i]);
2590 for (i = 0; i < 4; i++)
2592 SDL_FreeSurface(img_solid[i]);
2593 SDL_FreeSurface(img_bkgd[0][i]);
2594 SDL_FreeSurface(img_bkgd[1][i]);
2599 /* Free music data for this level: */
2601 void unloadlevelsong(void)
2603 free_music(level_song);
2607 /* Load graphics/sounds shared between all levels: */
2609 void loadshared(void)
2612 char * herring_song_path; /* for loading herring song*/
2616 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2619 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2622 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2625 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2628 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2631 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2634 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2637 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2640 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2643 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2646 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2649 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2652 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2656 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2658 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2661 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2664 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2668 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2671 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2675 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2679 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2683 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2686 ducktux_right = load_image(DATA_PREFIX
2687 "/images/shared/ducktux-right.png",
2690 ducktux_left = load_image(DATA_PREFIX
2691 "/images/shared/ducktux-left.png",
2694 skidtux_right = load_image(DATA_PREFIX
2695 "/images/shared/skidtux-right.png",
2698 skidtux_left = load_image(DATA_PREFIX
2699 "/images/shared/skidtux-left.png",
2705 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2707 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2714 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2716 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2719 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2722 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2728 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2729 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2735 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2737 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2743 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2746 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2749 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2752 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2756 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2759 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2762 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2765 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2773 img_bsod_left[0] = load_image(DATA_PREFIX
2774 "/images/shared/bsod-left-0.png",
2777 img_bsod_left[1] = load_image(DATA_PREFIX
2778 "/images/shared/bsod-left-1.png",
2781 img_bsod_left[2] = load_image(DATA_PREFIX
2782 "/images/shared/bsod-left-2.png",
2785 img_bsod_left[3] = load_image(DATA_PREFIX
2786 "/images/shared/bsod-left-3.png",
2789 img_bsod_right[0] = load_image(DATA_PREFIX
2790 "/images/shared/bsod-right-0.png",
2793 img_bsod_right[1] = load_image(DATA_PREFIX
2794 "/images/shared/bsod-right-1.png",
2797 img_bsod_right[2] = load_image(DATA_PREFIX
2798 "/images/shared/bsod-right-2.png",
2801 img_bsod_right[3] = load_image(DATA_PREFIX
2802 "/images/shared/bsod-right-3.png",
2805 img_bsod_squished_left = load_image(DATA_PREFIX
2806 "/images/shared/bsod-squished-left.png",
2809 img_bsod_squished_right = load_image(DATA_PREFIX
2810 "/images/shared/bsod-squished-right.png",
2813 img_bsod_falling_left = load_image(DATA_PREFIX
2814 "/images/shared/bsod-falling-left.png",
2817 img_bsod_falling_right = load_image(DATA_PREFIX
2818 "/images/shared/bsod-falling-right.png",
2824 img_laptop_left[0] = load_image(DATA_PREFIX
2825 "/images/shared/laptop-left-0.png",
2828 img_laptop_left[1] = load_image(DATA_PREFIX
2829 "/images/shared/laptop-left-1.png",
2832 img_laptop_left[2] = load_image(DATA_PREFIX
2833 "/images/shared/laptop-left-2.png",
2836 img_laptop_right[0] = load_image(DATA_PREFIX
2837 "/images/shared/laptop-right-0.png",
2840 img_laptop_right[1] = load_image(DATA_PREFIX
2841 "/images/shared/laptop-right-1.png",
2844 img_laptop_right[2] = load_image(DATA_PREFIX
2845 "/images/shared/laptop-right-2.png",
2848 img_laptop_flat_left = load_image(DATA_PREFIX
2849 "/images/shared/laptop-flat-left.png",
2852 img_laptop_flat_right = load_image(DATA_PREFIX
2853 "/images/shared/laptop-flat-right.png",
2856 img_laptop_falling_left =
2857 load_image(DATA_PREFIX
2858 "/images/shared/laptop-falling-left.png",
2861 img_laptop_falling_right =
2862 load_image(DATA_PREFIX
2863 "/images/shared/laptop-falling-right.png",
2869 img_money_left[0] = load_image(DATA_PREFIX
2870 "/images/shared/bag-left-0.png",
2873 img_money_left[1] = load_image(DATA_PREFIX
2874 "/images/shared/bag-left-1.png",
2877 img_money_right[0] = load_image(DATA_PREFIX
2878 "/images/shared/bag-right-0.png",
2881 img_money_right[1] = load_image(DATA_PREFIX
2882 "/images/shared/bag-right-1.png",
2889 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2890 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2895 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2897 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2903 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2906 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2909 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2912 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2917 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
2922 img_golden_herring =
2923 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2927 /* Super background: */
2929 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2933 /* Sound effects: */
2935 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
2936 // initialize sounds[i] with the correct pointer's value:
2937 // NULL or something else. And it will be dangerous to
2938 // play with not-initialized pointers.
2939 // This is also true with if (use_music)
2940 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
2942 for (i = 0; i < NUM_SOUNDS; i++)
2943 sounds[i] = load_sound(soundfilenames[i]);
2946 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2947 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
2949 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
2951 herring_song = load_song(herring_song_path);
2953 free(herring_song_path);
2958 /* Free shared data: */
2960 void unloadshared(void)
2964 for (i = 0; i < 3; i++)
2966 SDL_FreeSurface(tux_right[i]);
2967 SDL_FreeSurface(tux_left[i]);
2968 SDL_FreeSurface(bigtux_right[i]);
2969 SDL_FreeSurface(bigtux_left[i]);
2972 SDL_FreeSurface(bigtux_right_jump);
2973 SDL_FreeSurface(bigtux_left_jump);
2975 for (i = 0; i < 2; i++)
2977 SDL_FreeSurface(cape_right[i]);
2978 SDL_FreeSurface(cape_left[i]);
2979 SDL_FreeSurface(bigcape_right[i]);
2980 SDL_FreeSurface(bigcape_left[i]);
2983 SDL_FreeSurface(ducktux_left);
2984 SDL_FreeSurface(ducktux_right);
2986 SDL_FreeSurface(skidtux_left);
2987 SDL_FreeSurface(skidtux_right);
2989 for (i = 0; i < 4; i++)
2991 SDL_FreeSurface(img_bsod_left[i]);
2992 SDL_FreeSurface(img_bsod_right[i]);
2995 SDL_FreeSurface(img_bsod_squished_left);
2996 SDL_FreeSurface(img_bsod_squished_right);
2998 SDL_FreeSurface(img_bsod_falling_left);
2999 SDL_FreeSurface(img_bsod_falling_right);
3001 for (i = 0; i < 3; i++)
3003 SDL_FreeSurface(img_laptop_left[i]);
3004 SDL_FreeSurface(img_laptop_right[i]);
3007 SDL_FreeSurface(img_laptop_flat_left);
3008 SDL_FreeSurface(img_laptop_flat_right);
3010 SDL_FreeSurface(img_laptop_falling_left);
3011 SDL_FreeSurface(img_laptop_falling_right);
3013 for (i = 0; i < 2; i++)
3015 SDL_FreeSurface(img_money_left[i]);
3016 SDL_FreeSurface(img_money_right[i]);
3019 SDL_FreeSurface(img_box_full);
3020 SDL_FreeSurface(img_box_empty);
3022 SDL_FreeSurface(img_water);
3023 for (i = 0; i < 3; i++)
3024 SDL_FreeSurface(img_waves[i]);
3026 SDL_FreeSurface(img_pole);
3027 SDL_FreeSurface(img_poletop);
3029 for (i = 0; i < 2; i++)
3030 SDL_FreeSurface(img_flag[i]);
3032 SDL_FreeSurface(img_mints);
3033 SDL_FreeSurface(img_coffee);
3035 for (i = 0; i < 4; i++)
3037 SDL_FreeSurface(img_distro[i]);
3038 SDL_FreeSurface(img_cloud[0][i]);
3039 SDL_FreeSurface(img_cloud[1][i]);
3042 SDL_FreeSurface(img_golden_herring);
3044 for (i = 0; i < NUM_SOUNDS; i++)
3045 free_chunk(sounds[i]);
3047 /* free the herring song */
3048 free_music( herring_song );
3052 /* Draw a tile on the screen: */
3054 void drawshape(int x, int y, unsigned char c)
3058 if (c == 'X' || c == 'x')
3059 drawimage(img_brick[0], x, y, NO_UPDATE);
3060 else if (c == 'Y' || c == 'y')
3061 drawimage(img_brick[1], x, y, NO_UPDATE);
3062 else if (c == 'A' || c =='B' || c == '!')
3063 drawimage(img_box_full, x, y, NO_UPDATE);
3065 drawimage(img_box_empty, x, y, NO_UPDATE);
3066 else if (c >= 'C' && c <= 'F')
3067 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3068 else if (c >= 'c' && c <= 'f')
3069 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3070 else if (c >= 'G' && c <= 'J')
3071 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3072 else if (c >= 'g' && c <= 'j')
3073 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3075 drawimage(img_solid[0], x, y, NO_UPDATE);
3077 drawimage(img_solid[1], x, y, NO_UPDATE);
3079 drawimage(img_solid[2], x, y, NO_UPDATE);
3081 drawimage(img_solid[3], x, y, NO_UPDATE);
3084 z = (frame / 2) % 6;
3087 drawimage(img_distro[z], x, y, NO_UPDATE);
3089 drawimage(img_distro[2], x, y, NO_UPDATE);
3091 drawimage(img_distro[1], x, y, NO_UPDATE);
3095 z = (frame / 3) % 3;
3097 drawimage(img_waves[z], x, y, NO_UPDATE);
3100 drawimage(img_poletop, x, y, NO_UPDATE);
3103 drawimage(img_pole, x, y, NO_UPDATE);
3105 /* Mark this as the end position of the level! */
3111 z = (frame / 3) % 2;
3113 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3116 drawimage(img_water, x, y, NO_UPDATE);
3120 /* What shape is at some position? */
3122 unsigned char shape(int x, int y, int sx)
3128 xx = ((x + sx) / 32);
3130 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3141 int issolid(int x, int y, int sx)
3147 if (isbrick(x, y, sx) ||
3148 isbrick(x + 31, y, sx) ||
3150 isice(x + 31, y, sx) ||
3151 (shape(x, y, sx) == '[' ||
3152 shape(x + 31, y, sx) == '[') ||
3153 (shape(x, y, sx) == '=' ||
3154 shape(x + 31, y, sx) == '=') ||
3155 (shape(x, y, sx) == ']' ||
3156 shape(x + 31, y, sx) == ']') ||
3157 (shape(x, y, sx) == 'A' ||
3158 shape(x + 31, y, sx) == 'A') ||
3159 (shape(x, y, sx) == 'B' ||
3160 shape(x + 31, y, sx) == 'B') ||
3161 (shape(x, y, sx) == '!' ||
3162 shape(x + 31, y, sx) == '!') ||
3163 (shape(x, y, sx) == 'a' ||
3164 shape(x + 31, y, sx) == 'a'))
3173 /* Is it a brick? */
3175 int isbrick(int x, int y, int sx)
3181 if (shape(x, y, sx) == 'X' ||
3182 shape(x, y, sx) == 'x' ||
3183 shape(x, y, sx) == 'Y' ||
3184 shape(x, y, sx) == 'y')
3195 int isice(int x, int y, int sx)
3201 if (shape(x, y, sx) == '#')
3210 /* Is it a full box? */
3212 int isfullbox(int x, int y, int sx)
3218 if (shape(x, y, sx) == 'A' ||
3219 shape(x, y, sx) == 'B' ||
3220 shape(x, y, sx) == '!')
3229 /* Edit a piece of the map! */
3231 void change(int x, int y, int sx, unsigned char c)
3236 xx = ((x + sx) / 32);
3238 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3243 /* Break a brick: */
3245 void trybreakbrick(int x, int y, int sx)
3247 if (isbrick(x, y, sx))
3249 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3251 /* Get a distro from it: */
3253 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3256 if (counting_distros == NO)
3258 counting_distros = YES;
3259 distro_counter = 50;
3262 if (distro_counter <= 0)
3263 change(x, y, sx, 'a');
3265 play_sound(sounds[SND_DISTRO]);
3266 score = score + SCORE_DISTRO;
3271 /* Get rid of it: */
3273 change(x, y, sx, '.');
3277 /* Replace it with broken bits: */
3279 add_broken_brick(((x + sx + 1) / 32) * 32,
3283 /* Get some score: */
3285 play_sound(sounds[SND_BRICK]);
3286 score = score + SCORE_BRICK;
3291 /* Bounce a brick: */
3293 void bumpbrick(int x, int y, int sx)
3295 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3298 play_sound(sounds[SND_BRICK]);
3304 void tryemptybox(int x, int y, int sx)
3306 if (isfullbox(x, y, sx))
3308 if (shape(x, y, sx) == 'A')
3310 /* Box with a distro! */
3312 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3313 (y / 32) * 32 - 32);
3315 play_sound(sounds[SND_DISTRO]);
3316 score = score + SCORE_DISTRO;
3319 else if (shape(x, y, sx) == 'B')
3321 /* Add an upgrade! */
3323 if (tux_size == SMALL)
3325 /* Tux is small, add mints! */
3327 add_upgrade(((x + sx + 1) / 32) * 32,
3333 /* Tux is big, add coffee: */
3335 add_upgrade(((x + sx + 1) / 32) * 32,
3340 play_sound(sounds[SND_UPGRADE]);
3342 else if (shape(x, y, sx) == '!')
3344 /* Add a golden herring */
3346 add_upgrade(((x + sx + 1) / 32) * 32,
3351 /* Empty the box: */
3353 change(x, y, sx, 'a');
3358 /* Try to grab a distro: */
3360 void trygrabdistro(int x, int y, int sx, int bounciness)
3362 if (shape(x, y, sx) == '$')
3364 change(x, y, sx, '.');
3365 play_sound(sounds[SND_DISTRO]);
3367 if (bounciness == BOUNCE)
3369 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3373 score = score + SCORE_DISTRO;
3379 /* Add a bouncy distro: */
3381 void add_bouncy_distro(int x, int y)
3387 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3389 if (!bouncy_distros[i].alive)
3395 bouncy_distros[found].alive = YES;
3396 bouncy_distros[found].x = x;
3397 bouncy_distros[found].y = y;
3398 bouncy_distros[found].ym = -6;
3403 /* Add broken brick pieces: */
3405 void add_broken_brick(int x, int y)
3407 add_broken_brick_piece(x, y, -4, -16);
3408 add_broken_brick_piece(x, y + 16, -6, -12);
3410 add_broken_brick_piece(x + 16, y, 4, -16);
3411 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3415 /* Add a broken brick piece: */
3417 void add_broken_brick_piece(int x, int y, int xm, int ym)
3423 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3425 if (!broken_bricks[i].alive)
3431 broken_bricks[found].alive = YES;
3432 broken_bricks[found].x = x;
3433 broken_bricks[found].y = y;
3434 broken_bricks[found].xm = xm;
3435 broken_bricks[found].ym = ym;
3440 /* Add a bouncy brick piece: */
3442 void add_bouncy_brick(int x, int y)
3448 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3450 if (!bouncy_bricks[i].alive)
3456 bouncy_bricks[found].alive = YES;
3457 bouncy_bricks[found].x = x;
3458 bouncy_bricks[found].y = y;
3459 bouncy_bricks[found].offset = 0;
3460 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3461 bouncy_bricks[found].shape = shape(x, y, 0);
3466 /* Add a bad guy: */
3468 void add_bad_guy(int x, int y, int kind)
3474 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3476 if (!bad_guys[i].alive)
3482 bad_guys[found].alive = YES;
3483 bad_guys[found].mode = NORMAL;
3484 bad_guys[found].dying = NO;
3485 bad_guys[found].timer = 0;
3486 bad_guys[found].kind = kind;
3487 bad_guys[found].x = x;
3488 bad_guys[found].y = y;
3489 bad_guys[found].xm = 0;
3490 bad_guys[found].ym = 0;
3491 bad_guys[found].dir = LEFT;
3492 bad_guys[found].seen = NO;
3499 void add_score(int x, int y, int s)
3504 /* Add the score: */
3509 /* Add a floating score thing to the game: */
3513 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3515 if (!floating_scores[i].alive)
3522 floating_scores[found].alive = YES;
3523 floating_scores[found].x = x;
3524 floating_scores[found].y = y - 16;
3525 floating_scores[found].timer = 8;
3526 floating_scores[found].value = s;
3531 /* Try to bump a bad guy from below: */
3533 void trybumpbadguy(int x, int y, int sx)
3540 for (i = 0; i < NUM_BAD_GUYS; i++)
3542 if (bad_guys[i].alive &&
3543 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3544 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3546 if (bad_guys[i].kind == BAD_BSOD ||
3547 bad_guys[i].kind == BAD_LAPTOP)
3549 bad_guys[i].dying = FALLING;
3550 bad_guys[i].ym = -8;
3551 play_sound(sounds[SND_FALL]);
3559 for (i = 0; i < NUM_UPGRADES; i++)
3561 if (upgrades[i].alive && upgrades[i].height == 32 &&
3562 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3563 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3565 upgrades[i].xm = -upgrades[i].xm;
3566 upgrades[i].ym = -8;
3567 play_sound(sounds[SND_BUMP_UPGRADE]);
3573 /* Add an upgrade: */
3575 void add_upgrade(int x, int y, int kind)
3581 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3583 if (!upgrades[i].alive)
3589 upgrades[found].alive = YES;
3590 upgrades[found].kind = kind;
3591 upgrades[found].x = x;
3592 upgrades[found].y = y;
3593 upgrades[found].xm = 4;
3594 upgrades[found].ym = -4;
3595 upgrades[found].height = 0;
3602 void killtux(int mode)
3606 play_sound(sounds[SND_HURT]);
3608 if (tux_dir == RIGHT)
3610 else if (tux_dir == LEFT)
3613 if (mode == SHRINK && tux_size == BIG)
3616 tux_got_coffee = NO;
3620 tux_safe = TUX_SAFE_TIME;
3631 void add_bullet(int x, int y, int dir, int xm)
3637 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3639 if (!bullets[i].alive)
3645 bullets[found].alive = YES;
3649 bullets[found].x = x + 32;
3650 bullets[found].xm = BULLET_XM + xm;
3654 bullets[found].x = x;
3655 bullets[found].xm = -BULLET_XM + xm;
3658 bullets[found].y = y;
3659 bullets[found].ym = BULLET_STARTING_YM;
3661 play_sound(sounds[SND_SHOOT]);
3666 void drawendscreen(void)
3670 clearscreen(0, 0, 0);
3672 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3674 sprintf(str, "SCORE: %d", score);
3675 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3677 sprintf(str, "DISTROS: %d", distros);
3678 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3684 void drawresultscreen(void)
3688 clearscreen(0, 0, 0);
3690 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3692 sprintf(str, "SCORE: %d", score);
3693 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3695 sprintf(str, "DISTROS: %d", distros);
3696 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3699 /*SDL_Delay(2000);*/