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,
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;
108 unsigned char * tiles[15];
109 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
110 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
111 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
112 bad_guy_type bad_guys[NUM_BAD_GUYS];
113 floating_score_type floating_scores[NUM_FLOATING_SCORES];
114 upgrade_type upgrades[NUM_UPGRADES];
115 bullet_type bullets[NUM_BULLETS];
120 /* Local function prototypes: */
123 void loadlevel(void);
124 void loadlevelgfx(void);
125 void loadlevelsong(void);
126 void unloadlevelgfx(void);
127 void unloadlevelsong(void);
128 void loadshared(void);
129 void unloadshared(void);
130 void drawshape(int x, int y, unsigned char c);
131 unsigned char shape(int x, int y, int sx);
132 int issolid(int x, int y, int sx);
133 int isbrick(int x, int y, int sx);
134 int isice(int x, int y, int sx);
135 int isfullbox(int x, int y, int sx);
136 void change(int x, int y, int sx, unsigned char c);
137 void trybreakbrick(int x, int y, int sx);
138 void bumpbrick(int x, int y, int sx);
139 void tryemptybox(int x, int y, int sx);
140 void trygrabdistro(int x, int y, int sx, int bounciness);
141 void add_bouncy_distro(int x, int y);
142 void add_broken_brick(int x, int y);
143 void add_broken_brick_piece(int x, int y, int xm, int ym);
144 void add_bouncy_brick(int x, int y);
145 void add_bad_guy(int x, int y, int kind);
146 void add_score(int x, int y, int s);
147 void trybumpbadguy(int x, int y, int sx);
148 void add_upgrade(int x, int y, int kind);
149 void killtux(int mode);
150 void add_bullet(int x, int y, int dir, int xm);
151 void drawendscreen(void);
152 void drawresultscreen(void);
155 /* --- GAME LOOP! --- */
159 int done, quit, x, y, i, j;
163 Uint32 last_time, now_time;
169 clearscreen(0, 0, 0);
180 highscore = load_hs();
183 /* --- MAIN GAME LOOP!!! --- */
193 last_time = SDL_GetTicks();
201 while (SDL_PollEvent(&event))
203 if (event.type == SDL_QUIT)
205 /* Quit event - quit: */
209 else if (event.type == SDL_KEYDOWN)
213 key = event.key.keysym.sym;
215 if (key == SDLK_ESCAPE)
217 /* Escape: Quit the game and return to main menu: */
221 else if (key == SDLK_RIGHT)
225 else if (key == SDLK_LEFT)
229 else if (key == SDLK_UP)
233 else if (key == SDLK_DOWN)
237 else if (key == SDLK_LCTRL)
242 else if (event.type == SDL_KEYUP)
246 key = event.key.keysym.sym;
248 if (key == SDLK_RIGHT)
252 else if (key == SDLK_LEFT)
256 else if (key == SDLK_UP)
260 else if (key == SDLK_DOWN)
264 else if (key == SDLK_LCTRL)
268 else if (key == SDLK_TAB)
270 tux_size = !tux_size;
272 else if (key == SDLK_END)
276 else if (key == SDLK_SPACE)
282 else if (event.type == SDL_JOYAXISMOTION)
284 if (event.jaxis.axis == JOY_X)
286 if (event.jaxis.value < -256)
291 if (event.jaxis.value > 256)
296 else if (event.jaxis.axis == JOY_Y)
298 if (event.jaxis.value > 256)
304 else if (event.type == SDL_JOYBUTTONDOWN)
306 if (event.jbutton.button == JOY_A)
308 else if (event.jbutton.button == JOY_B)
311 else if (event.type == SDL_JOYBUTTONUP)
313 if (event.jbutton.button == JOY_A)
315 else if (event.jbutton.button == JOY_B)
322 /* --- HANDLE TUX! --- */
324 /* Handle key and joystick state: */
326 if (!(tux_dying || next_level))
328 if (right == DOWN && left == UP)
332 if (tux_xm < -SKID_XM && !tux_skidding &&
335 tux_skidding = SKID_TIME;
337 playsound(sounds[SND_SKID]);
343 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
351 if (tux_dir == RIGHT)
353 /* Facing the direction we're jumping? Go full-speed: */
357 tux_xm = tux_xm + WALK_SPEED;
359 if (tux_xm > MAX_WALK_XM)
360 tux_xm = MAX_WALK_XM;
362 else if (fire == DOWN)
364 tux_xm = tux_xm + RUN_SPEED;
366 if (tux_xm > MAX_RUN_XM)
372 /* Not facing the direction we're jumping?
375 tux_xm = tux_xm + WALK_SPEED / 2;
377 if (tux_xm > MAX_WALK_XM / 2)
378 tux_xm = MAX_WALK_XM / 2;
382 else if (left == DOWN && right == UP)
386 if (tux_xm > SKID_XM && !tux_skidding &&
389 tux_skidding = SKID_TIME;
390 playsound(sounds[SND_SKID]);
395 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
405 /* Facing the direction we're jumping? Go full-speed: */
409 tux_xm = tux_xm - WALK_SPEED;
411 if (tux_xm < -MAX_WALK_XM)
412 tux_xm = -MAX_WALK_XM;
414 else if (fire == DOWN)
416 tux_xm = tux_xm - RUN_SPEED;
418 if (tux_xm < -MAX_RUN_XM)
419 tux_xm = -MAX_RUN_XM;
424 /* Not facing the direction we're jumping?
427 tux_xm = tux_xm - WALK_SPEED / 2;
429 if (tux_xm < -MAX_WALK_XM / 2)
430 tux_xm = -MAX_WALK_XM / 2;
438 if (tux_x >= endpos && endpos != 0)
440 /* FIXME: No need to kill Tux to end the level! ;^) */
449 if (jump_counter == 0)
453 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
456 /* If they're not on the ground, or are currently moving
457 vertically, don't jump! */
459 jump_counter = MAX_JUMP_COUNT;
463 /* Make sure we're not standing back up into a solid! */
465 if (tux_size == SMALL || tux_duck == NO ||
466 !issolid(tux_x, tux_y, scroll_x))
470 if (tux_size == SMALL)
471 playsound(sounds[SND_JUMP]);
473 playsound(sounds[SND_BIGJUMP]);
479 /* Keep jumping for a while: */
481 if (jump_counter < MAX_JUMP_COUNT)
483 tux_ym = tux_ym - JUMP_SPEED;
493 if (fire == DOWN && old_fire == UP && tux_got_coffee)
495 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
508 if (tux_size == BIG && tux_duck == YES)
510 /* Make sure we're not standing back up into a solid! */
512 if (!issolid(tux_x, tux_y - 32, scroll_x))
518 } /* (tux_dying || next_level) */
521 /* Tux either died, or reached the end of a level! */
526 if (Mix_PlayingMusic())
533 /* End of a level! */
541 tux_ym = tux_ym + GRAVITY;
549 /* No more lives!? */
555 if (score > highscore)
562 /* Either way, (re-)load the (next) level... */
573 tux_x = tux_x + tux_xm;
574 tux_y = tux_y + tux_ym;
577 /* Keep tux in bounds: */
581 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
583 /* Scroll the screen in past center: */
585 scroll_x = scroll_x + (tux_x - 320);
588 if (scroll_x > ((level_width * 32) - 640))
589 scroll_x = ((level_width * 32) - 640);
591 else if (tux_x > 608)
593 /* ... unless there's no more to scroll! */
603 if (issolid(tux_x, tux_y + 31, scroll_x) &&
604 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
606 while (issolid(tux_x, tux_y + 31, scroll_x))
617 if (issolid(tux_x, tux_y, scroll_x) &&
618 !issolid(tux_x - tux_xm, tux_y, scroll_x))
620 while (issolid(tux_x, tux_y, scroll_x))
631 if (issolid(tux_x, tux_y + 31, scroll_x))
633 /* Set down properly: */
635 while (issolid(tux_x, tux_y + 31, scroll_x))
644 /* Reset score multiplier (for mutli-hits): */
647 score_multiplier = 1;
657 /* Bump into things: */
659 if (issolid(tux_x, tux_y, scroll_x) ||
660 (tux_size == BIG && !tux_duck &&
661 (issolid(tux_x, tux_y - 32, scroll_x))))
663 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
664 (tux_size == SMALL || tux_duck ||
665 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
667 tux_x = tux_x - tux_xm;
670 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
671 (tux_size == SMALL || tux_duck ||
672 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
680 /* Break bricks and empty boxes: */
684 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
685 isfullbox(tux_x, tux_y - 32, scroll_x))
687 trygrabdistro(tux_x, tux_y - 64, scroll_x,
689 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
691 if (isfullbox(tux_x, tux_y - 32,
694 bumpbrick(tux_x, tux_y - 32,
698 trybreakbrick(tux_x, tux_y - 32, scroll_x);
699 tryemptybox(tux_x, tux_y - 32, scroll_x);
702 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
703 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
705 trygrabdistro(tux_x + 31,
709 trybumpbadguy(tux_x + 31,
713 if (isfullbox(tux_x + 31, tux_y - 32,
716 bumpbrick(tux_x + 31, tux_y - 32,
720 trybreakbrick(tux_x + 31,
723 tryemptybox(tux_x + 31,
730 if (isbrick(tux_x, tux_y, scroll_x) ||
731 isfullbox(tux_x, tux_y, scroll_x))
733 trygrabdistro(tux_x, tux_y - 32, scroll_x,
735 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
736 if (isfullbox(tux_x, tux_y, scroll_x))
737 bumpbrick(tux_x, tux_y, scroll_x);
738 trybreakbrick(tux_x, tux_y, scroll_x);
739 tryemptybox(tux_x, tux_y, scroll_x);
742 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
743 isfullbox(tux_x + 31, tux_y, scroll_x))
745 trygrabdistro(tux_x + 31,
749 trybumpbadguy(tux_x + 31,
752 if (isfullbox(tux_x + 31, tux_y, scroll_x))
753 bumpbrick(tux_x + 31, tux_y, scroll_x);
754 trybreakbrick(tux_x + 31, tux_y, scroll_x);
755 tryemptybox(tux_x + 31, tux_y, scroll_x);
761 /* It's a brick and we're small, make the brick
762 bounce, and grab any distros above it: */
764 if (isbrick(tux_x, tux_y, scroll_x) ||
765 isfullbox(tux_x, tux_y, scroll_x))
767 trygrabdistro(tux_x, tux_y - 32, scroll_x,
769 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
770 bumpbrick(tux_x, tux_y, scroll_x);
771 tryemptybox(tux_x, tux_y, scroll_x);
774 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
775 isfullbox(tux_x + 31, tux_y, scroll_x))
777 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
779 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
780 bumpbrick(tux_x + 31, tux_y, scroll_x);
781 tryemptybox(tux_x + 31, tux_y, scroll_x);
785 /* Get a distro from a brick? */
787 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
788 shape(tux_x, tux_y, scroll_x) == 'y')
790 add_bouncy_distro(((tux_x + scroll_x + 1)
794 if (counting_distros == NO)
796 counting_distros = YES;
797 distro_counter = 100;
800 if (distro_counter <= 0)
801 change(tux_x, tux_y, scroll_x, 'a');
803 playsound(sounds[SND_DISTRO]);
804 score = score + SCORE_DISTRO;
807 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
808 shape(tux_x + 31, tux_y, scroll_x) == 'y')
810 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
814 if (counting_distros == NO)
816 counting_distros = YES;
817 distro_counter = 100;
820 if (distro_counter <= 0)
821 change(tux_x + 31, tux_y, scroll_x, 'a');
823 playsound(sounds[SND_DISTRO]);
824 score = score + SCORE_DISTRO;
832 tux_y = (tux_y / 32) * 32 + 30;
838 tux_y = (tux_y / 32) * 32 - 32;
843 jump_counter = MAX_JUMP_COUNT;
853 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
854 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
856 if (tux_size == BIG && !tux_duck)
858 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
859 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
864 /* Enough distros for a One-up? */
866 if (distros >= DISTROS_LIFEUP)
868 distros = distros - DISTROS_LIFEUP;
869 if(lives < MAX_LIVES)
871 playsound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
875 /* Keep in-bounds, vertically: */
879 else if (tux_y > 480)
885 /* Slow down horizontally: */
889 if (right == UP && left == UP)
891 if (isice(tux_x, tux_y + 32, scroll_x) ||
892 !issolid(tux_x, tux_y + 32, scroll_x))
894 /* Slowly on ice or in air: */
903 /* Quickly, otherwise: */
910 /* Drop vertically: */
912 if (!issolid(tux_x, tux_y + 32, scroll_x))
914 tux_ym = tux_ym + GRAVITY;
926 /* ---- DONE HANDLING TUX! --- */
929 /* Handle bouncy distros: */
931 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
933 if (bouncy_distros[i].alive)
935 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
937 bouncy_distros[i].ym++;
939 if (bouncy_distros[i].ym >= 0)
940 bouncy_distros[i].alive = NO;
945 /* Handle broken bricks: */
947 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
949 if (broken_bricks[i].alive)
951 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
952 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
954 broken_bricks[i].ym++;
956 if (broken_bricks[i].ym >= 0)
957 broken_bricks[i].alive = NO;
962 /* Handle distro counting: */
964 if (counting_distros == YES)
968 if (distro_counter <= 0)
969 counting_distros = -1;
973 /* Handle bouncy bricks: */
975 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
977 if (bouncy_bricks[i].alive)
979 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
980 bouncy_bricks[i].offset_m);
984 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
985 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
990 if (bouncy_bricks[i].offset == 0)
991 bouncy_bricks[i].alive = NO;
996 /* Handle floating scores: */
998 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1000 if (floating_scores[i].alive)
1002 floating_scores[i].y = floating_scores[i].y - 2;
1003 floating_scores[i].timer--;
1005 if (floating_scores[i].timer <= 0)
1006 floating_scores[i].alive = NO;
1011 /* Handle bullets: */
1013 for (i = 0; i < NUM_BULLETS; i++)
1015 if (bullets[i].alive)
1017 bullets[i].x = bullets[i].x + bullets[i].xm;
1018 bullets[i].y = bullets[i].y + bullets[i].ym;
1020 if (issolid(bullets[i].x, bullets[i].y, 0))
1022 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1023 bullets[i].alive = NO;
1026 if (bullets[i].ym >= 0)
1028 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1030 bullets[i].ym = -bullets[i].ym;
1034 bullets[i].ym = bullets[i].ym + GRAVITY;
1036 if (bullets[i].x < scroll_x ||
1037 bullets[i].x > scroll_x + 640)
1039 bullets[i].alive = NO;
1044 if (bullets[i].alive)
1046 for (j = 0; j < NUM_BAD_GUYS; j++)
1048 if (bad_guys[j].alive && !bad_guys[j].dying)
1050 if (bullets[i].x >= bad_guys[j].x - 4 &&
1051 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1052 bullets[i].y >= bad_guys[j].y - 4 &&
1053 bullets[i].y <= bad_guys[j].y + 32 + 4)
1055 /* Kill the bad guy! */
1057 bullets[i].alive = 0;
1058 bad_guys[j].dying = FALLING;
1059 bad_guys[j].ym = -8;
1062 /* Gain some points: */
1064 if (bad_guys[j].kind == BAD_BSOD)
1066 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1067 50 * score_multiplier);
1069 else if (bad_guys[j].kind == BAD_LAPTOP)
1071 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1072 25 * score_multiplier);
1076 /* Play death sound: */
1077 playsound(sounds[SND_FALL]);
1085 /* Handle background timer: */
1087 if (super_bkgd_time)
1091 /* Handle invincibility timer: */
1093 if (tux_invincible_time)
1094 tux_invincible_time--;
1097 /* Handle upgrades: */
1099 for (i = 0; i < NUM_UPGRADES; i++)
1101 if (upgrades[i].alive)
1103 if (upgrades[i].height < 32)
1107 upgrades[i].height++;
1113 if (upgrades[i].kind == UPGRADE_MINTS ||
1114 upgrades[i].kind == UPGRADE_HERRING)
1116 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1117 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1119 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1120 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1122 if (upgrades[i].ym > 0)
1124 if (upgrades[i].kind == UPGRADE_MINTS)
1128 else if (upgrades[i].kind == UPGRADE_HERRING)
1130 upgrades[i].ym = -24;
1133 upgrades[i].y = (upgrades[i].y / 32) * 32;
1137 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1139 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1141 upgrades[i].xm = -upgrades[i].xm;
1146 /* Off the screen? Kill it! */
1148 if (upgrades[i].x < scroll_x)
1149 upgrades[i].alive = NO;
1152 /* Did the player grab it? */
1154 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1155 tux_x + scroll_x <= upgrades[i].x + 32 &&
1156 tux_y >= upgrades[i].y - 32 &&
1157 tux_y <= upgrades[i].y + 32)
1159 /* Remove the upgrade: */
1161 upgrades[i].alive = NO;
1164 /* Affect the player: */
1166 if (upgrades[i].kind == UPGRADE_MINTS)
1168 playsound(sounds[SND_EXCELLENT]);
1170 super_bkgd_time = 8;
1172 else if (upgrades[i].kind == UPGRADE_COFFEE)
1174 playsound(sounds[SND_COFFEE]);
1175 tux_got_coffee = YES;
1176 super_bkgd_time = 4;
1178 else if (upgrades[i].kind == UPGRADE_HERRING)
1180 playsound(sounds[SND_HERRING]);
1181 tux_invincible_time = 200;
1182 super_bkgd_time = 4;
1190 /* Handle bad guys: */
1192 for (i = 0; i < NUM_BAD_GUYS; i++)
1194 if (bad_guys[i].alive)
1196 if (bad_guys[i].seen)
1198 if (bad_guys[i].kind == BAD_BSOD)
1200 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1202 /* Move left/right: */
1204 if (bad_guys[i].dying == NO ||
1205 bad_guys[i].dying == FALLING)
1207 if (bad_guys[i].dir == RIGHT)
1208 bad_guys[i].x = bad_guys[i].x + 4;
1209 else if (bad_guys[i].dir == LEFT)
1210 bad_guys[i].x = bad_guys[i].x - 4;
1214 /* Move vertically: */
1216 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1219 /* Bump into things horizontally: */
1221 if (!bad_guys[i].dying)
1223 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1224 bad_guys[i].dir = !bad_guys[i].dir;
1228 /* Bump into other bad guys: */
1230 for (j = 0; j < NUM_BAD_GUYS; j++)
1232 if (j != i && bad_guys[j].alive &&
1233 !bad_guys[j].dying && !bad_guys[i].dying &&
1234 bad_guys[i].x >= bad_guys[j].x - 32 &&
1235 bad_guys[i].x <= bad_guys[j].x + 32 &&
1236 bad_guys[i].y >= bad_guys[j].y - 32 &&
1237 bad_guys[i].y <= bad_guys[j].y + 32)
1239 bad_guys[i].dir = !bad_guys[i].dir;
1244 /* Fall if we get off the ground: */
1246 if (bad_guys[i].dying != FALLING)
1248 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1249 bad_guys[i].ym < MAX_YM)
1251 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1257 if (bad_guys[i].ym > 0)
1259 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1265 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1267 if (bad_guys[i].y > 480)
1268 bad_guys[i].alive = NO;
1270 else if (bad_guys[i].kind == BAD_LAPTOP)
1272 /* --- LAPTOP MONSTER: --- */
1274 /* Move left/right: */
1276 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1278 if (bad_guys[i].dying == NO ||
1279 bad_guys[i].dying == FALLING)
1281 if (bad_guys[i].dir == RIGHT)
1282 bad_guys[i].x = bad_guys[i].x + 4;
1283 else if (bad_guys[i].dir == LEFT)
1284 bad_guys[i].x = bad_guys[i].x - 4;
1287 else if (bad_guys[i].mode == KICK)
1289 if (bad_guys[i].dir == RIGHT)
1290 bad_guys[i].x = bad_guys[i].x + 16;
1291 else if (bad_guys[i].dir == LEFT)
1292 bad_guys[i].x = bad_guys[i].x - 16;
1296 /* Move vertically: */
1298 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1301 /* Bump into things horizontally: */
1303 if (!bad_guys[i].dying)
1305 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1307 bad_guys[i].dir = !bad_guys[i].dir;
1309 if (bad_guys[i].mode == KICK)
1310 playsound(sounds[SND_RICOCHET]);
1315 /* Bump into other bad guys: */
1317 for (j = 0; j < NUM_BAD_GUYS; j++)
1319 if (j != i && bad_guys[j].alive &&
1320 !bad_guys[j].dying && !bad_guys[i].dying &&
1321 bad_guys[i].x >= bad_guys[j].x - 32 &&
1322 bad_guys[i].x <= bad_guys[j].x + 32 &&
1323 bad_guys[i].y >= bad_guys[j].y - 32 &&
1324 bad_guys[i].y <= bad_guys[j].y + 32)
1326 if (bad_guys[i].mode != KICK)
1327 bad_guys[i].dir = !bad_guys[i].dir;
1330 /* We're in kick mode, kill the other guy: */
1332 bad_guys[j].dying = FALLING;
1333 bad_guys[j].ym = -8;
1334 playsound(sounds[SND_FALL]);
1336 add_score(bad_guys[i].x - scroll_x,
1337 bad_guys[i].y, 100);
1343 /* Fall if we get off the ground: */
1345 if (bad_guys[i].dying != FALLING)
1347 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1348 bad_guys[i].ym < MAX_YM)
1350 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1356 if (bad_guys[i].ym > 0)
1358 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1364 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1366 if (bad_guys[i].y > 480)
1367 bad_guys[i].alive = NO;
1369 else if (bad_guys[i].kind == BAD_MONEY)
1371 /* --- MONEY BAGS: --- */
1374 /* Move vertically: */
1376 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1379 /* Fall if we get off the ground: */
1381 if (bad_guys[i].dying != FALLING)
1383 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1385 if (bad_guys[i].ym < MAX_YM)
1387 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1394 if (bad_guys[i].ym > 0)
1396 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1397 bad_guys[i].ym = -MAX_YM;
1402 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1404 if (bad_guys[i].y > 480)
1405 bad_guys[i].alive = NO;
1407 else if (bad_guys[i].kind == -1)
1412 /* Kill it if the player jumped on it: */
1414 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1415 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1416 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1417 tux_y >= bad_guys[i].y - 32 &&
1418 tux_y <= bad_guys[i].y - 8
1422 if (bad_guys[i].kind == BAD_BSOD)
1424 bad_guys[i].dying = SQUISHED;
1425 bad_guys[i].timer = 16;
1426 tux_ym = -KILL_BOUNCE_YM;
1428 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1429 50 * score_multiplier);
1431 playsound(sounds[SND_SQUISH]);
1433 else if (bad_guys[i].kind == BAD_LAPTOP)
1435 if (bad_guys[i].mode != FLAT)
1439 bad_guys[i].mode = FLAT;
1441 bad_guys[i].timer = 64;
1449 bad_guys[i].mode = KICK;
1451 if (tux_x + scroll_x <= bad_guys[i].x)
1452 bad_guys[i].dir = RIGHT;
1454 bad_guys[i].dir = LEFT;
1456 bad_guys[i].timer = 8;
1459 tux_ym = -KILL_BOUNCE_YM;
1461 add_score(bad_guys[i].x - scroll_x,
1463 25 * score_multiplier);
1465 /* playsound(sounds[SND_SQUISH]); */
1467 else if (bad_guys[i].kind == -1)
1475 /* Hurt the player if he just touched it: */
1477 if (!bad_guys[i].dying && !tux_dying &&
1479 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1480 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1481 tux_y >= bad_guys[i].y - 32 &&
1482 tux_y <= bad_guys[i].y + 32)
1484 if (bad_guys[i].mode == FLAT)
1488 bad_guys[i].mode = KICK;
1490 if (tux_x < bad_guys[i].x)
1492 bad_guys[i].dir = RIGHT;
1493 bad_guys[i].x = bad_guys[i].x + 16;
1497 bad_guys[i].dir = LEFT;
1498 bad_guys[i].x = bad_guys[i].x - 16;
1501 bad_guys[i].timer = 8;
1503 else if (bad_guys[i].mode == KICK)
1505 if (tux_y < bad_guys[i].y - 16 &&
1506 bad_guys[i].timer == 0)
1508 /* Step on (stop being kicked) */
1510 bad_guys[i].mode = FLAT;
1511 bad_guys[i].timer = 64;
1515 /* Hurt if you get hit by kicked laptop: */
1517 if (bad_guys[i].timer == 0)
1519 if (tux_invincible_time == 0)
1525 bad_guys[i].dying = FALLING;
1526 bad_guys[i].ym = -8;
1527 playsound(sounds[SND_FALL]);
1534 if (tux_invincible_time == 0)
1540 bad_guys[i].dying = FALLING;
1541 bad_guys[i].ym = -8;
1542 playsound(sounds[SND_FALL]);
1548 /* Handle mode timer: */
1550 if (bad_guys[i].mode == FLAT)
1552 bad_guys[i].timer--;
1554 if (bad_guys[i].timer <= 0)
1555 bad_guys[i].mode = NORMAL;
1557 else if (bad_guys[i].mode == KICK)
1559 if (bad_guys[i].timer > 0)
1560 bad_guys[i].timer--;
1564 /* Handle dying timer: */
1566 if (bad_guys[i].dying == SQUISHED)
1568 bad_guys[i].timer--;
1571 /* Remove it if time's up: */
1573 if (bad_guys[i].timer <= 0)
1574 bad_guys[i].alive = NO;
1578 /* Remove if it's far off the screen: */
1580 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1581 bad_guys[i].alive = NO;
1585 /* Once it's on screen, it's activated! */
1587 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1588 bad_guys[i].seen = YES;
1594 /* Handle skidding: */
1596 if (tux_skidding > 0)
1604 if (tux_dying && (frame % 4) == 0)
1605 clearscreen(255, 255, 255);
1608 if (super_bkgd_time == 0)
1609 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1611 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1615 /* Draw background: */
1617 for (y = 0; y < 15; y++)
1619 for (x = 0; x < 21; x++)
1621 drawshape(x * 32 - (scroll_x % 32), y * 32,
1622 tiles[y][x + (scroll_x / 32)]);
1627 /* (Bouncy bricks): */
1629 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1631 if (bouncy_bricks[i].alive)
1633 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1634 bouncy_bricks[i].x <= scroll_x + 640)
1636 dest.x = bouncy_bricks[i].x - scroll_x;
1637 dest.y = bouncy_bricks[i].y;
1641 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1646 drawshape(bouncy_bricks[i].x - scroll_x,
1647 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1648 bouncy_bricks[i].shape);
1656 for (i = 0; i < NUM_BAD_GUYS; i++)
1658 if (bad_guys[i].alive &&
1659 bad_guys[i].x > scroll_x - 32 &&
1660 bad_guys[i].x < scroll_x + 640)
1662 if (bad_guys[i].kind == BAD_BSOD)
1664 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1666 if (bad_guys[i].dying == NO)
1670 if (bad_guys[i].dir == LEFT)
1672 drawimage(img_bsod_left[(frame / 5) % 4],
1673 bad_guys[i].x - scroll_x,
1679 drawimage(img_bsod_right[(frame / 5) % 4],
1680 bad_guys[i].x - scroll_x,
1685 else if (bad_guys[i].dying == FALLING)
1689 if (bad_guys[i].dir == LEFT)
1691 drawimage(img_bsod_falling_left,
1692 bad_guys[i].x - scroll_x,
1698 drawimage(img_bsod_falling_right,
1699 bad_guys[i].x - scroll_x,
1704 else if (bad_guys[i].dying == SQUISHED)
1706 /* Dying - Squished: */
1708 if (bad_guys[i].dir == LEFT)
1710 drawimage(img_bsod_squished_left,
1711 bad_guys[i].x - scroll_x,
1717 drawimage(img_bsod_squished_right,
1718 bad_guys[i].x - scroll_x,
1724 else if (bad_guys[i].kind == BAD_LAPTOP)
1726 /* --- LAPTOP MONSTER: --- */
1728 if (bad_guys[i].dying == NO)
1732 if (bad_guys[i].mode == NORMAL)
1736 if (bad_guys[i].dir == LEFT)
1738 drawimage(img_laptop_left[(frame / 5) % 3],
1739 bad_guys[i].x - scroll_x,
1745 drawimage(img_laptop_right[(frame / 5) % 3],
1746 bad_guys[i].x - scroll_x,
1755 if (bad_guys[i].dir == LEFT)
1757 drawimage(img_laptop_flat_left,
1758 bad_guys[i].x - scroll_x,
1764 drawimage(img_laptop_flat_right,
1765 bad_guys[i].x - scroll_x,
1771 else if (bad_guys[i].dying == FALLING)
1775 if (bad_guys[i].dir == LEFT)
1777 drawimage(img_laptop_falling_left,
1778 bad_guys[i].x - scroll_x,
1784 drawimage(img_laptop_falling_right,
1785 bad_guys[i].x - scroll_x,
1791 else if (bad_guys[i].kind == BAD_MONEY)
1793 if (bad_guys[i].ym > -16)
1795 if (bad_guys[i].dir == LEFT)
1797 drawimage(img_money_left[0],
1798 bad_guys[i].x - scroll_x,
1804 drawimage(img_money_right[0],
1805 bad_guys[i].x - scroll_x,
1812 if (bad_guys[i].dir == LEFT)
1814 drawimage(img_money_left[1],
1815 bad_guys[i].x - scroll_x,
1821 drawimage(img_money_right[1],
1822 bad_guys[i].x - scroll_x,
1828 else if (bad_guys[i].kind == -1)
1837 if (right == UP && left == UP)
1844 if ((fire == DOWN && (frame % 2) == 0) ||
1846 tux_frame_main = (tux_frame_main + 1) % 4;
1848 tux_frame = tux_frame_main;
1855 if (tux_got_coffee && (frame % 2) == 1)
1859 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1863 if (tux_safe == 0 || (frame % 2) == 0)
1865 if (tux_size == SMALL)
1867 if (tux_invincible_time)
1871 if (tux_dir == RIGHT)
1873 drawimage(cape_right[frame % 2],
1879 drawimage(cape_left[frame % 2],
1886 if (tux_dir == RIGHT)
1888 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1892 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1897 if (tux_invincible_time)
1901 if (tux_dir == RIGHT)
1903 drawimage(bigcape_right[frame % 2],
1904 tux_x - 8 - 16, tux_y - 32,
1909 drawimage(bigcape_left[frame % 2],
1910 tux_x - 8, tux_y - 32,
1919 if (!jumping || tux_ym > 0)
1921 if (tux_dir == RIGHT)
1923 drawimage(bigtux_right[tux_frame],
1924 tux_x - 8, tux_y - 32,
1929 drawimage(bigtux_left[tux_frame],
1930 tux_x - 8, tux_y - 32,
1936 if (tux_dir == RIGHT)
1938 drawimage(bigtux_right_jump,
1939 tux_x - 8, tux_y - 32,
1944 drawimage(bigtux_left_jump,
1945 tux_x - 8, tux_y - 32,
1952 if (tux_dir == RIGHT)
1954 drawimage(skidtux_right,
1955 tux_x - 8, tux_y - 32,
1960 drawimage(skidtux_left,
1961 tux_x - 8, tux_y - 32,
1968 if (tux_dir == RIGHT)
1970 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
1975 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
1985 for (i = 0; i < NUM_BULLETS; i++)
1987 if (bullets[i].alive &&
1988 bullets[i].x >= scroll_x - 4 &&
1989 bullets[i].x <= scroll_x + 640)
1991 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
1997 /* (Floating scores): */
1999 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2001 if (floating_scores[i].alive)
2003 sprintf(str, "%d", floating_scores[i].value);
2005 floating_scores[i].x + 16 - strlen(str) * 8,
2006 floating_scores[i].y,
2007 letters_gold, NO_UPDATE);
2014 for (i = 0; i < NUM_UPGRADES; i++)
2016 if (upgrades[i].alive)
2018 if (upgrades[i].height < 32)
2022 dest.x = upgrades[i].x - scroll_x;
2023 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2025 dest.h = upgrades[i].height;
2030 src.h = upgrades[i].height;
2032 if (upgrades[i].kind == UPGRADE_MINTS)
2033 SDL_BlitSurface(img_mints, &src, screen, &dest);
2034 else if (upgrades[i].kind == UPGRADE_COFFEE)
2035 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2036 else if (upgrades[i].kind == UPGRADE_HERRING)
2037 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2041 if (upgrades[i].kind == UPGRADE_MINTS)
2043 drawimage(img_mints,
2044 upgrades[i].x - scroll_x, upgrades[i].y,
2047 else if (upgrades[i].kind == UPGRADE_COFFEE)
2049 drawimage(img_coffee,
2050 upgrades[i].x - scroll_x, upgrades[i].y,
2053 else if (upgrades[i].kind == UPGRADE_HERRING)
2055 drawimage(img_golden_herring,
2056 upgrades[i].x - scroll_x, upgrades[i].y,
2064 /* (Bouncy distros): */
2066 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2068 if (bouncy_distros[i].alive)
2070 drawimage(img_distro[0],
2071 bouncy_distros[i].x - scroll_x,
2072 bouncy_distros[i].y,
2078 /* (Broken bricks): */
2080 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2082 if (broken_bricks[i].alive)
2084 src.x = rand() % 16;
2085 src.y = rand() % 16;
2089 dest.x = broken_bricks[i].x - scroll_x;
2090 dest.y = broken_bricks[i].y;
2094 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2101 sprintf(str, "%d", score);
2102 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2103 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2105 sprintf(str, "%d", highscore);
2106 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2107 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2109 if (time_left >= 50 || (frame % 10) < 5)
2111 sprintf(str, "%d", time_left);
2112 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2113 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2116 sprintf(str, "%d", distros);
2117 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2118 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2121 /* (Update it all!) */
2126 /* Keep playing music: */
2130 if (!Mix_PlayingMusic())
2132 Mix_PlayMusic(song, 1);
2137 /* Pause til next frame: */
2139 now_time = SDL_GetTicks();
2140 if (now_time < last_time + FPS)
2141 SDL_Delay(last_time + FPS - now_time);
2146 if ((frame % 10) == 0 && time_left > 0)
2154 while (!done && !quit);
2158 if (Mix_PlayingMusic())
2170 /* Initialize the game stuff: */
2181 /* Load data for this level: */
2183 void loadlevel(void)
2194 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2195 bouncy_distros[i].alive = NO;
2197 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2198 broken_bricks[i].alive = NO;
2200 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2201 bouncy_bricks[i].alive = NO;
2203 for (i = 0; i < NUM_BAD_GUYS; i++)
2204 bad_guys[i].alive = NO;
2206 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2207 floating_scores[i].alive = NO;
2209 for (i = 0; i < NUM_UPGRADES; i++)
2210 upgrades[i].alive = NO;
2212 for (i = 0; i < NUM_BULLETS; i++)
2213 bullets[i].alive = NO;
2216 /* Load data file: */
2218 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2219 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2220 fi = fopen(filename, "r");
2229 /* Load header info: */
2233 strcpy(levelname, str);
2237 strcpy(leveltheme, str);
2238 leveltheme[strlen(leveltheme)-1] = '\0';
2240 /* (Time to beat level) */
2242 time_left = atoi(str);
2244 /* (Song file for this level) */
2246 strcpy(song_title, str);
2247 song_title[strlen(song_title)-1] = '\0';
2249 /* (Level background color) */
2251 bkgd_red = atoi(str);
2253 bkgd_green= atoi(str);
2255 bkgd_blue = atoi(str);
2259 level_width = atoi(str);
2262 /* Allocate some space for the line-reading! */
2264 line = (char *) malloc(sizeof(char) * (level_width + 5));
2267 fprintf(stderr, "Couldn't allocate space to load level data!");
2272 /* Load the level lines: */
2274 for (y = 0; y < 15; y++)
2276 fgets(line, level_width + 5, fi);
2277 line[strlen(line) - 1] = '\0';
2278 tiles[y] = strdup(line);
2284 /* Activate bad guys: */
2286 for (y = 0; y < 15; y++)
2288 for (x = 0; x < level_width; x++)
2290 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2292 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2307 tux_got_coffee = NO;
2308 tux_invincible_time = 0;
2312 tux_safe = TUX_SAFE_TIME;
2328 score_multiplier = 1;
2329 super_bkgd_time = 0;
2333 counting_distros = NO;
2339 clearscreen(0, 0, 0);
2341 sprintf(str, "LEVEL %d", level);
2342 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2344 sprintf(str, "%s", levelname);
2345 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2347 sprintf(str, "TUX x %d", lives);
2348 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2356 /* Load a level-specific graphic... */
2358 SDL_Surface * load_level_image(char * file, int use_alpha)
2362 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2364 return(load_image(fname, use_alpha));
2368 /* Load graphics: */
2370 void loadlevelgfx(void)
2372 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2373 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2375 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2376 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2377 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2378 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2380 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2381 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2382 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2383 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2385 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2386 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2387 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2388 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2394 void loadlevelsong(void)
2399 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2400 strlen(song_title) + 8));
2402 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2404 song = load_song(song_path);
2410 /* Free graphics data for this level: */
2412 void unloadlevelgfx(void)
2416 for (i = 0; i < 2; i++)
2418 SDL_FreeSurface(img_brick[i]);
2420 for (i = 0; i < 4; i++)
2422 SDL_FreeSurface(img_solid[i]);
2423 SDL_FreeSurface(img_bkgd[0][i]);
2424 SDL_FreeSurface(img_bkgd[1][i]);
2429 /* Free music data for this level: */
2431 void unloadlevelsong(void)
2435 Mix_FreeMusic(song);
2440 /* Load graphics shared between all levels: */
2442 void loadshared(void)
2449 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2452 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2455 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2458 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2461 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2464 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2467 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2470 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2473 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2476 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2479 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2482 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2485 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2489 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2491 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2494 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2497 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2501 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2504 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2508 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2512 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2516 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2519 ducktux_right = load_image(DATA_PREFIX
2520 "/images/shared/ducktux-right.png",
2523 ducktux_left = load_image(DATA_PREFIX
2524 "/images/shared/ducktux-left.png",
2527 skidtux_right = load_image(DATA_PREFIX
2528 "/images/shared/skidtux-right.png",
2531 skidtux_left = load_image(DATA_PREFIX
2532 "/images/shared/skidtux-left.png",
2538 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2540 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2547 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2549 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2552 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2555 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2561 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2562 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2568 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2570 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2576 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2579 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2582 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2585 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2589 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2592 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2595 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2598 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2606 img_bsod_left[0] = load_image(DATA_PREFIX
2607 "/images/shared/bsod-left-0.png",
2610 img_bsod_left[1] = load_image(DATA_PREFIX
2611 "/images/shared/bsod-left-1.png",
2614 img_bsod_left[2] = load_image(DATA_PREFIX
2615 "/images/shared/bsod-left-2.png",
2618 img_bsod_left[3] = load_image(DATA_PREFIX
2619 "/images/shared/bsod-left-3.png",
2622 img_bsod_right[0] = load_image(DATA_PREFIX
2623 "/images/shared/bsod-right-0.png",
2626 img_bsod_right[1] = load_image(DATA_PREFIX
2627 "/images/shared/bsod-right-1.png",
2630 img_bsod_right[2] = load_image(DATA_PREFIX
2631 "/images/shared/bsod-right-2.png",
2634 img_bsod_right[3] = load_image(DATA_PREFIX
2635 "/images/shared/bsod-right-3.png",
2638 img_bsod_squished_left = load_image(DATA_PREFIX
2639 "/images/shared/bsod-squished-left.png",
2642 img_bsod_squished_right = load_image(DATA_PREFIX
2643 "/images/shared/bsod-squished-right.png",
2646 img_bsod_falling_left = load_image(DATA_PREFIX
2647 "/images/shared/bsod-falling-left.png",
2650 img_bsod_falling_right = load_image(DATA_PREFIX
2651 "/images/shared/bsod-falling-right.png",
2657 img_laptop_left[0] = load_image(DATA_PREFIX
2658 "/images/shared/laptop-left-0.png",
2661 img_laptop_left[1] = load_image(DATA_PREFIX
2662 "/images/shared/laptop-left-1.png",
2665 img_laptop_left[2] = load_image(DATA_PREFIX
2666 "/images/shared/laptop-left-2.png",
2669 img_laptop_right[0] = load_image(DATA_PREFIX
2670 "/images/shared/laptop-right-0.png",
2673 img_laptop_right[1] = load_image(DATA_PREFIX
2674 "/images/shared/laptop-right-1.png",
2677 img_laptop_right[2] = load_image(DATA_PREFIX
2678 "/images/shared/laptop-right-2.png",
2681 img_laptop_flat_left = load_image(DATA_PREFIX
2682 "/images/shared/laptop-flat-left.png",
2685 img_laptop_flat_right = load_image(DATA_PREFIX
2686 "/images/shared/laptop-flat-right.png",
2689 img_laptop_falling_left =
2690 load_image(DATA_PREFIX
2691 "/images/shared/laptop-falling-left.png",
2694 img_laptop_falling_right =
2695 load_image(DATA_PREFIX
2696 "/images/shared/laptop-falling-right.png",
2702 img_money_left[0] = load_image(DATA_PREFIX
2703 "/images/shared/bag-left-0.png",
2706 img_money_left[1] = load_image(DATA_PREFIX
2707 "/images/shared/bag-left-1.png",
2710 img_money_right[0] = load_image(DATA_PREFIX
2711 "/images/shared/bag-right-0.png",
2714 img_money_right[1] = load_image(DATA_PREFIX
2715 "/images/shared/bag-right-1.png",
2722 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2723 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2728 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2730 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2736 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2739 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2742 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2745 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2751 img_golden_herring =
2752 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2756 /* Super background: */
2758 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2762 /* Sound effects: */
2766 for (i = 0; i < NUM_SOUNDS; i++)
2767 sounds[i] = load_sound(soundfilenames[i]);
2773 /* Free shared data: */
2775 void unloadshared(void)
2779 for (i = 0; i < 3; i++)
2781 SDL_FreeSurface(tux_right[i]);
2782 SDL_FreeSurface(tux_left[i]);
2783 SDL_FreeSurface(bigtux_right[i]);
2784 SDL_FreeSurface(bigtux_left[i]);
2787 SDL_FreeSurface(bigtux_right_jump);
2788 SDL_FreeSurface(bigtux_left_jump);
2790 for (i = 0; i < 2; i++)
2792 SDL_FreeSurface(cape_right[i]);
2793 SDL_FreeSurface(cape_left[i]);
2794 SDL_FreeSurface(bigcape_right[i]);
2795 SDL_FreeSurface(bigcape_left[i]);
2798 SDL_FreeSurface(ducktux_left);
2799 SDL_FreeSurface(ducktux_right);
2801 SDL_FreeSurface(skidtux_left);
2802 SDL_FreeSurface(skidtux_right);
2804 for (i = 0; i < 4; i++)
2806 SDL_FreeSurface(img_bsod_left[i]);
2807 SDL_FreeSurface(img_bsod_right[i]);
2810 SDL_FreeSurface(img_bsod_squished_left);
2811 SDL_FreeSurface(img_bsod_squished_right);
2813 SDL_FreeSurface(img_bsod_falling_left);
2814 SDL_FreeSurface(img_bsod_falling_right);
2816 for (i = 0; i < 3; i++)
2818 SDL_FreeSurface(img_laptop_left[i]);
2819 SDL_FreeSurface(img_laptop_right[i]);
2822 SDL_FreeSurface(img_laptop_flat_left);
2823 SDL_FreeSurface(img_laptop_flat_right);
2825 SDL_FreeSurface(img_laptop_falling_left);
2826 SDL_FreeSurface(img_laptop_falling_right);
2828 for (i = 0; i < 2; i++)
2830 SDL_FreeSurface(img_money_left[i]);
2831 SDL_FreeSurface(img_money_right[i]);
2834 SDL_FreeSurface(img_box_full);
2835 SDL_FreeSurface(img_box_empty);
2837 SDL_FreeSurface(img_water);
2838 for (i = 0; i < 3; i++)
2839 SDL_FreeSurface(img_waves[i]);
2841 SDL_FreeSurface(img_pole);
2842 SDL_FreeSurface(img_poletop);
2844 for (i = 0; i < 2; i++)
2845 SDL_FreeSurface(img_flag[i]);
2847 SDL_FreeSurface(img_mints);
2848 SDL_FreeSurface(img_coffee);
2850 for (i = 0; i < 4; i++)
2852 SDL_FreeSurface(img_distro[i]);
2853 SDL_FreeSurface(img_cloud[0][i]);
2854 SDL_FreeSurface(img_cloud[1][i]);
2857 SDL_FreeSurface(img_golden_herring);
2861 for (i = 0; i < NUM_SOUNDS; i++)
2862 Mix_FreeChunk(sounds[i]);
2867 /* Draw a tile on the screen: */
2869 void drawshape(int x, int y, unsigned char c)
2873 if (c == 'X' || c == 'x')
2874 drawimage(img_brick[0], x, y, NO_UPDATE);
2875 else if (c == 'Y' || c == 'y')
2876 drawimage(img_brick[1], x, y, NO_UPDATE);
2877 else if (c == 'A' || c =='B' || c == '!')
2878 drawimage(img_box_full, x, y, NO_UPDATE);
2880 drawimage(img_box_empty, x, y, NO_UPDATE);
2881 else if (c >= 'C' && c <= 'F')
2882 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
2883 else if (c >= 'c' && c <= 'f')
2884 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
2885 else if (c >= 'G' && c <= 'J')
2886 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
2887 else if (c >= 'g' && c <= 'j')
2888 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
2890 drawimage(img_solid[0], x, y, NO_UPDATE);
2892 drawimage(img_solid[1], x, y, NO_UPDATE);
2894 drawimage(img_solid[2], x, y, NO_UPDATE);
2896 drawimage(img_solid[3], x, y, NO_UPDATE);
2899 z = (frame / 2) % 6;
2902 drawimage(img_distro[z], x, y, NO_UPDATE);
2904 drawimage(img_distro[2], x, y, NO_UPDATE);
2906 drawimage(img_distro[1], x, y, NO_UPDATE);
2910 z = (frame / 3) % 3;
2912 drawimage(img_waves[z], x, y, NO_UPDATE);
2915 drawimage(img_poletop, x, y, NO_UPDATE);
2918 drawimage(img_pole, x, y, NO_UPDATE);
2920 /* Mark this as the end position of the level! */
2926 z = (frame / 3) % 2;
2928 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
2931 drawimage(img_water, x, y, NO_UPDATE);
2935 /* What shape is at some position? */
2937 unsigned char shape(int x, int y, int sx)
2943 xx = ((x + sx) / 32);
2945 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
2956 int issolid(int x, int y, int sx)
2962 if (isbrick(x, y, sx) ||
2963 isbrick(x + 31, y, sx) ||
2965 isice(x + 31, y, sx) ||
2966 (shape(x, y, sx) == '[' ||
2967 shape(x + 31, y, sx) == '[') ||
2968 (shape(x, y, sx) == '=' ||
2969 shape(x + 31, y, sx) == '=') ||
2970 (shape(x, y, sx) == ']' ||
2971 shape(x + 31, y, sx) == ']') ||
2972 (shape(x, y, sx) == 'A' ||
2973 shape(x + 31, y, sx) == 'A') ||
2974 (shape(x, y, sx) == 'B' ||
2975 shape(x + 31, y, sx) == 'B') ||
2976 (shape(x, y, sx) == '!' ||
2977 shape(x + 31, y, sx) == '!') ||
2978 (shape(x, y, sx) == 'a' ||
2979 shape(x + 31, y, sx) == 'a'))
2988 /* Is it a brick? */
2990 int isbrick(int x, int y, int sx)
2996 if (shape(x, y, sx) == 'X' ||
2997 shape(x, y, sx) == 'x' ||
2998 shape(x, y, sx) == 'Y' ||
2999 shape(x, y, sx) == 'y')
3010 int isice(int x, int y, int sx)
3016 if (shape(x, y, sx) == '#')
3025 /* Is it a full box? */
3027 int isfullbox(int x, int y, int sx)
3033 if (shape(x, y, sx) == 'A' ||
3034 shape(x, y, sx) == 'B' ||
3035 shape(x, y, sx) == '!')
3044 /* Edit a piece of the map! */
3046 void change(int x, int y, int sx, unsigned char c)
3051 xx = ((x + sx) / 32);
3053 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3058 /* Break a brick: */
3060 void trybreakbrick(int x, int y, int sx)
3062 if (isbrick(x, y, sx))
3064 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3066 /* Get a distro from it: */
3068 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3071 if (counting_distros == NO)
3073 counting_distros = YES;
3074 distro_counter = 50;
3077 if (distro_counter <= 0)
3078 change(x, y, sx, 'a');
3080 playsound(sounds[SND_DISTRO]);
3081 score = score + SCORE_DISTRO;
3086 /* Get rid of it: */
3088 change(x, y, sx, '.');
3092 /* Replace it with broken bits: */
3094 add_broken_brick(((x + sx + 1) / 32) * 32,
3098 /* Get some score: */
3100 playsound(sounds[SND_BRICK]);
3101 score = score + SCORE_BRICK;
3106 /* Bounce a brick: */
3108 void bumpbrick(int x, int y, int sx)
3110 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3113 playsound(sounds[SND_BRICK]);
3119 void tryemptybox(int x, int y, int sx)
3121 if (isfullbox(x, y, sx))
3123 if (shape(x, y, sx) == 'A')
3125 /* Box with a distro! */
3127 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3128 (y / 32) * 32 - 32);
3130 playsound(sounds[SND_DISTRO]);
3131 score = score + SCORE_DISTRO;
3134 else if (shape(x, y, sx) == 'B')
3136 /* Add an upgrade! */
3138 if (tux_size == SMALL)
3140 /* Tux is small, add mints! */
3142 add_upgrade(((x + sx + 1) / 32) * 32,
3148 /* Tux is big, add coffee: */
3150 add_upgrade(((x + sx + 1) / 32) * 32,
3155 playsound(sounds[SND_UPGRADE]);
3157 else if (shape(x, y, sx) == '!')
3159 /* Add a golden herring */
3161 add_upgrade(((x + sx + 1) / 32) * 32,
3166 /* Empty the box: */
3168 change(x, y, sx, 'a');
3173 /* Try to grab a distro: */
3175 void trygrabdistro(int x, int y, int sx, int bounciness)
3177 if (shape(x, y, sx) == '$')
3179 change(x, y, sx, '.');
3180 playsound(sounds[SND_DISTRO]);
3182 if (bounciness == BOUNCE)
3184 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3188 score = score + SCORE_DISTRO;
3194 /* Add a bouncy distro: */
3196 void add_bouncy_distro(int x, int y)
3202 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3204 if (!bouncy_distros[i].alive)
3210 bouncy_distros[found].alive = YES;
3211 bouncy_distros[found].x = x;
3212 bouncy_distros[found].y = y;
3213 bouncy_distros[found].ym = -6;
3218 /* Add broken brick pieces: */
3220 void add_broken_brick(int x, int y)
3222 add_broken_brick_piece(x, y, -4, -16);
3223 add_broken_brick_piece(x, y + 16, -6, -12);
3225 add_broken_brick_piece(x + 16, y, 4, -16);
3226 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3230 /* Add a broken brick piece: */
3232 void add_broken_brick_piece(int x, int y, int xm, int ym)
3238 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3240 if (!broken_bricks[i].alive)
3246 broken_bricks[found].alive = YES;
3247 broken_bricks[found].x = x;
3248 broken_bricks[found].y = y;
3249 broken_bricks[found].xm = xm;
3250 broken_bricks[found].ym = ym;
3255 /* Add a bouncy brick piece: */
3257 void add_bouncy_brick(int x, int y)
3263 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3265 if (!bouncy_bricks[i].alive)
3271 bouncy_bricks[found].alive = YES;
3272 bouncy_bricks[found].x = x;
3273 bouncy_bricks[found].y = y;
3274 bouncy_bricks[found].offset = 0;
3275 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3276 bouncy_bricks[found].shape = shape(x, y, 0);
3281 /* Add a bad guy: */
3283 void add_bad_guy(int x, int y, int kind)
3289 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3291 if (!bad_guys[i].alive)
3297 bad_guys[found].alive = YES;
3298 bad_guys[found].mode = NORMAL;
3299 bad_guys[found].dying = NO;
3300 bad_guys[found].timer = 0;
3301 bad_guys[found].kind = kind;
3302 bad_guys[found].x = x;
3303 bad_guys[found].y = y;
3304 bad_guys[found].xm = 0;
3305 bad_guys[found].ym = 0;
3306 bad_guys[found].dir = LEFT;
3307 bad_guys[found].seen = NO;
3314 void add_score(int x, int y, int s)
3319 /* Add the score: */
3324 /* Add a floating score thing to the game: */
3328 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3330 if (!floating_scores[i].alive)
3337 floating_scores[found].alive = YES;
3338 floating_scores[found].x = x;
3339 floating_scores[found].y = y - 16;
3340 floating_scores[found].timer = 8;
3341 floating_scores[found].value = s;
3346 /* Try to bump a bad guy from below: */
3348 void trybumpbadguy(int x, int y, int sx)
3355 for (i = 0; i < NUM_BAD_GUYS; i++)
3357 if (bad_guys[i].alive &&
3358 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3359 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3361 if (bad_guys[i].kind == BAD_BSOD ||
3362 bad_guys[i].kind == BAD_LAPTOP)
3364 bad_guys[i].dying = FALLING;
3365 bad_guys[i].ym = -8;
3366 playsound(sounds[SND_FALL]);
3374 for (i = 0; i < NUM_UPGRADES; i++)
3376 if (upgrades[i].alive && upgrades[i].height == 32 &&
3377 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3378 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3380 upgrades[i].xm = -upgrades[i].xm;
3381 upgrades[i].ym = -8;
3382 playsound(sounds[SND_BUMP_UPGRADE]);
3388 /* Add an upgrade: */
3390 void add_upgrade(int x, int y, int kind)
3396 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3398 if (!upgrades[i].alive)
3404 upgrades[found].alive = YES;
3405 upgrades[found].kind = kind;
3406 upgrades[found].x = x;
3407 upgrades[found].y = y;
3408 upgrades[found].xm = 4;
3409 upgrades[found].ym = -4;
3410 upgrades[found].height = 0;
3417 void killtux(int mode)
3421 playsound(sounds[SND_HURT]);
3423 if (tux_dir == RIGHT)
3425 else if (tux_dir == LEFT)
3428 if (mode == SHRINK && tux_size == BIG)
3431 tux_got_coffee = NO;
3435 tux_safe = TUX_SAFE_TIME;
3446 void add_bullet(int x, int y, int dir, int xm)
3452 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3454 if (!bullets[i].alive)
3460 bullets[found].alive = YES;
3464 bullets[found].x = x + 32;
3465 bullets[found].xm = BULLET_XM + xm;
3469 bullets[found].x = x;
3470 bullets[found].xm = -BULLET_XM + xm;
3473 bullets[found].y = y;
3474 bullets[found].ym = BULLET_STARTING_YM;
3476 playsound(sounds[SND_SHOOT]);
3481 void drawendscreen(void)
3485 clearscreen(0, 0, 0);
3487 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3489 sprintf(str, "SCORE: %d", score);
3490 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3492 sprintf(str, "DISTROS: %d", distros);
3493 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3499 void drawresultscreen(void)
3503 clearscreen(0, 0, 0);
3505 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3507 sprintf(str, "SCORE: %d", score);
3508 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3510 sprintf(str, "DISTROS: %d", distros);
3511 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);