7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 9, 2003
19 #include <SDL_image.h>
23 #include <sys/types.h>
33 #include "high_scores.h"
57 char * soundfilenames[NUM_SOUNDS] = {
58 DATA_PREFIX "/sounds/jump.wav",
59 DATA_PREFIX "/sounds/bigjump.wav",
60 DATA_PREFIX "/sounds/skid.wav",
61 DATA_PREFIX "/sounds/distro.wav",
62 DATA_PREFIX "/sounds/herring.wav",
63 DATA_PREFIX "/sounds/brick.wav",
64 DATA_PREFIX "/sounds/hurt.wav",
65 DATA_PREFIX "/sounds/squish.wav",
66 DATA_PREFIX "/sounds/fall.wav",
67 DATA_PREFIX "/sounds/ricochet.wav",
68 DATA_PREFIX "/sounds/bump-upgrade.wav",
69 DATA_PREFIX "/sounds/upgrade.wav",
70 DATA_PREFIX "/sounds/excellent.wav",
71 DATA_PREFIX "/sounds/coffee.wav",
72 DATA_PREFIX "/sounds/shoot.wav",
73 DATA_PREFIX "/sounds/lifeup.wav"
77 /* Local variables: */
79 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause, done, quit,
80 tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
81 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
82 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
83 super_bkgd_time, time_left, tux_invincible_time, endpos,
84 counting_distros, distro_counter;
85 int bkgd_red, bkgd_green, bkgd_blue, level_width;
86 int left, right, up, down, fire, old_fire;
87 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
88 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
89 SDL_Surface * img_bkgd[2][4];
90 SDL_Surface * img_golden_herring;
91 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
92 * img_laptop_left[3], * img_laptop_right[3],
93 * img_money_left[2], * img_money_right[2];
94 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
95 * img_bsod_falling_left, * img_bsod_falling_right,
96 * img_laptop_flat_left, * img_laptop_flat_right,
97 * img_laptop_falling_left, * img_laptop_falling_right;
98 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
99 * img_super_bkgd, * img_bullet, * img_red_glow;
100 SDL_Surface * img_cloud[2][4];
101 SDL_Surface * tux_right[3], * tux_left[3],
102 * bigtux_right[3], * bigtux_left[3],
103 * bigtux_right_jump, * bigtux_left_jump,
104 * cape_right[2], * cape_left[2],
105 * bigcape_right[2], * bigcape_left[2],
106 * ducktux_right, * ducktux_left,
107 * skidtux_right, * skidtux_left;
111 unsigned char * tiles[15];
112 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
113 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
114 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
115 bad_guy_type bad_guys[NUM_BAD_GUYS];
116 floating_score_type floating_scores[NUM_FLOATING_SCORES];
117 upgrade_type upgrades[NUM_UPGRADES];
118 bullet_type bullets[NUM_BULLETS];
124 /* Local function prototypes: */
127 void loadlevel(void);
128 void loadlevelgfx(void);
129 void loadlevelsong(void);
130 void unloadlevelgfx(void);
131 void unloadlevelsong(void);
132 void loadshared(void);
133 void unloadshared(void);
134 void drawshape(int x, int y, unsigned char c);
135 unsigned char shape(int x, int y, int sx);
136 int issolid(int x, int y, int sx);
137 int isbrick(int x, int y, int sx);
138 int isice(int x, int y, int sx);
139 int isfullbox(int x, int y, int sx);
140 void change(int x, int y, int sx, unsigned char c);
141 void trybreakbrick(int x, int y, int sx);
142 void bumpbrick(int x, int y, int sx);
143 void tryemptybox(int x, int y, int sx);
144 void trygrabdistro(int x, int y, int sx, int bounciness);
145 void add_bouncy_distro(int x, int y);
146 void add_broken_brick(int x, int y);
147 void add_broken_brick_piece(int x, int y, int xm, int ym);
148 void add_bouncy_brick(int x, int y);
149 void add_bad_guy(int x, int y, int kind);
150 void add_score(int x, int y, int s);
151 void trybumpbadguy(int x, int y, int sx);
152 void add_upgrade(int x, int y, int kind);
153 void killtux(int mode);
154 void add_bullet(int x, int y, int dir, int xm);
155 void drawendscreen(void);
156 void drawresultscreen(void);
158 /* --- GAME EVENT! --- */
160 void game_event(void)
163 while (SDL_PollEvent(&event))
166 if (event.type == SDL_QUIT)
168 /* Quit event - quit: */
172 else if (event.type == SDL_KEYDOWN)
176 key = event.key.keysym.sym;
178 if (key == SDLK_ESCAPE)
180 /* Escape: Quit the game and return to main menu: */
184 else if (key == SDLK_RIGHT)
188 else if (key == SDLK_LEFT)
192 else if (key == SDLK_UP)
196 else if (key == SDLK_DOWN)
200 else if (key == SDLK_LCTRL)
205 else if (event.type == SDL_KEYUP)
209 key = event.key.keysym.sym;
211 if (key == SDLK_RIGHT)
215 else if (key == SDLK_LEFT)
219 else if (key == SDLK_UP)
223 else if (key == SDLK_DOWN)
227 else if (key == SDLK_LCTRL)
231 else if (key == SDLK_p)
238 else if (key == SDLK_TAB)
240 tux_size = !tux_size;
242 else if (key == SDLK_END)
246 else if (key == SDLK_SPACE)
252 else if (event.type == SDL_JOYAXISMOTION)
254 if (event.jaxis.axis == JOY_X)
256 if (event.jaxis.value < -256)
261 if (event.jaxis.value > 256)
266 else if (event.jaxis.axis == JOY_Y)
268 if (event.jaxis.value > 256)
274 else if (event.type == SDL_JOYBUTTONDOWN)
276 if (event.jbutton.button == JOY_A)
278 else if (event.jbutton.button == JOY_B)
281 else if (event.type == SDL_JOYBUTTONUP)
283 if (event.jbutton.button == JOY_A)
285 else if (event.jbutton.button == JOY_B)
293 /* --- GAME ACTION! --- */
295 int game_action(void)
299 /* --- HANDLE TUX! --- */
301 /* Handle key and joystick state: */
303 if (!(tux_dying || next_level))
305 if (right == DOWN && left == UP)
309 if (tux_xm < -SKID_XM && !tux_skidding &&
312 tux_skidding = SKID_TIME;
314 play_sound(sounds[SND_SKID]);
320 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
328 if (tux_dir == RIGHT)
330 /* Facing the direction we're jumping? Go full-speed: */
334 tux_xm = tux_xm + WALK_SPEED;
336 if (tux_xm > MAX_WALK_XM)
337 tux_xm = MAX_WALK_XM;
339 else if (fire == DOWN)
341 tux_xm = tux_xm + RUN_SPEED;
343 if (tux_xm > MAX_RUN_XM)
349 /* Not facing the direction we're jumping?
352 tux_xm = tux_xm + WALK_SPEED / 2;
354 if (tux_xm > MAX_WALK_XM / 2)
355 tux_xm = MAX_WALK_XM / 2;
359 else if (left == DOWN && right == UP)
363 if (tux_xm > SKID_XM && !tux_skidding &&
366 tux_skidding = SKID_TIME;
367 play_sound(sounds[SND_SKID]);
372 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
382 /* Facing the direction we're jumping? Go full-speed: */
386 tux_xm = tux_xm - WALK_SPEED;
388 if (tux_xm < -MAX_WALK_XM)
389 tux_xm = -MAX_WALK_XM;
391 else if (fire == DOWN)
393 tux_xm = tux_xm - RUN_SPEED;
395 if (tux_xm < -MAX_RUN_XM)
396 tux_xm = -MAX_RUN_XM;
401 /* Not facing the direction we're jumping?
404 tux_xm = tux_xm - WALK_SPEED / 2;
406 if (tux_xm < -MAX_WALK_XM / 2)
407 tux_xm = -MAX_WALK_XM / 2;
415 if (tux_x >= endpos && endpos != 0)
425 if (jump_counter == 0)
429 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
432 /* If they're not on the ground, or are currently moving
433 vertically, don't jump! */
435 jump_counter = MAX_JUMP_COUNT;
439 /* Make sure we're not standing back up into a solid! */
441 if (tux_size == SMALL || tux_duck == NO ||
442 !issolid(tux_x, tux_y, scroll_x))
446 if (tux_size == SMALL)
447 play_sound(sounds[SND_JUMP]);
449 play_sound(sounds[SND_BIGJUMP]);
455 /* Keep jumping for a while: */
457 if (jump_counter < MAX_JUMP_COUNT)
459 tux_ym = tux_ym - JUMP_SPEED;
469 if (fire == DOWN && old_fire == UP && tux_got_coffee)
471 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
484 if (tux_size == BIG && tux_duck == YES)
486 /* Make sure we're not standing back up into a solid! */
488 if (!issolid(tux_x, tux_y - 32, scroll_x))
494 } /* (tux_dying || next_level) */
497 /* Tux either died, or reached the end of a level! */
509 /* End of a level! */
517 tux_ym = tux_ym + GRAVITY;
525 /* No more lives!? */
531 if (score > highscore)
538 /* Either way, (re-)load the (next) level... */
549 tux_x = tux_x + tux_xm;
550 tux_y = tux_y + tux_ym;
553 /* Keep tux in bounds: */
557 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
559 /* Scroll the screen in past center: */
561 scroll_x = scroll_x + (tux_x - 320);
564 if (scroll_x > ((level_width * 32) - 640))
565 scroll_x = ((level_width * 32) - 640);
567 else if (tux_x > 608)
569 /* ... unless there's no more to scroll! */
579 if (issolid(tux_x, tux_y + 31, scroll_x) &&
580 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
582 while (issolid(tux_x, tux_y + 31, scroll_x))
593 if (issolid(tux_x, tux_y, scroll_x) &&
594 !issolid(tux_x - tux_xm, tux_y, scroll_x))
596 while (issolid(tux_x, tux_y, scroll_x))
607 if (issolid(tux_x, tux_y + 31, scroll_x))
609 /* Set down properly: */
611 while (issolid(tux_x, tux_y + 31, scroll_x))
620 /* Reset score multiplier (for mutli-hits): */
623 score_multiplier = 1;
633 /* Bump into things: */
635 if (issolid(tux_x, tux_y, scroll_x) ||
636 (tux_size == BIG && !tux_duck &&
637 (issolid(tux_x, tux_y - 32, scroll_x))))
639 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
640 (tux_size == SMALL || tux_duck ||
641 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
643 tux_x = tux_x - tux_xm;
646 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
647 (tux_size == SMALL || tux_duck ||
648 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
656 /* Break bricks and empty boxes: */
660 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
661 isfullbox(tux_x, tux_y - 32, scroll_x))
663 trygrabdistro(tux_x, tux_y - 64, scroll_x,
665 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
667 if (isfullbox(tux_x, tux_y - 32,
670 bumpbrick(tux_x, tux_y - 32,
674 trybreakbrick(tux_x, tux_y - 32, scroll_x);
675 tryemptybox(tux_x, tux_y - 32, scroll_x);
678 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
679 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
681 trygrabdistro(tux_x + 31,
685 trybumpbadguy(tux_x + 31,
689 if (isfullbox(tux_x + 31, tux_y - 32,
692 bumpbrick(tux_x + 31, tux_y - 32,
696 trybreakbrick(tux_x + 31,
699 tryemptybox(tux_x + 31,
706 if (isbrick(tux_x, tux_y, scroll_x) ||
707 isfullbox(tux_x, tux_y, scroll_x))
709 trygrabdistro(tux_x, tux_y - 32, scroll_x,
711 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
712 if (isfullbox(tux_x, tux_y, scroll_x))
713 bumpbrick(tux_x, tux_y, scroll_x);
714 trybreakbrick(tux_x, tux_y, scroll_x);
715 tryemptybox(tux_x, tux_y, scroll_x);
718 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
719 isfullbox(tux_x + 31, tux_y, scroll_x))
721 trygrabdistro(tux_x + 31,
725 trybumpbadguy(tux_x + 31,
728 if (isfullbox(tux_x + 31, tux_y, scroll_x))
729 bumpbrick(tux_x + 31, tux_y, scroll_x);
730 trybreakbrick(tux_x + 31, tux_y, scroll_x);
731 tryemptybox(tux_x + 31, tux_y, scroll_x);
737 /* It's a brick and we're small, make the brick
738 bounce, and grab any distros above it: */
740 if (isbrick(tux_x, tux_y, scroll_x) ||
741 isfullbox(tux_x, tux_y, scroll_x))
743 trygrabdistro(tux_x, tux_y - 32, scroll_x,
745 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
746 bumpbrick(tux_x, tux_y, scroll_x);
747 tryemptybox(tux_x, tux_y, scroll_x);
750 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
751 isfullbox(tux_x + 31, tux_y, scroll_x))
753 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
755 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
756 bumpbrick(tux_x + 31, tux_y, scroll_x);
757 tryemptybox(tux_x + 31, tux_y, scroll_x);
761 /* Get a distro from a brick? */
763 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
764 shape(tux_x, tux_y, scroll_x) == 'y')
766 add_bouncy_distro(((tux_x + scroll_x + 1)
770 if (counting_distros == NO)
772 counting_distros = YES;
773 distro_counter = 100;
776 if (distro_counter <= 0)
777 change(tux_x, tux_y, scroll_x, 'a');
779 play_sound(sounds[SND_DISTRO]);
780 score = score + SCORE_DISTRO;
783 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
784 shape(tux_x + 31, tux_y, scroll_x) == 'y')
786 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
790 if (counting_distros == NO)
792 counting_distros = YES;
793 distro_counter = 100;
796 if (distro_counter <= 0)
797 change(tux_x + 31, tux_y, scroll_x, 'a');
799 play_sound(sounds[SND_DISTRO]);
800 score = score + SCORE_DISTRO;
808 tux_y = (tux_y / 32) * 32 + 30;
814 tux_y = (tux_y / 32) * 32 - 32;
819 jump_counter = MAX_JUMP_COUNT;
829 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
830 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
832 if (tux_size == BIG && !tux_duck)
834 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
835 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
840 /* Enough distros for a One-up? */
842 if (distros >= DISTROS_LIFEUP)
844 distros = distros - DISTROS_LIFEUP;
845 if(lives < MAX_LIVES)
847 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
851 /* Keep in-bounds, vertically: */
855 else if (tux_y > 480)
861 /* Slow down horizontally: */
865 if (right == UP && left == UP)
867 if (isice(tux_x, tux_y + 32, scroll_x) ||
868 !issolid(tux_x, tux_y + 32, scroll_x))
870 /* Slowly on ice or in air: */
879 /* Quickly, otherwise: */
886 /* Drop vertically: */
888 if (!issolid(tux_x, tux_y + 32, scroll_x))
890 tux_ym = tux_ym + GRAVITY;
902 /* ---- DONE HANDLING TUX! --- */
905 /* Handle bouncy distros: */
907 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
909 if (bouncy_distros[i].alive)
911 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
913 bouncy_distros[i].ym++;
915 if (bouncy_distros[i].ym >= 0)
916 bouncy_distros[i].alive = NO;
921 /* Handle broken bricks: */
923 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
925 if (broken_bricks[i].alive)
927 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
928 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
930 broken_bricks[i].ym++;
932 if (broken_bricks[i].ym >= 0)
933 broken_bricks[i].alive = NO;
938 /* Handle distro counting: */
940 if (counting_distros == YES)
944 if (distro_counter <= 0)
945 counting_distros = -1;
949 /* Handle bouncy bricks: */
951 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
953 if (bouncy_bricks[i].alive)
955 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
956 bouncy_bricks[i].offset_m);
960 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
961 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
966 if (bouncy_bricks[i].offset == 0)
967 bouncy_bricks[i].alive = NO;
972 /* Handle floating scores: */
974 for (i = 0; i < NUM_FLOATING_SCORES; i++)
976 if (floating_scores[i].alive)
978 floating_scores[i].y = floating_scores[i].y - 2;
979 floating_scores[i].timer--;
981 if (floating_scores[i].timer <= 0)
982 floating_scores[i].alive = NO;
987 /* Handle bullets: */
989 for (i = 0; i < NUM_BULLETS; i++)
991 if (bullets[i].alive)
993 bullets[i].x = bullets[i].x + bullets[i].xm;
994 bullets[i].y = bullets[i].y + bullets[i].ym;
996 if (issolid(bullets[i].x, bullets[i].y, 0))
998 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
999 bullets[i].alive = NO;
1002 if (bullets[i].ym >= 0)
1004 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1006 bullets[i].ym = -bullets[i].ym;
1010 bullets[i].ym = bullets[i].ym + GRAVITY;
1012 if (bullets[i].x < scroll_x ||
1013 bullets[i].x > scroll_x + 640)
1015 bullets[i].alive = NO;
1020 if (bullets[i].alive)
1022 for (j = 0; j < NUM_BAD_GUYS; j++)
1024 if (bad_guys[j].alive && !bad_guys[j].dying)
1026 if (bullets[i].x >= bad_guys[j].x - 4 &&
1027 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1028 bullets[i].y >= bad_guys[j].y - 4 &&
1029 bullets[i].y <= bad_guys[j].y + 32 + 4)
1031 /* Kill the bad guy! */
1033 bullets[i].alive = 0;
1034 bad_guys[j].dying = FALLING;
1035 bad_guys[j].ym = -8;
1038 /* Gain some points: */
1040 if (bad_guys[j].kind == BAD_BSOD)
1042 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1043 50 * score_multiplier);
1045 else if (bad_guys[j].kind == BAD_LAPTOP)
1047 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1048 25 * score_multiplier);
1052 /* Play death sound: */
1053 play_sound(sounds[SND_FALL]);
1061 /* Handle background timer: */
1063 if (super_bkgd_time)
1067 /* Handle invincibility timer: */
1069 if (tux_invincible_time)
1070 tux_invincible_time--;
1073 /* Handle upgrades: */
1075 for (i = 0; i < NUM_UPGRADES; i++)
1077 if (upgrades[i].alive)
1079 if (upgrades[i].height < 32)
1083 upgrades[i].height++;
1089 if (upgrades[i].kind == UPGRADE_MINTS ||
1090 upgrades[i].kind == UPGRADE_HERRING)
1092 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1093 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1095 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1096 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1098 if (upgrades[i].ym > 0)
1100 if (upgrades[i].kind == UPGRADE_MINTS)
1104 else if (upgrades[i].kind == UPGRADE_HERRING)
1106 upgrades[i].ym = -24;
1109 upgrades[i].y = (upgrades[i].y / 32) * 32;
1113 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1115 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1117 upgrades[i].xm = -upgrades[i].xm;
1122 /* Off the screen? Kill it! */
1124 if (upgrades[i].x < scroll_x)
1125 upgrades[i].alive = NO;
1128 /* Did the player grab it? */
1130 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1131 tux_x + scroll_x <= upgrades[i].x + 32 &&
1132 tux_y >= upgrades[i].y - 32 &&
1133 tux_y <= upgrades[i].y + 32)
1135 /* Remove the upgrade: */
1137 upgrades[i].alive = NO;
1140 /* Affect the player: */
1142 if (upgrades[i].kind == UPGRADE_MINTS)
1144 play_sound(sounds[SND_EXCELLENT]);
1146 super_bkgd_time = 8;
1148 else if (upgrades[i].kind == UPGRADE_COFFEE)
1150 play_sound(sounds[SND_COFFEE]);
1151 tux_got_coffee = YES;
1152 super_bkgd_time = 4;
1154 else if (upgrades[i].kind == UPGRADE_HERRING)
1156 play_sound(sounds[SND_HERRING]);
1157 tux_invincible_time = 200;
1158 super_bkgd_time = 4;
1166 /* Handle bad guys: */
1168 for (i = 0; i < NUM_BAD_GUYS; i++)
1170 if (bad_guys[i].alive)
1172 if (bad_guys[i].seen)
1174 if (bad_guys[i].kind == BAD_BSOD)
1176 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1178 /* Move left/right: */
1180 if (bad_guys[i].dying == NO ||
1181 bad_guys[i].dying == FALLING)
1183 if (bad_guys[i].dir == RIGHT)
1184 bad_guys[i].x = bad_guys[i].x + 4;
1185 else if (bad_guys[i].dir == LEFT)
1186 bad_guys[i].x = bad_guys[i].x - 4;
1190 /* Move vertically: */
1192 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1195 /* Bump into things horizontally: */
1197 if (!bad_guys[i].dying)
1199 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1200 bad_guys[i].dir = !bad_guys[i].dir;
1204 /* Bump into other bad guys: */
1206 for (j = 0; j < NUM_BAD_GUYS; j++)
1208 if (j != i && bad_guys[j].alive &&
1209 !bad_guys[j].dying && !bad_guys[i].dying &&
1210 bad_guys[i].x >= bad_guys[j].x - 32 &&
1211 bad_guys[i].x <= bad_guys[j].x + 32 &&
1212 bad_guys[i].y >= bad_guys[j].y - 32 &&
1213 bad_guys[i].y <= bad_guys[j].y + 32)
1215 bad_guys[i].dir = !bad_guys[i].dir;
1220 /* Fall if we get off the ground: */
1222 if (bad_guys[i].dying != FALLING)
1224 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1225 bad_guys[i].ym < MAX_YM)
1227 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1233 if (bad_guys[i].ym > 0)
1235 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1241 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1243 if (bad_guys[i].y > 480)
1244 bad_guys[i].alive = NO;
1246 else if (bad_guys[i].kind == BAD_LAPTOP)
1248 /* --- LAPTOP MONSTER: --- */
1250 /* Move left/right: */
1252 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1254 if (bad_guys[i].dying == NO ||
1255 bad_guys[i].dying == FALLING)
1257 if (bad_guys[i].dir == RIGHT)
1258 bad_guys[i].x = bad_guys[i].x + 4;
1259 else if (bad_guys[i].dir == LEFT)
1260 bad_guys[i].x = bad_guys[i].x - 4;
1263 else if (bad_guys[i].mode == KICK)
1265 if (bad_guys[i].dir == RIGHT)
1266 bad_guys[i].x = bad_guys[i].x + 16;
1267 else if (bad_guys[i].dir == LEFT)
1268 bad_guys[i].x = bad_guys[i].x - 16;
1272 /* Move vertically: */
1274 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1277 /* Bump into things horizontally: */
1279 if (!bad_guys[i].dying)
1281 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1283 bad_guys[i].dir = !bad_guys[i].dir;
1285 if (bad_guys[i].mode == KICK)
1286 play_sound(sounds[SND_RICOCHET]);
1291 /* Bump into other bad guys: */
1293 for (j = 0; j < NUM_BAD_GUYS; j++)
1295 if (j != i && bad_guys[j].alive &&
1296 !bad_guys[j].dying && !bad_guys[i].dying &&
1297 bad_guys[i].x >= bad_guys[j].x - 32 &&
1298 bad_guys[i].x <= bad_guys[j].x + 32 &&
1299 bad_guys[i].y >= bad_guys[j].y - 32 &&
1300 bad_guys[i].y <= bad_guys[j].y + 32)
1302 if (bad_guys[i].mode != KICK)
1303 bad_guys[i].dir = !bad_guys[i].dir;
1306 /* We're in kick mode, kill the other guy: */
1308 bad_guys[j].dying = FALLING;
1309 bad_guys[j].ym = -8;
1310 play_sound(sounds[SND_FALL]);
1312 add_score(bad_guys[i].x - scroll_x,
1313 bad_guys[i].y, 100);
1319 /* Fall if we get off the ground: */
1321 if (bad_guys[i].dying != FALLING)
1323 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1324 bad_guys[i].ym < MAX_YM)
1326 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1332 if (bad_guys[i].ym > 0)
1334 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1340 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1342 if (bad_guys[i].y > 480)
1343 bad_guys[i].alive = NO;
1345 else if (bad_guys[i].kind == BAD_MONEY)
1347 /* --- MONEY BAGS: --- */
1350 /* Move vertically: */
1352 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1355 /* Fall if we get off the ground: */
1357 if (bad_guys[i].dying != FALLING)
1359 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1361 if (bad_guys[i].ym < MAX_YM)
1363 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1370 if (bad_guys[i].ym > 0)
1372 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1373 bad_guys[i].ym = -MAX_YM;
1378 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1380 if (bad_guys[i].y > 480)
1381 bad_guys[i].alive = NO;
1383 else if (bad_guys[i].kind == -1)
1388 /* Kill it if the player jumped on it: */
1390 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1391 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1392 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1393 tux_y >= bad_guys[i].y - 32 &&
1394 tux_y <= bad_guys[i].y - 8
1398 if (bad_guys[i].kind == BAD_BSOD)
1400 bad_guys[i].dying = SQUISHED;
1401 bad_guys[i].timer = 16;
1402 tux_ym = -KILL_BOUNCE_YM;
1404 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1405 50 * score_multiplier);
1407 play_sound(sounds[SND_SQUISH]);
1409 else if (bad_guys[i].kind == BAD_LAPTOP)
1411 if (bad_guys[i].mode != FLAT)
1415 bad_guys[i].mode = FLAT;
1417 bad_guys[i].timer = 64;
1425 bad_guys[i].mode = KICK;
1427 if (tux_x + scroll_x <= bad_guys[i].x)
1428 bad_guys[i].dir = RIGHT;
1430 bad_guys[i].dir = LEFT;
1432 bad_guys[i].timer = 8;
1435 tux_ym = -KILL_BOUNCE_YM;
1437 add_score(bad_guys[i].x - scroll_x,
1439 25 * score_multiplier);
1441 /* play_sound(sounds[SND_SQUISH]); */
1443 else if (bad_guys[i].kind == -1)
1451 /* Hurt the player if he just touched it: */
1453 if (!bad_guys[i].dying && !tux_dying &&
1455 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1456 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1457 tux_y >= bad_guys[i].y - 32 &&
1458 tux_y <= bad_guys[i].y + 32)
1460 if (bad_guys[i].mode == FLAT)
1464 bad_guys[i].mode = KICK;
1466 if (tux_x < bad_guys[i].x)
1468 bad_guys[i].dir = RIGHT;
1469 bad_guys[i].x = bad_guys[i].x + 16;
1473 bad_guys[i].dir = LEFT;
1474 bad_guys[i].x = bad_guys[i].x - 16;
1477 bad_guys[i].timer = 8;
1479 else if (bad_guys[i].mode == KICK)
1481 if (tux_y < bad_guys[i].y - 16 &&
1482 bad_guys[i].timer == 0)
1484 /* Step on (stop being kicked) */
1486 bad_guys[i].mode = FLAT;
1487 bad_guys[i].timer = 64;
1491 /* Hurt if you get hit by kicked laptop: */
1493 if (bad_guys[i].timer == 0)
1495 if (tux_invincible_time == 0)
1501 bad_guys[i].dying = FALLING;
1502 bad_guys[i].ym = -8;
1503 play_sound(sounds[SND_FALL]);
1510 if (tux_invincible_time == 0)
1516 bad_guys[i].dying = FALLING;
1517 bad_guys[i].ym = -8;
1518 play_sound(sounds[SND_FALL]);
1524 /* Handle mode timer: */
1526 if (bad_guys[i].mode == FLAT)
1528 bad_guys[i].timer--;
1530 if (bad_guys[i].timer <= 0)
1531 bad_guys[i].mode = NORMAL;
1533 else if (bad_guys[i].mode == KICK)
1535 if (bad_guys[i].timer > 0)
1536 bad_guys[i].timer--;
1540 /* Handle dying timer: */
1542 if (bad_guys[i].dying == SQUISHED)
1544 bad_guys[i].timer--;
1547 /* Remove it if time's up: */
1549 if (bad_guys[i].timer <= 0)
1550 bad_guys[i].alive = NO;
1554 /* Remove if it's far off the screen: */
1556 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1557 bad_guys[i].alive = NO;
1561 /* Once it's on screen, it's activated! */
1563 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1564 bad_guys[i].seen = YES;
1570 /* Handle skidding: */
1572 if (tux_skidding > 0)
1580 /* --- GAME DRAW! --- */
1588 if (tux_dying && (frame % 4) == 0)
1589 clearscreen(255, 255, 255);
1592 if (super_bkgd_time == 0)
1593 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1595 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1599 /* Draw background: */
1601 for (y = 0; y < 15; y++)
1603 for (x = 0; x < 21; x++)
1605 drawshape(x * 32 - (scroll_x % 32), y * 32,
1606 tiles[y][x + (scroll_x / 32)]);
1611 /* (Bouncy bricks): */
1613 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1615 if (bouncy_bricks[i].alive)
1617 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1618 bouncy_bricks[i].x <= scroll_x + 640)
1620 dest.x = bouncy_bricks[i].x - scroll_x;
1621 dest.y = bouncy_bricks[i].y;
1625 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1630 drawshape(bouncy_bricks[i].x - scroll_x,
1631 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1632 bouncy_bricks[i].shape);
1640 for (i = 0; i < NUM_BAD_GUYS; i++)
1642 if (bad_guys[i].alive &&
1643 bad_guys[i].x > scroll_x - 32 &&
1644 bad_guys[i].x < scroll_x + 640)
1646 if (bad_guys[i].kind == BAD_BSOD)
1648 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1650 if (bad_guys[i].dying == NO)
1654 if (bad_guys[i].dir == LEFT)
1656 drawimage(img_bsod_left[(frame / 5) % 4],
1657 bad_guys[i].x - scroll_x,
1663 drawimage(img_bsod_right[(frame / 5) % 4],
1664 bad_guys[i].x - scroll_x,
1669 else if (bad_guys[i].dying == FALLING)
1673 if (bad_guys[i].dir == LEFT)
1675 drawimage(img_bsod_falling_left,
1676 bad_guys[i].x - scroll_x,
1682 drawimage(img_bsod_falling_right,
1683 bad_guys[i].x - scroll_x,
1688 else if (bad_guys[i].dying == SQUISHED)
1690 /* Dying - Squished: */
1692 if (bad_guys[i].dir == LEFT)
1694 drawimage(img_bsod_squished_left,
1695 bad_guys[i].x - scroll_x,
1701 drawimage(img_bsod_squished_right,
1702 bad_guys[i].x - scroll_x,
1708 else if (bad_guys[i].kind == BAD_LAPTOP)
1710 /* --- LAPTOP MONSTER: --- */
1712 if (bad_guys[i].dying == NO)
1716 if (bad_guys[i].mode == NORMAL)
1720 if (bad_guys[i].dir == LEFT)
1722 drawimage(img_laptop_left[(frame / 5) % 3],
1723 bad_guys[i].x - scroll_x,
1729 drawimage(img_laptop_right[(frame / 5) % 3],
1730 bad_guys[i].x - scroll_x,
1739 if (bad_guys[i].dir == LEFT)
1741 drawimage(img_laptop_flat_left,
1742 bad_guys[i].x - scroll_x,
1748 drawimage(img_laptop_flat_right,
1749 bad_guys[i].x - scroll_x,
1755 else if (bad_guys[i].dying == FALLING)
1759 if (bad_guys[i].dir == LEFT)
1761 drawimage(img_laptop_falling_left,
1762 bad_guys[i].x - scroll_x,
1768 drawimage(img_laptop_falling_right,
1769 bad_guys[i].x - scroll_x,
1775 else if (bad_guys[i].kind == BAD_MONEY)
1777 if (bad_guys[i].ym > -16)
1779 if (bad_guys[i].dir == LEFT)
1781 drawimage(img_money_left[0],
1782 bad_guys[i].x - scroll_x,
1788 drawimage(img_money_right[0],
1789 bad_guys[i].x - scroll_x,
1796 if (bad_guys[i].dir == LEFT)
1798 drawimage(img_money_left[1],
1799 bad_guys[i].x - scroll_x,
1805 drawimage(img_money_right[1],
1806 bad_guys[i].x - scroll_x,
1812 else if (bad_guys[i].kind == -1)
1821 if (right == UP && left == UP)
1828 if ((fire == DOWN && (frame % 2) == 0) ||
1830 tux_frame_main = (tux_frame_main + 1) % 4;
1832 tux_frame = tux_frame_main;
1839 if (tux_got_coffee && (frame % 2) == 1)
1843 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1847 if (tux_safe == 0 || (frame % 2) == 0)
1849 if (tux_size == SMALL)
1851 if (tux_invincible_time)
1855 if (tux_dir == RIGHT)
1857 drawimage(cape_right[frame % 2],
1863 drawimage(cape_left[frame % 2],
1870 if (tux_dir == RIGHT)
1872 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1876 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1881 if (tux_invincible_time)
1885 if (tux_dir == RIGHT)
1887 drawimage(bigcape_right[frame % 2],
1888 tux_x - 8 - 16, tux_y - 32,
1893 drawimage(bigcape_left[frame % 2],
1894 tux_x - 8, tux_y - 32,
1903 if (!jumping || tux_ym > 0)
1905 if (tux_dir == RIGHT)
1907 drawimage(bigtux_right[tux_frame],
1908 tux_x - 8, tux_y - 32,
1913 drawimage(bigtux_left[tux_frame],
1914 tux_x - 8, tux_y - 32,
1920 if (tux_dir == RIGHT)
1922 drawimage(bigtux_right_jump,
1923 tux_x - 8, tux_y - 32,
1928 drawimage(bigtux_left_jump,
1929 tux_x - 8, tux_y - 32,
1936 if (tux_dir == RIGHT)
1938 drawimage(skidtux_right,
1939 tux_x - 8, tux_y - 32,
1944 drawimage(skidtux_left,
1945 tux_x - 8, tux_y - 32,
1952 if (tux_dir == RIGHT)
1954 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
1959 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
1969 for (i = 0; i < NUM_BULLETS; i++)
1971 if (bullets[i].alive &&
1972 bullets[i].x >= scroll_x - 4 &&
1973 bullets[i].x <= scroll_x + 640)
1975 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
1981 /* (Floating scores): */
1983 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1985 if (floating_scores[i].alive)
1987 sprintf(str, "%d", floating_scores[i].value);
1989 floating_scores[i].x + 16 - strlen(str) * 8,
1990 floating_scores[i].y,
1991 letters_gold, NO_UPDATE);
1998 for (i = 0; i < NUM_UPGRADES; i++)
2000 if (upgrades[i].alive)
2002 if (upgrades[i].height < 32)
2006 dest.x = upgrades[i].x - scroll_x;
2007 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2009 dest.h = upgrades[i].height;
2014 src.h = upgrades[i].height;
2016 if (upgrades[i].kind == UPGRADE_MINTS)
2017 SDL_BlitSurface(img_mints, &src, screen, &dest);
2018 else if (upgrades[i].kind == UPGRADE_COFFEE)
2019 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2020 else if (upgrades[i].kind == UPGRADE_HERRING)
2021 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2025 if (upgrades[i].kind == UPGRADE_MINTS)
2027 drawimage(img_mints,
2028 upgrades[i].x - scroll_x, upgrades[i].y,
2031 else if (upgrades[i].kind == UPGRADE_COFFEE)
2033 drawimage(img_coffee,
2034 upgrades[i].x - scroll_x, upgrades[i].y,
2037 else if (upgrades[i].kind == UPGRADE_HERRING)
2039 drawimage(img_golden_herring,
2040 upgrades[i].x - scroll_x, upgrades[i].y,
2048 /* (Bouncy distros): */
2050 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2052 if (bouncy_distros[i].alive)
2054 drawimage(img_distro[0],
2055 bouncy_distros[i].x - scroll_x,
2056 bouncy_distros[i].y,
2062 /* (Broken bricks): */
2064 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2066 if (broken_bricks[i].alive)
2068 src.x = rand() % 16;
2069 src.y = rand() % 16;
2073 dest.x = broken_bricks[i].x - scroll_x;
2074 dest.y = broken_bricks[i].y;
2078 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2085 sprintf(str, "%d", score);
2086 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2087 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2089 sprintf(str, "%d", highscore);
2090 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2091 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2093 if (time_left >= 50 || (frame % 10) < 5)
2095 sprintf(str, "%d", time_left);
2096 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2097 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2100 sprintf(str, "%d", distros);
2101 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2102 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2105 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2107 /* (Update it all!) */
2113 /* --- GAME LOOP! --- */
2118 Uint32 last_time, now_time;
2122 clearscreen(0, 0, 0);
2126 /* Init the game: */
2133 highscore = load_hs();
2136 /* --- MAIN GAME LOOP!!! --- */
2146 last_time = SDL_GetTicks();
2150 /* Handle events: */
2156 /* Handle actions: */
2161 if((ret = game_action()) != -1) { return ret; }
2164 /*Draw the current scene to the screen */
2167 /* Keep playing music: */
2171 if (!playing_music())
2173 play_music(song, 1);
2177 /* Time stops in pause mode */
2178 if(game_pause) { continue; }
2180 /* Pause til next frame: */
2182 now_time = SDL_GetTicks();
2183 if (now_time < last_time + FPS)
2184 SDL_Delay(last_time + FPS - now_time);
2189 if ((frame % 10) == 0 && time_left > 0)
2197 while (!done && !quit);
2201 if (playing_music())
2213 /* Initialize the game stuff: */
2225 /* Load data for this level: */
2227 void loadlevel(void)
2238 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2239 bouncy_distros[i].alive = NO;
2241 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2242 broken_bricks[i].alive = NO;
2244 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2245 bouncy_bricks[i].alive = NO;
2247 for (i = 0; i < NUM_BAD_GUYS; i++)
2248 bad_guys[i].alive = NO;
2250 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2251 floating_scores[i].alive = NO;
2253 for (i = 0; i < NUM_UPGRADES; i++)
2254 upgrades[i].alive = NO;
2256 for (i = 0; i < NUM_BULLETS; i++)
2257 bullets[i].alive = NO;
2260 /* Load data file: */
2262 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2263 DEBUG_MSG("Fatal: FIXME QUICKLY : SEGMENTATION FAULT POSSIBLE !");
2264 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2265 fi = fopen(filename, "r");
2276 /* Load header info: */
2281 strcpy(levelname, str);
2282 levelname[strlen(levelname)-1] = '\0';
2286 strcpy(leveltheme, str);
2287 leveltheme[strlen(leveltheme)-1] = '\0';
2291 /* (Time to beat level) */
2293 time_left = atoi(str);
2295 /* (Song file for this level) */
2297 strcpy(song_title, str);
2298 song_title[strlen(song_title)-1] = '\0';
2302 /* (Level background color) */
2304 bkgd_red = atoi(str);
2306 bkgd_green= atoi(str);
2308 bkgd_blue = atoi(str);
2312 level_width = atoi(str);
2315 /* Allocate some space for the line-reading! */
2317 line = (char *) malloc(sizeof(char) * (level_width + 5));
2320 fprintf(stderr, "Couldn't allocate space to load level data!");
2325 /* Load the level lines: */
2327 for (y = 0; y < 15; y++)
2329 if(fgets(line, level_width + 5, fi) == NULL)
2331 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2334 line[strlen(line) - 1] = '\0';
2335 tiles[y] = strdup(line);
2341 /* Activate bad guys: */
2343 for (y = 0; y < 15; y++)
2345 for (x = 0; x < level_width; x++)
2347 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2349 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2364 tux_got_coffee = NO;
2365 tux_invincible_time = 0;
2369 tux_safe = TUX_SAFE_TIME;
2385 score_multiplier = 1;
2386 super_bkgd_time = 0;
2390 counting_distros = NO;
2396 clearscreen(0, 0, 0);
2398 sprintf(str, "LEVEL %d", level);
2399 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2401 sprintf(str, "%s", levelname);
2402 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2404 sprintf(str, "TUX x %d", lives);
2405 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2415 /* Load a level-specific graphic... */
2417 SDL_Surface * load_level_image(char * file, int use_alpha)
2421 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2423 return(load_image(fname, use_alpha));
2427 /* Load graphics: */
2429 void loadlevelgfx(void)
2431 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2432 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2434 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2435 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2436 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2437 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2439 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2440 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2441 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2442 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2444 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2445 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2446 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2447 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2453 void loadlevelsong(void)
2458 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2459 strlen(song_title) + 8));
2461 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2463 song = load_song(song_path);
2469 /* Free graphics data for this level: */
2471 void unloadlevelgfx(void)
2475 for (i = 0; i < 2; i++)
2477 SDL_FreeSurface(img_brick[i]);
2479 for (i = 0; i < 4; i++)
2481 SDL_FreeSurface(img_solid[i]);
2482 SDL_FreeSurface(img_bkgd[0][i]);
2483 SDL_FreeSurface(img_bkgd[1][i]);
2488 /* Free music data for this level: */
2490 void unloadlevelsong(void)
2496 /* Load graphics shared between all levels: */
2498 void loadshared(void)
2505 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2508 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2511 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2514 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2517 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2520 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2523 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2526 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2529 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2532 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2535 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2538 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2541 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2545 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2547 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2550 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2553 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2557 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2560 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2564 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2568 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2572 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2575 ducktux_right = load_image(DATA_PREFIX
2576 "/images/shared/ducktux-right.png",
2579 ducktux_left = load_image(DATA_PREFIX
2580 "/images/shared/ducktux-left.png",
2583 skidtux_right = load_image(DATA_PREFIX
2584 "/images/shared/skidtux-right.png",
2587 skidtux_left = load_image(DATA_PREFIX
2588 "/images/shared/skidtux-left.png",
2594 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2596 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2603 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2605 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2608 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2611 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2617 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2618 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2624 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2626 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2632 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2635 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2638 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2641 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2645 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2648 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2651 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2654 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2662 img_bsod_left[0] = load_image(DATA_PREFIX
2663 "/images/shared/bsod-left-0.png",
2666 img_bsod_left[1] = load_image(DATA_PREFIX
2667 "/images/shared/bsod-left-1.png",
2670 img_bsod_left[2] = load_image(DATA_PREFIX
2671 "/images/shared/bsod-left-2.png",
2674 img_bsod_left[3] = load_image(DATA_PREFIX
2675 "/images/shared/bsod-left-3.png",
2678 img_bsod_right[0] = load_image(DATA_PREFIX
2679 "/images/shared/bsod-right-0.png",
2682 img_bsod_right[1] = load_image(DATA_PREFIX
2683 "/images/shared/bsod-right-1.png",
2686 img_bsod_right[2] = load_image(DATA_PREFIX
2687 "/images/shared/bsod-right-2.png",
2690 img_bsod_right[3] = load_image(DATA_PREFIX
2691 "/images/shared/bsod-right-3.png",
2694 img_bsod_squished_left = load_image(DATA_PREFIX
2695 "/images/shared/bsod-squished-left.png",
2698 img_bsod_squished_right = load_image(DATA_PREFIX
2699 "/images/shared/bsod-squished-right.png",
2702 img_bsod_falling_left = load_image(DATA_PREFIX
2703 "/images/shared/bsod-falling-left.png",
2706 img_bsod_falling_right = load_image(DATA_PREFIX
2707 "/images/shared/bsod-falling-right.png",
2713 img_laptop_left[0] = load_image(DATA_PREFIX
2714 "/images/shared/laptop-left-0.png",
2717 img_laptop_left[1] = load_image(DATA_PREFIX
2718 "/images/shared/laptop-left-1.png",
2721 img_laptop_left[2] = load_image(DATA_PREFIX
2722 "/images/shared/laptop-left-2.png",
2725 img_laptop_right[0] = load_image(DATA_PREFIX
2726 "/images/shared/laptop-right-0.png",
2729 img_laptop_right[1] = load_image(DATA_PREFIX
2730 "/images/shared/laptop-right-1.png",
2733 img_laptop_right[2] = load_image(DATA_PREFIX
2734 "/images/shared/laptop-right-2.png",
2737 img_laptop_flat_left = load_image(DATA_PREFIX
2738 "/images/shared/laptop-flat-left.png",
2741 img_laptop_flat_right = load_image(DATA_PREFIX
2742 "/images/shared/laptop-flat-right.png",
2745 img_laptop_falling_left =
2746 load_image(DATA_PREFIX
2747 "/images/shared/laptop-falling-left.png",
2750 img_laptop_falling_right =
2751 load_image(DATA_PREFIX
2752 "/images/shared/laptop-falling-right.png",
2758 img_money_left[0] = load_image(DATA_PREFIX
2759 "/images/shared/bag-left-0.png",
2762 img_money_left[1] = load_image(DATA_PREFIX
2763 "/images/shared/bag-left-1.png",
2766 img_money_right[0] = load_image(DATA_PREFIX
2767 "/images/shared/bag-right-0.png",
2770 img_money_right[1] = load_image(DATA_PREFIX
2771 "/images/shared/bag-right-1.png",
2778 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2779 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2784 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2786 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2792 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2795 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2798 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2801 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2807 img_golden_herring =
2808 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2812 /* Super background: */
2814 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2818 /* Sound effects: */
2822 for (i = 0; i < NUM_SOUNDS; i++)
2823 sounds[i] = load_sound(soundfilenames[i]);
2829 /* Free shared data: */
2831 void unloadshared(void)
2835 for (i = 0; i < 3; i++)
2837 SDL_FreeSurface(tux_right[i]);
2838 SDL_FreeSurface(tux_left[i]);
2839 SDL_FreeSurface(bigtux_right[i]);
2840 SDL_FreeSurface(bigtux_left[i]);
2843 SDL_FreeSurface(bigtux_right_jump);
2844 SDL_FreeSurface(bigtux_left_jump);
2846 for (i = 0; i < 2; i++)
2848 SDL_FreeSurface(cape_right[i]);
2849 SDL_FreeSurface(cape_left[i]);
2850 SDL_FreeSurface(bigcape_right[i]);
2851 SDL_FreeSurface(bigcape_left[i]);
2854 SDL_FreeSurface(ducktux_left);
2855 SDL_FreeSurface(ducktux_right);
2857 SDL_FreeSurface(skidtux_left);
2858 SDL_FreeSurface(skidtux_right);
2860 for (i = 0; i < 4; i++)
2862 SDL_FreeSurface(img_bsod_left[i]);
2863 SDL_FreeSurface(img_bsod_right[i]);
2866 SDL_FreeSurface(img_bsod_squished_left);
2867 SDL_FreeSurface(img_bsod_squished_right);
2869 SDL_FreeSurface(img_bsod_falling_left);
2870 SDL_FreeSurface(img_bsod_falling_right);
2872 for (i = 0; i < 3; i++)
2874 SDL_FreeSurface(img_laptop_left[i]);
2875 SDL_FreeSurface(img_laptop_right[i]);
2878 SDL_FreeSurface(img_laptop_flat_left);
2879 SDL_FreeSurface(img_laptop_flat_right);
2881 SDL_FreeSurface(img_laptop_falling_left);
2882 SDL_FreeSurface(img_laptop_falling_right);
2884 for (i = 0; i < 2; i++)
2886 SDL_FreeSurface(img_money_left[i]);
2887 SDL_FreeSurface(img_money_right[i]);
2890 SDL_FreeSurface(img_box_full);
2891 SDL_FreeSurface(img_box_empty);
2893 SDL_FreeSurface(img_water);
2894 for (i = 0; i < 3; i++)
2895 SDL_FreeSurface(img_waves[i]);
2897 SDL_FreeSurface(img_pole);
2898 SDL_FreeSurface(img_poletop);
2900 for (i = 0; i < 2; i++)
2901 SDL_FreeSurface(img_flag[i]);
2903 SDL_FreeSurface(img_mints);
2904 SDL_FreeSurface(img_coffee);
2906 for (i = 0; i < 4; i++)
2908 SDL_FreeSurface(img_distro[i]);
2909 SDL_FreeSurface(img_cloud[0][i]);
2910 SDL_FreeSurface(img_cloud[1][i]);
2913 SDL_FreeSurface(img_golden_herring);
2915 for (i = 0; i < NUM_SOUNDS; i++)
2916 free_chunk(sounds[i]);
2920 /* Draw a tile on the screen: */
2922 void drawshape(int x, int y, unsigned char c)
2926 if (c == 'X' || c == 'x')
2927 drawimage(img_brick[0], x, y, NO_UPDATE);
2928 else if (c == 'Y' || c == 'y')
2929 drawimage(img_brick[1], x, y, NO_UPDATE);
2930 else if (c == 'A' || c =='B' || c == '!')
2931 drawimage(img_box_full, x, y, NO_UPDATE);
2933 drawimage(img_box_empty, x, y, NO_UPDATE);
2934 else if (c >= 'C' && c <= 'F')
2935 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
2936 else if (c >= 'c' && c <= 'f')
2937 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
2938 else if (c >= 'G' && c <= 'J')
2939 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
2940 else if (c >= 'g' && c <= 'j')
2941 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
2943 drawimage(img_solid[0], x, y, NO_UPDATE);
2945 drawimage(img_solid[1], x, y, NO_UPDATE);
2947 drawimage(img_solid[2], x, y, NO_UPDATE);
2949 drawimage(img_solid[3], x, y, NO_UPDATE);
2952 z = (frame / 2) % 6;
2955 drawimage(img_distro[z], x, y, NO_UPDATE);
2957 drawimage(img_distro[2], x, y, NO_UPDATE);
2959 drawimage(img_distro[1], x, y, NO_UPDATE);
2963 z = (frame / 3) % 3;
2965 drawimage(img_waves[z], x, y, NO_UPDATE);
2968 drawimage(img_poletop, x, y, NO_UPDATE);
2971 drawimage(img_pole, x, y, NO_UPDATE);
2973 /* Mark this as the end position of the level! */
2979 z = (frame / 3) % 2;
2981 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
2984 drawimage(img_water, x, y, NO_UPDATE);
2988 /* What shape is at some position? */
2990 unsigned char shape(int x, int y, int sx)
2996 xx = ((x + sx) / 32);
2998 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3009 int issolid(int x, int y, int sx)
3015 if (isbrick(x, y, sx) ||
3016 isbrick(x + 31, y, sx) ||
3018 isice(x + 31, y, sx) ||
3019 (shape(x, y, sx) == '[' ||
3020 shape(x + 31, y, sx) == '[') ||
3021 (shape(x, y, sx) == '=' ||
3022 shape(x + 31, y, sx) == '=') ||
3023 (shape(x, y, sx) == ']' ||
3024 shape(x + 31, y, sx) == ']') ||
3025 (shape(x, y, sx) == 'A' ||
3026 shape(x + 31, y, sx) == 'A') ||
3027 (shape(x, y, sx) == 'B' ||
3028 shape(x + 31, y, sx) == 'B') ||
3029 (shape(x, y, sx) == '!' ||
3030 shape(x + 31, y, sx) == '!') ||
3031 (shape(x, y, sx) == 'a' ||
3032 shape(x + 31, y, sx) == 'a'))
3041 /* Is it a brick? */
3043 int isbrick(int x, int y, int sx)
3049 if (shape(x, y, sx) == 'X' ||
3050 shape(x, y, sx) == 'x' ||
3051 shape(x, y, sx) == 'Y' ||
3052 shape(x, y, sx) == 'y')
3063 int isice(int x, int y, int sx)
3069 if (shape(x, y, sx) == '#')
3078 /* Is it a full box? */
3080 int isfullbox(int x, int y, int sx)
3086 if (shape(x, y, sx) == 'A' ||
3087 shape(x, y, sx) == 'B' ||
3088 shape(x, y, sx) == '!')
3097 /* Edit a piece of the map! */
3099 void change(int x, int y, int sx, unsigned char c)
3104 xx = ((x + sx) / 32);
3106 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3111 /* Break a brick: */
3113 void trybreakbrick(int x, int y, int sx)
3115 if (isbrick(x, y, sx))
3117 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3119 /* Get a distro from it: */
3121 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3124 if (counting_distros == NO)
3126 counting_distros = YES;
3127 distro_counter = 50;
3130 if (distro_counter <= 0)
3131 change(x, y, sx, 'a');
3133 play_sound(sounds[SND_DISTRO]);
3134 score = score + SCORE_DISTRO;
3139 /* Get rid of it: */
3141 change(x, y, sx, '.');
3145 /* Replace it with broken bits: */
3147 add_broken_brick(((x + sx + 1) / 32) * 32,
3151 /* Get some score: */
3153 play_sound(sounds[SND_BRICK]);
3154 score = score + SCORE_BRICK;
3159 /* Bounce a brick: */
3161 void bumpbrick(int x, int y, int sx)
3163 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3166 play_sound(sounds[SND_BRICK]);
3172 void tryemptybox(int x, int y, int sx)
3174 if (isfullbox(x, y, sx))
3176 if (shape(x, y, sx) == 'A')
3178 /* Box with a distro! */
3180 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3181 (y / 32) * 32 - 32);
3183 play_sound(sounds[SND_DISTRO]);
3184 score = score + SCORE_DISTRO;
3187 else if (shape(x, y, sx) == 'B')
3189 /* Add an upgrade! */
3191 if (tux_size == SMALL)
3193 /* Tux is small, add mints! */
3195 add_upgrade(((x + sx + 1) / 32) * 32,
3201 /* Tux is big, add coffee: */
3203 add_upgrade(((x + sx + 1) / 32) * 32,
3208 play_sound(sounds[SND_UPGRADE]);
3210 else if (shape(x, y, sx) == '!')
3212 /* Add a golden herring */
3214 add_upgrade(((x + sx + 1) / 32) * 32,
3219 /* Empty the box: */
3221 change(x, y, sx, 'a');
3226 /* Try to grab a distro: */
3228 void trygrabdistro(int x, int y, int sx, int bounciness)
3230 if (shape(x, y, sx) == '$')
3232 change(x, y, sx, '.');
3233 play_sound(sounds[SND_DISTRO]);
3235 if (bounciness == BOUNCE)
3237 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3241 score = score + SCORE_DISTRO;
3247 /* Add a bouncy distro: */
3249 void add_bouncy_distro(int x, int y)
3255 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3257 if (!bouncy_distros[i].alive)
3263 bouncy_distros[found].alive = YES;
3264 bouncy_distros[found].x = x;
3265 bouncy_distros[found].y = y;
3266 bouncy_distros[found].ym = -6;
3271 /* Add broken brick pieces: */
3273 void add_broken_brick(int x, int y)
3275 add_broken_brick_piece(x, y, -4, -16);
3276 add_broken_brick_piece(x, y + 16, -6, -12);
3278 add_broken_brick_piece(x + 16, y, 4, -16);
3279 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3283 /* Add a broken brick piece: */
3285 void add_broken_brick_piece(int x, int y, int xm, int ym)
3291 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3293 if (!broken_bricks[i].alive)
3299 broken_bricks[found].alive = YES;
3300 broken_bricks[found].x = x;
3301 broken_bricks[found].y = y;
3302 broken_bricks[found].xm = xm;
3303 broken_bricks[found].ym = ym;
3308 /* Add a bouncy brick piece: */
3310 void add_bouncy_brick(int x, int y)
3316 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3318 if (!bouncy_bricks[i].alive)
3324 bouncy_bricks[found].alive = YES;
3325 bouncy_bricks[found].x = x;
3326 bouncy_bricks[found].y = y;
3327 bouncy_bricks[found].offset = 0;
3328 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3329 bouncy_bricks[found].shape = shape(x, y, 0);
3334 /* Add a bad guy: */
3336 void add_bad_guy(int x, int y, int kind)
3342 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3344 if (!bad_guys[i].alive)
3350 bad_guys[found].alive = YES;
3351 bad_guys[found].mode = NORMAL;
3352 bad_guys[found].dying = NO;
3353 bad_guys[found].timer = 0;
3354 bad_guys[found].kind = kind;
3355 bad_guys[found].x = x;
3356 bad_guys[found].y = y;
3357 bad_guys[found].xm = 0;
3358 bad_guys[found].ym = 0;
3359 bad_guys[found].dir = LEFT;
3360 bad_guys[found].seen = NO;
3367 void add_score(int x, int y, int s)
3372 /* Add the score: */
3377 /* Add a floating score thing to the game: */
3381 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3383 if (!floating_scores[i].alive)
3390 floating_scores[found].alive = YES;
3391 floating_scores[found].x = x;
3392 floating_scores[found].y = y - 16;
3393 floating_scores[found].timer = 8;
3394 floating_scores[found].value = s;
3399 /* Try to bump a bad guy from below: */
3401 void trybumpbadguy(int x, int y, int sx)
3408 for (i = 0; i < NUM_BAD_GUYS; i++)
3410 if (bad_guys[i].alive &&
3411 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3412 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3414 if (bad_guys[i].kind == BAD_BSOD ||
3415 bad_guys[i].kind == BAD_LAPTOP)
3417 bad_guys[i].dying = FALLING;
3418 bad_guys[i].ym = -8;
3419 play_sound(sounds[SND_FALL]);
3427 for (i = 0; i < NUM_UPGRADES; i++)
3429 if (upgrades[i].alive && upgrades[i].height == 32 &&
3430 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3431 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3433 upgrades[i].xm = -upgrades[i].xm;
3434 upgrades[i].ym = -8;
3435 play_sound(sounds[SND_BUMP_UPGRADE]);
3441 /* Add an upgrade: */
3443 void add_upgrade(int x, int y, int kind)
3449 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3451 if (!upgrades[i].alive)
3457 upgrades[found].alive = YES;
3458 upgrades[found].kind = kind;
3459 upgrades[found].x = x;
3460 upgrades[found].y = y;
3461 upgrades[found].xm = 4;
3462 upgrades[found].ym = -4;
3463 upgrades[found].height = 0;
3470 void killtux(int mode)
3474 play_sound(sounds[SND_HURT]);
3476 if (tux_dir == RIGHT)
3478 else if (tux_dir == LEFT)
3481 if (mode == SHRINK && tux_size == BIG)
3484 tux_got_coffee = NO;
3488 tux_safe = TUX_SAFE_TIME;
3499 void add_bullet(int x, int y, int dir, int xm)
3505 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3507 if (!bullets[i].alive)
3513 bullets[found].alive = YES;
3517 bullets[found].x = x + 32;
3518 bullets[found].xm = BULLET_XM + xm;
3522 bullets[found].x = x;
3523 bullets[found].xm = -BULLET_XM + xm;
3526 bullets[found].y = y;
3527 bullets[found].ym = BULLET_STARTING_YM;
3529 play_sound(sounds[SND_SHOOT]);
3534 void drawendscreen(void)
3538 clearscreen(0, 0, 0);
3540 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3542 sprintf(str, "SCORE: %d", score);
3543 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3545 sprintf(str, "DISTROS: %d", distros);
3546 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3552 void drawresultscreen(void)
3556 clearscreen(0, 0, 0);
3558 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3560 sprintf(str, "SCORE: %d", score);
3561 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3563 sprintf(str, "DISTROS: %d", distros);
3564 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);