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);
154 /* --- GAME LOOP! --- */
158 int done, quit, x, y, i, j;
162 Uint32 last_time, now_time;
168 clearscreen(0, 0, 0);
179 highscore = load_hs();
182 /* --- MAIN GAME LOOP!!! --- */
192 last_time = SDL_GetTicks();
200 while (SDL_PollEvent(&event))
202 if (event.type == SDL_QUIT)
204 /* Quit event - quit: */
208 else if (event.type == SDL_KEYDOWN)
212 key = event.key.keysym.sym;
214 if (key == SDLK_ESCAPE)
216 /* Escape: Quit the game and return to main menu: */
220 else if (key == SDLK_RIGHT)
224 else if (key == SDLK_LEFT)
228 else if (key == SDLK_UP)
232 else if (key == SDLK_DOWN)
236 else if (key == SDLK_LCTRL)
241 else if (event.type == SDL_KEYUP)
245 key = event.key.keysym.sym;
247 if (key == SDLK_RIGHT)
251 else if (key == SDLK_LEFT)
255 else if (key == SDLK_UP)
259 else if (key == SDLK_DOWN)
263 else if (key == SDLK_LCTRL)
267 else if (key == SDLK_TAB)
269 tux_size = !tux_size;
271 else if (key == SDLK_END)
277 else if (event.type == SDL_JOYAXISMOTION)
279 if (event.jaxis.axis == JOY_X)
281 if (event.jaxis.value < -256)
286 if (event.jaxis.value > 256)
291 else if (event.jaxis.axis == JOY_Y)
293 if (event.jaxis.value > 256)
299 else if (event.type == SDL_JOYBUTTONDOWN)
301 if (event.jbutton.button == JOY_A)
303 else if (event.jbutton.button == JOY_B)
306 else if (event.type == SDL_JOYBUTTONUP)
308 if (event.jbutton.button == JOY_A)
310 else if (event.jbutton.button == JOY_B)
317 /* --- HANDLE TUX! --- */
319 /* Handle key and joystick state: */
321 if (!tux_dying && !next_level)
323 if (right == DOWN && left == UP)
327 if (tux_xm < -SKID_XM && !tux_skidding &&
330 tux_skidding = SKID_TIME;
332 playsound(sounds[SND_SKID]);
338 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
346 if (tux_dir == RIGHT)
348 /* Facing the direction we're jumping? Go full-speed: */
352 tux_xm = tux_xm + WALK_SPEED;
354 if (tux_xm > MAX_WALK_XM)
355 tux_xm = MAX_WALK_XM;
357 else if (fire == DOWN)
359 tux_xm = tux_xm + RUN_SPEED;
361 if (tux_xm > MAX_RUN_XM)
367 /* Not facing the direction we're jumping?
370 tux_xm = tux_xm + WALK_SPEED / 2;
372 if (tux_xm > MAX_WALK_XM / 2)
373 tux_xm = MAX_WALK_XM / 2;
377 else if (left == DOWN && right == UP)
381 if (tux_xm > SKID_XM && !tux_skidding &&
384 tux_skidding = SKID_TIME;
385 playsound(sounds[SND_SKID]);
390 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
400 /* Facing the direction we're jumping? Go full-speed: */
404 tux_xm = tux_xm - WALK_SPEED;
406 if (tux_xm < -MAX_WALK_XM)
407 tux_xm = -MAX_WALK_XM;
409 else if (fire == DOWN)
411 tux_xm = tux_xm - RUN_SPEED;
413 if (tux_xm < -MAX_RUN_XM)
414 tux_xm = -MAX_RUN_XM;
419 /* Not facing the direction we're jumping?
422 tux_xm = tux_xm - WALK_SPEED / 2;
424 if (tux_xm < -MAX_WALK_XM / 2)
425 tux_xm = -MAX_WALK_XM / 2;
433 if (tux_x >= endpos && endpos != 0)
435 /* FIXME: No need to kill Tux to end the level! ;^) */
445 if (jump_counter == 0)
449 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
452 /* If they're not on the ground, or are currently moving
453 vertically, don't jump! */
455 jump_counter = MAX_JUMP_COUNT;
459 /* Make sure we're not standing back up into a solid! */
461 if (tux_size == SMALL || tux_duck == NO ||
462 !issolid(tux_x, tux_y, scroll_x))
466 if (tux_size == SMALL)
467 playsound(sounds[SND_JUMP]);
469 playsound(sounds[SND_BIGJUMP]);
475 /* Keep jumping for a while: */
477 if (jump_counter < MAX_JUMP_COUNT)
479 tux_ym = tux_ym - JUMP_SPEED;
489 if (fire == DOWN && old_fire == UP && tux_got_coffee)
491 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
504 if (tux_size == BIG && tux_duck == YES)
506 /* Make sure we're not standing back up into a solid! */
508 if (!issolid(tux_x, tux_y - 32, scroll_x))
514 } /* !tux_dying && !next_level */
517 /* Tux either died, or reached the end of a level! */
519 tux_ym = tux_ym + GRAVITY;
525 if (Mix_PlayingMusic())
531 /* End of a level! */
544 /* No more lives!? */
550 if (score > highscore)
557 /* Either way, (re-)load the (next) level... */
568 tux_x = tux_x + tux_xm;
569 tux_y = tux_y + tux_ym;
572 /* Keep tux in bounds: */
576 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
578 /* Scroll the screen in past center: */
580 scroll_x = scroll_x + (tux_x - 320);
583 if (scroll_x > ((level_width * 32) - 640))
584 scroll_x = ((level_width * 32) - 640);
586 else if (tux_x > 608)
588 /* ... unless there's no more to scroll! */
598 if (issolid(tux_x, tux_y + 31, scroll_x) &&
599 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
601 while (issolid(tux_x, tux_y + 31, scroll_x))
612 if (issolid(tux_x, tux_y, scroll_x) &&
613 !issolid(tux_x - tux_xm, tux_y, scroll_x))
615 while (issolid(tux_x, tux_y, scroll_x))
626 if (issolid(tux_x, tux_y + 31, scroll_x))
628 /* Set down properly: */
630 while (issolid(tux_x, tux_y + 31, scroll_x))
639 /* Reset score multiplier (for mutli-hits): */
642 score_multiplier = 1;
652 /* Bump into things: */
654 if (issolid(tux_x, tux_y, scroll_x) ||
655 (tux_size == BIG && !tux_duck &&
656 (issolid(tux_x, tux_y - 32, scroll_x))))
658 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
659 (tux_size == SMALL || tux_duck ||
660 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
662 tux_x = tux_x - tux_xm;
665 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
666 (tux_size == SMALL || tux_duck ||
667 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
675 /* Break bricks and empty boxes: */
679 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
680 isfullbox(tux_x, tux_y - 32, scroll_x))
682 trygrabdistro(tux_x, tux_y - 64, scroll_x,
684 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
686 if (isfullbox(tux_x, tux_y - 32,
689 bumpbrick(tux_x, tux_y - 32,
693 trybreakbrick(tux_x, tux_y - 32, scroll_x);
694 tryemptybox(tux_x, tux_y - 32, scroll_x);
697 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
698 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
700 trygrabdistro(tux_x + 31,
704 trybumpbadguy(tux_x + 31,
708 if (isfullbox(tux_x + 31, tux_y - 32,
711 bumpbrick(tux_x + 31, tux_y - 32,
715 trybreakbrick(tux_x + 31,
718 tryemptybox(tux_x + 31,
725 if (isbrick(tux_x, tux_y, scroll_x) ||
726 isfullbox(tux_x, tux_y, scroll_x))
728 trygrabdistro(tux_x, tux_y - 32, scroll_x,
730 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
731 if (isfullbox(tux_x, tux_y, scroll_x))
732 bumpbrick(tux_x, tux_y, scroll_x);
733 trybreakbrick(tux_x, tux_y, scroll_x);
734 tryemptybox(tux_x, tux_y, scroll_x);
737 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
738 isfullbox(tux_x + 31, tux_y, scroll_x))
740 trygrabdistro(tux_x + 31,
744 trybumpbadguy(tux_x + 31,
747 if (isfullbox(tux_x + 31, tux_y, scroll_x))
748 bumpbrick(tux_x + 31, tux_y, scroll_x);
749 trybreakbrick(tux_x + 31, tux_y, scroll_x);
750 tryemptybox(tux_x + 31, tux_y, scroll_x);
756 /* It's a brick and we're small, make the brick
757 bounce, and grab any distros above it: */
759 if (isbrick(tux_x, tux_y, scroll_x) ||
760 isfullbox(tux_x, tux_y, scroll_x))
762 trygrabdistro(tux_x, tux_y - 32, scroll_x,
764 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
765 bumpbrick(tux_x, tux_y, scroll_x);
766 tryemptybox(tux_x, tux_y, scroll_x);
769 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
770 isfullbox(tux_x + 31, tux_y, scroll_x))
772 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
774 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
775 bumpbrick(tux_x + 31, tux_y, scroll_x);
776 tryemptybox(tux_x + 31, tux_y, scroll_x);
780 /* Get a distro from a brick? */
782 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
783 shape(tux_x, tux_y, scroll_x) == 'y')
785 add_bouncy_distro(((tux_x + scroll_x + 1)
789 if (counting_distros == NO)
791 counting_distros = YES;
792 distro_counter = 100;
795 if (distro_counter <= 0)
796 change(tux_x, tux_y, scroll_x, 'a');
798 playsound(sounds[SND_DISTRO]);
799 score = score + SCORE_DISTRO;
802 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
803 shape(tux_x + 31, tux_y, scroll_x) == 'y')
805 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
809 if (counting_distros == NO)
811 counting_distros = YES;
812 distro_counter = 100;
815 if (distro_counter <= 0)
816 change(tux_x + 31, tux_y, scroll_x, 'a');
818 playsound(sounds[SND_DISTRO]);
819 score = score + SCORE_DISTRO;
827 tux_y = (tux_y / 32) * 32 + 30;
833 tux_y = (tux_y / 32) * 32 - 32;
838 jump_counter = MAX_JUMP_COUNT;
848 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
849 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
851 if (tux_size == BIG && !tux_duck)
853 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
854 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
859 /* Enough distros for a One-up? */
861 if (distros >= DISTROS_LIFEUP)
863 /* FIXME: Play a special sound or flash or both! */
865 distros = distros - DISTROS_LIFEUP;
867 playsound(sounds[SND_LIFEUP]);
871 /* Keep in-bounds, vertically: */
875 else if (tux_y > 480)
881 /* Slow down horizontally: */
885 if (right == UP && left == UP)
887 if (isice(tux_x, tux_y + 32, scroll_x) ||
888 !issolid(tux_x, tux_y + 32, scroll_x))
890 /* Slowly on ice or in air: */
899 /* Quickly, otherwise: */
906 /* Drop vertically: */
908 if (!issolid(tux_x, tux_y + 32, scroll_x))
910 tux_ym = tux_ym + GRAVITY;
922 /* ---- DONE HANDLING TUX! --- */
925 /* Handle bouncy distros: */
927 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
929 if (bouncy_distros[i].alive)
931 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
933 bouncy_distros[i].ym++;
935 if (bouncy_distros[i].ym >= 0)
936 bouncy_distros[i].alive = NO;
941 /* Handle broken bricks: */
943 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
945 if (broken_bricks[i].alive)
947 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
948 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
950 broken_bricks[i].ym++;
952 if (broken_bricks[i].ym >= 0)
953 broken_bricks[i].alive = NO;
958 /* Handle distro counting: */
960 if (counting_distros == YES)
964 if (distro_counter <= 0)
965 counting_distros = -1;
969 /* Handle bouncy bricks: */
971 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
973 if (bouncy_bricks[i].alive)
975 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
976 bouncy_bricks[i].offset_m);
980 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
981 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
986 if (bouncy_bricks[i].offset == 0)
987 bouncy_bricks[i].alive = NO;
992 /* Handle floating scores: */
994 for (i = 0; i < NUM_FLOATING_SCORES; i++)
996 if (floating_scores[i].alive)
998 floating_scores[i].y = floating_scores[i].y - 2;
999 floating_scores[i].timer--;
1001 if (floating_scores[i].timer <= 0)
1002 floating_scores[i].alive = NO;
1007 /* Handle bullets: */
1009 for (i = 0; i < NUM_BULLETS; i++)
1011 if (bullets[i].alive)
1013 bullets[i].x = bullets[i].x + bullets[i].xm;
1014 bullets[i].y = bullets[i].y + bullets[i].ym;
1016 if (issolid(bullets[i].x, bullets[i].y, 0))
1018 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1019 bullets[i].alive = NO;
1022 if (bullets[i].ym >= 0)
1024 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1026 bullets[i].ym = -bullets[i].ym;
1030 bullets[i].ym = bullets[i].ym + GRAVITY;
1032 if (bullets[i].x < scroll_x ||
1033 bullets[i].x > scroll_x + 640)
1035 bullets[i].alive = NO;
1040 if (bullets[i].alive)
1042 for (j = 0; j < NUM_BAD_GUYS; j++)
1044 if (bad_guys[j].alive && !bad_guys[j].dying)
1046 if (bullets[i].x >= bad_guys[j].x - 4 &&
1047 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1048 bullets[i].y >= bad_guys[j].y - 4 &&
1049 bullets[i].y <= bad_guys[j].y + 32 + 4)
1051 /* Kill the bad guy! */
1053 bullets[i].alive = 0;
1054 bad_guys[j].dying = FALLING;
1055 bad_guys[j].ym = -8;
1058 /* Gain some points: */
1060 if (bad_guys[j].kind == BAD_BSOD)
1062 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1063 50 * score_multiplier);
1065 else if (bad_guys[j].kind == BAD_LAPTOP)
1067 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1068 25 * score_multiplier);
1072 /* Play death sound: */
1073 playsound(sounds[SND_FALL]);
1081 /* Handle background timer: */
1083 if (super_bkgd_time)
1087 /* Handle invincibility timer: */
1089 if (tux_invincible_time)
1090 tux_invincible_time--;
1093 /* Handle upgrades: */
1095 for (i = 0; i < NUM_UPGRADES; i++)
1097 if (upgrades[i].alive)
1099 if (upgrades[i].height < 32)
1103 upgrades[i].height++;
1109 if (upgrades[i].kind == UPGRADE_MINTS ||
1110 upgrades[i].kind == UPGRADE_HERRING)
1112 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1113 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1115 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1116 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1118 if (upgrades[i].ym > 0)
1120 if (upgrades[i].kind == UPGRADE_MINTS)
1124 else if (upgrades[i].kind == UPGRADE_HERRING)
1126 upgrades[i].ym = -24;
1129 upgrades[i].y = (upgrades[i].y / 32) * 32;
1133 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1135 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1137 upgrades[i].xm = -upgrades[i].xm;
1142 /* Off the screen? Kill it! */
1144 if (upgrades[i].x < scroll_x)
1145 upgrades[i].alive = NO;
1148 /* Did the player grab it? */
1150 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1151 tux_x + scroll_x <= upgrades[i].x + 32 &&
1152 tux_y >= upgrades[i].y - 32 &&
1153 tux_y <= upgrades[i].y + 32)
1155 /* Remove the upgrade: */
1157 upgrades[i].alive = NO;
1160 /* Affect the player: */
1162 if (upgrades[i].kind == UPGRADE_MINTS)
1164 playsound(sounds[SND_EXCELLENT]);
1166 super_bkgd_time = 8;
1168 else if (upgrades[i].kind == UPGRADE_COFFEE)
1170 playsound(sounds[SND_COFFEE]);
1171 tux_got_coffee = YES;
1172 super_bkgd_time = 4;
1174 else if (upgrades[i].kind == UPGRADE_HERRING)
1176 playsound(sounds[SND_HERRING]);
1177 tux_invincible_time = 200;
1178 super_bkgd_time = 4;
1186 /* Handle bad guys: */
1188 for (i = 0; i < NUM_BAD_GUYS; i++)
1190 if (bad_guys[i].alive)
1192 if (bad_guys[i].seen)
1194 if (bad_guys[i].kind == BAD_BSOD)
1196 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1198 /* Move left/right: */
1200 if (bad_guys[i].dying == NO ||
1201 bad_guys[i].dying == FALLING)
1203 if (bad_guys[i].dir == RIGHT)
1204 bad_guys[i].x = bad_guys[i].x + 4;
1205 else if (bad_guys[i].dir == LEFT)
1206 bad_guys[i].x = bad_guys[i].x - 4;
1210 /* Move vertically: */
1212 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1215 /* Bump into things horizontally: */
1217 if (!bad_guys[i].dying)
1219 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1220 bad_guys[i].dir = !bad_guys[i].dir;
1224 /* Bump into other bad guys: */
1226 for (j = 0; j < NUM_BAD_GUYS; j++)
1228 if (j != i && bad_guys[j].alive &&
1229 !bad_guys[j].dying && !bad_guys[i].dying &&
1230 bad_guys[i].x >= bad_guys[j].x - 32 &&
1231 bad_guys[i].x <= bad_guys[j].x + 32 &&
1232 bad_guys[i].y >= bad_guys[j].y - 32 &&
1233 bad_guys[i].y <= bad_guys[j].y + 32)
1235 bad_guys[i].dir = !bad_guys[i].dir;
1240 /* Fall if we get off the ground: */
1242 if (bad_guys[i].dying != FALLING)
1244 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1245 bad_guys[i].ym < MAX_YM)
1247 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1253 if (bad_guys[i].ym > 0)
1255 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1261 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1263 if (bad_guys[i].y > 480)
1264 bad_guys[i].alive = NO;
1266 else if (bad_guys[i].kind == BAD_LAPTOP)
1268 /* --- LAPTOP MONSTER: --- */
1270 /* Move left/right: */
1272 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1274 if (bad_guys[i].dying == NO ||
1275 bad_guys[i].dying == FALLING)
1277 if (bad_guys[i].dir == RIGHT)
1278 bad_guys[i].x = bad_guys[i].x + 4;
1279 else if (bad_guys[i].dir == LEFT)
1280 bad_guys[i].x = bad_guys[i].x - 4;
1283 else if (bad_guys[i].mode == KICK)
1285 if (bad_guys[i].dir == RIGHT)
1286 bad_guys[i].x = bad_guys[i].x + 16;
1287 else if (bad_guys[i].dir == LEFT)
1288 bad_guys[i].x = bad_guys[i].x - 16;
1292 /* Move vertically: */
1294 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1297 /* Bump into things horizontally: */
1299 if (!bad_guys[i].dying)
1301 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1303 bad_guys[i].dir = !bad_guys[i].dir;
1305 if (bad_guys[i].mode == KICK)
1306 playsound(sounds[SND_RICOCHET]);
1311 /* Bump into other bad guys: */
1313 for (j = 0; j < NUM_BAD_GUYS; j++)
1315 if (j != i && bad_guys[j].alive &&
1316 !bad_guys[j].dying && !bad_guys[i].dying &&
1317 bad_guys[i].x >= bad_guys[j].x - 32 &&
1318 bad_guys[i].x <= bad_guys[j].x + 32 &&
1319 bad_guys[i].y >= bad_guys[j].y - 32 &&
1320 bad_guys[i].y <= bad_guys[j].y + 32)
1322 if (bad_guys[i].mode != KICK)
1323 bad_guys[i].dir = !bad_guys[i].dir;
1326 /* We're in kick mode, kill the other guy: */
1328 bad_guys[j].dying = FALLING;
1329 bad_guys[j].ym = -8;
1330 playsound(sounds[SND_FALL]);
1332 add_score(bad_guys[i].x - scroll_x,
1333 bad_guys[i].y, 100);
1339 /* Fall if we get off the ground: */
1341 if (bad_guys[i].dying != FALLING)
1343 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1344 bad_guys[i].ym < MAX_YM)
1346 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1352 if (bad_guys[i].ym > 0)
1354 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1360 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1362 if (bad_guys[i].y > 480)
1363 bad_guys[i].alive = NO;
1365 else if (bad_guys[i].kind == BAD_MONEY)
1367 /* --- MONEY BAGS: --- */
1370 /* Move vertically: */
1372 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1375 /* Fall if we get off the ground: */
1377 if (bad_guys[i].dying != FALLING)
1379 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1381 if (bad_guys[i].ym < MAX_YM)
1383 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1390 if (bad_guys[i].ym > 0)
1392 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1393 bad_guys[i].ym = -MAX_YM;
1398 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1400 if (bad_guys[i].y > 480)
1401 bad_guys[i].alive = NO;
1403 else if (bad_guys[i].kind == -1)
1408 /* Kill it if the player jumped on it: */
1410 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1411 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1412 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1413 tux_y >= bad_guys[i].y - 32 &&
1414 tux_y <= bad_guys[i].y - 8
1418 if (bad_guys[i].kind == BAD_BSOD)
1420 bad_guys[i].dying = SQUISHED;
1421 bad_guys[i].timer = 16;
1422 tux_ym = -KILL_BOUNCE_YM;
1424 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1425 50 * score_multiplier);
1427 playsound(sounds[SND_SQUISH]);
1429 else if (bad_guys[i].kind == BAD_LAPTOP)
1431 if (bad_guys[i].mode != FLAT)
1435 bad_guys[i].mode = FLAT;
1437 bad_guys[i].timer = 64;
1445 bad_guys[i].mode = KICK;
1447 if (tux_x + scroll_x <= bad_guys[i].x)
1448 bad_guys[i].dir = RIGHT;
1450 bad_guys[i].dir = LEFT;
1452 bad_guys[i].timer = 8;
1455 tux_ym = -KILL_BOUNCE_YM;
1457 add_score(bad_guys[i].x - scroll_x,
1459 25 * score_multiplier);
1461 /* playsound(sounds[SND_SQUISH]); */
1463 else if (bad_guys[i].kind == -1)
1471 /* Hurt the player if he just touched it: */
1473 if (!bad_guys[i].dying && !tux_dying &&
1475 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1476 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1477 tux_y >= bad_guys[i].y - 32 &&
1478 tux_y <= bad_guys[i].y + 32)
1480 if (bad_guys[i].mode == FLAT)
1484 bad_guys[i].mode = KICK;
1486 if (tux_x < bad_guys[i].x)
1488 bad_guys[i].dir = RIGHT;
1489 bad_guys[i].x = bad_guys[i].x + 16;
1493 bad_guys[i].dir = LEFT;
1494 bad_guys[i].x = bad_guys[i].x - 16;
1497 bad_guys[i].timer = 8;
1499 else if (bad_guys[i].mode == KICK)
1501 if (tux_y < bad_guys[i].y - 16 &&
1502 bad_guys[i].timer == 0)
1504 /* Step on (stop being kicked) */
1506 bad_guys[i].mode = FLAT;
1507 bad_guys[i].timer = 64;
1511 /* Hurt if you get hit by kicked laptop: */
1513 if (bad_guys[i].timer == 0)
1515 if (tux_invincible_time == 0)
1521 bad_guys[i].dying = FALLING;
1522 bad_guys[i].ym = -8;
1523 playsound(sounds[SND_FALL]);
1530 if (tux_invincible_time == 0)
1536 bad_guys[i].dying = FALLING;
1537 bad_guys[i].ym = -8;
1538 playsound(sounds[SND_FALL]);
1544 /* Handle mode timer: */
1546 if (bad_guys[i].mode == FLAT)
1548 bad_guys[i].timer--;
1550 if (bad_guys[i].timer <= 0)
1551 bad_guys[i].mode = NORMAL;
1553 else if (bad_guys[i].mode == KICK)
1555 if (bad_guys[i].timer > 0)
1556 bad_guys[i].timer--;
1560 /* Handle dying timer: */
1562 if (bad_guys[i].dying == SQUISHED)
1564 bad_guys[i].timer--;
1567 /* Remove it if time's up: */
1569 if (bad_guys[i].timer <= 0)
1570 bad_guys[i].alive = NO;
1574 /* Remove if it's far off the screen: */
1576 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1577 bad_guys[i].alive = NO;
1581 /* Once it's on screen, it's activated! */
1583 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1584 bad_guys[i].seen = YES;
1590 /* Handle skidding: */
1592 if (tux_skidding > 0)
1600 if (tux_dying && (frame % 4) == 0)
1601 clearscreen(255, 255, 255);
1604 if (super_bkgd_time == 0)
1605 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1607 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1611 /* Draw background: */
1613 for (y = 0; y < 15; y++)
1615 for (x = 0; x < 21; x++)
1617 drawshape(x * 32 - (scroll_x % 32), y * 32,
1618 tiles[y][x + (scroll_x / 32)]);
1623 /* (Bouncy bricks): */
1625 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1627 if (bouncy_bricks[i].alive)
1629 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1630 bouncy_bricks[i].x <= scroll_x + 640)
1632 dest.x = bouncy_bricks[i].x - scroll_x;
1633 dest.y = bouncy_bricks[i].y;
1637 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1642 drawshape(bouncy_bricks[i].x - scroll_x,
1643 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1644 bouncy_bricks[i].shape);
1652 for (i = 0; i < NUM_BAD_GUYS; i++)
1654 if (bad_guys[i].alive &&
1655 bad_guys[i].x > scroll_x - 32 &&
1656 bad_guys[i].x < scroll_x + 640)
1658 if (bad_guys[i].kind == BAD_BSOD)
1660 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1662 if (bad_guys[i].dying == NO)
1666 if (bad_guys[i].dir == LEFT)
1668 drawimage(img_bsod_left[(frame / 5) % 4],
1669 bad_guys[i].x - scroll_x,
1675 drawimage(img_bsod_right[(frame / 5) % 4],
1676 bad_guys[i].x - scroll_x,
1681 else if (bad_guys[i].dying == FALLING)
1685 if (bad_guys[i].dir == LEFT)
1687 drawimage(img_bsod_falling_left,
1688 bad_guys[i].x - scroll_x,
1694 drawimage(img_bsod_falling_right,
1695 bad_guys[i].x - scroll_x,
1700 else if (bad_guys[i].dying == SQUISHED)
1702 /* Dying - Squished: */
1704 if (bad_guys[i].dir == LEFT)
1706 drawimage(img_bsod_squished_left,
1707 bad_guys[i].x - scroll_x,
1713 drawimage(img_bsod_squished_right,
1714 bad_guys[i].x - scroll_x,
1720 else if (bad_guys[i].kind == BAD_LAPTOP)
1722 /* --- LAPTOP MONSTER: --- */
1724 if (bad_guys[i].dying == NO)
1728 if (bad_guys[i].mode == NORMAL)
1732 if (bad_guys[i].dir == LEFT)
1734 drawimage(img_laptop_left[(frame / 5) % 3],
1735 bad_guys[i].x - scroll_x,
1741 drawimage(img_laptop_right[(frame / 5) % 3],
1742 bad_guys[i].x - scroll_x,
1751 if (bad_guys[i].dir == LEFT)
1753 drawimage(img_laptop_flat_left,
1754 bad_guys[i].x - scroll_x,
1760 drawimage(img_laptop_flat_right,
1761 bad_guys[i].x - scroll_x,
1767 else if (bad_guys[i].dying == FALLING)
1771 if (bad_guys[i].dir == LEFT)
1773 drawimage(img_laptop_falling_left,
1774 bad_guys[i].x - scroll_x,
1780 drawimage(img_laptop_falling_right,
1781 bad_guys[i].x - scroll_x,
1787 else if (bad_guys[i].kind == BAD_MONEY)
1789 if (bad_guys[i].ym > -16)
1791 if (bad_guys[i].dir == LEFT)
1793 drawimage(img_money_left[0],
1794 bad_guys[i].x - scroll_x,
1800 drawimage(img_money_right[0],
1801 bad_guys[i].x - scroll_x,
1808 if (bad_guys[i].dir == LEFT)
1810 drawimage(img_money_left[1],
1811 bad_guys[i].x - scroll_x,
1817 drawimage(img_money_right[1],
1818 bad_guys[i].x - scroll_x,
1824 else if (bad_guys[i].kind == -1)
1833 if (right == UP && left == UP)
1840 if ((fire == DOWN && (frame % 2) == 0) ||
1842 tux_frame_main = (tux_frame_main + 1) % 4;
1844 tux_frame = tux_frame_main;
1851 if (tux_got_coffee && (frame % 2) == 1)
1855 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1859 if (tux_safe == 0 || (frame % 2) == 0)
1861 if (tux_size == SMALL)
1863 if (tux_invincible_time)
1867 if (tux_dir == RIGHT)
1869 drawimage(cape_right[frame % 2],
1875 drawimage(cape_left[frame % 2],
1882 if (tux_dir == RIGHT)
1884 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1888 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1893 if (tux_invincible_time)
1897 if (tux_dir == RIGHT)
1899 drawimage(bigcape_right[frame % 2],
1900 tux_x - 8 - 16, tux_y - 32,
1905 drawimage(bigcape_left[frame % 2],
1906 tux_x - 8, tux_y - 32,
1915 if (!jumping || tux_ym > 0)
1917 if (tux_dir == RIGHT)
1919 drawimage(bigtux_right[tux_frame],
1920 tux_x - 8, tux_y - 32,
1925 drawimage(bigtux_left[tux_frame],
1926 tux_x - 8, tux_y - 32,
1932 if (tux_dir == RIGHT)
1934 drawimage(bigtux_right_jump,
1935 tux_x - 8, tux_y - 32,
1940 drawimage(bigtux_left_jump,
1941 tux_x - 8, tux_y - 32,
1948 if (tux_dir == RIGHT)
1950 drawimage(skidtux_right,
1951 tux_x - 8, tux_y - 32,
1956 drawimage(skidtux_left,
1957 tux_x - 8, tux_y - 32,
1964 if (tux_dir == RIGHT)
1966 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
1971 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
1981 for (i = 0; i < NUM_BULLETS; i++)
1983 if (bullets[i].alive &&
1984 bullets[i].x >= scroll_x - 4 &&
1985 bullets[i].x <= scroll_x + 640)
1987 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
1993 /* (Floating scores): */
1995 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1997 if (floating_scores[i].alive)
1999 sprintf(str, "%d", floating_scores[i].value);
2001 floating_scores[i].x + 16 - strlen(str) * 8,
2002 floating_scores[i].y,
2003 letters_gold, NO_UPDATE);
2010 for (i = 0; i < NUM_UPGRADES; i++)
2012 if (upgrades[i].alive)
2014 if (upgrades[i].height < 32)
2018 dest.x = upgrades[i].x - scroll_x;
2019 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2021 dest.h = upgrades[i].height;
2026 src.h = upgrades[i].height;
2028 if (upgrades[i].kind == UPGRADE_MINTS)
2029 SDL_BlitSurface(img_mints, &src, screen, &dest);
2030 else if (upgrades[i].kind == UPGRADE_COFFEE)
2031 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2032 else if (upgrades[i].kind == UPGRADE_HERRING)
2033 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2037 if (upgrades[i].kind == UPGRADE_MINTS)
2039 drawimage(img_mints,
2040 upgrades[i].x - scroll_x, upgrades[i].y,
2043 else if (upgrades[i].kind == UPGRADE_COFFEE)
2045 drawimage(img_coffee,
2046 upgrades[i].x - scroll_x, upgrades[i].y,
2049 else if (upgrades[i].kind == UPGRADE_HERRING)
2051 drawimage(img_golden_herring,
2052 upgrades[i].x - scroll_x, upgrades[i].y,
2060 /* (Bouncy distros): */
2062 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2064 if (bouncy_distros[i].alive)
2066 drawimage(img_distro[0],
2067 bouncy_distros[i].x - scroll_x,
2068 bouncy_distros[i].y,
2074 /* (Broken bricks): */
2076 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2078 if (broken_bricks[i].alive)
2080 src.x = rand() % 16;
2081 src.y = rand() % 16;
2085 dest.x = broken_bricks[i].x - scroll_x;
2086 dest.y = broken_bricks[i].y;
2090 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2097 sprintf(str, "%d", score);
2098 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2099 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2101 sprintf(str, "%d", highscore);
2102 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2103 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2105 if (time_left >= 50 || (frame % 10) < 5)
2107 sprintf(str, "%d", time_left);
2108 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2109 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2112 sprintf(str, "%d", distros);
2113 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2114 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2117 /* (Update it all!) */
2122 /* Keep playing music: */
2126 if (!Mix_PlayingMusic())
2128 Mix_PlayMusic(song, 1);
2133 /* Pause til next frame: */
2135 now_time = SDL_GetTicks();
2136 if (now_time < last_time + FPS)
2137 SDL_Delay(last_time + FPS - now_time);
2142 if ((frame % 10) == 0 && time_left > 0)
2150 while (!done && !quit);
2154 if (Mix_PlayingMusic())
2166 /* Initialize the game stuff: */
2177 /* Load data for this level: */
2179 void loadlevel(void)
2190 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2191 bouncy_distros[i].alive = NO;
2193 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2194 broken_bricks[i].alive = NO;
2196 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2197 bouncy_bricks[i].alive = NO;
2199 for (i = 0; i < NUM_BAD_GUYS; i++)
2200 bad_guys[i].alive = NO;
2202 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2203 floating_scores[i].alive = NO;
2205 for (i = 0; i < NUM_UPGRADES; i++)
2206 upgrades[i].alive = NO;
2208 for (i = 0; i < NUM_BULLETS; i++)
2209 bullets[i].alive = NO;
2212 /* Load data file: */
2214 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2215 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2216 fi = fopen(filename, "r");
2225 /* Load header info: */
2229 strcpy(levelname, str);
2231 /* (Time to beat level) */
2233 time_left = atoi(str);
2235 /* (Song file for this level) */
2237 strcpy(song_title, str);
2239 /* (Level background color) */
2241 bkgd_red = atoi(str);
2243 bkgd_green= atoi(str);
2245 bkgd_blue = atoi(str);
2249 level_width = atoi(str);
2252 /* Allocate some space for the line-reading! */
2254 line = (char *) malloc(sizeof(char) * (level_width + 5));
2257 fprintf(stderr, "Couldn't allocate space to load level data!");
2262 /* Load the level lines: */
2264 for (y = 0; y < 15; y++)
2266 fgets(line, level_width + 5, fi);
2267 line[strlen(line) - 1] = '\0';
2268 tiles[y] = strdup(line);
2274 /* Activate bad guys: */
2276 for (y = 0; y < 15; y++)
2278 for (x = 0; x < level_width; x++)
2280 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2282 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2297 tux_got_coffee = NO;
2298 tux_invincible_time = 0;
2302 tux_safe = TUX_SAFE_TIME;
2318 score_multiplier = 1;
2319 super_bkgd_time = 0;
2323 counting_distros = NO;
2329 clearscreen(0, 0, 0);
2331 sprintf(str, "LEVEL %d", level);
2332 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2334 sprintf(str, "%s", levelname);
2335 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2337 sprintf(str, "TUX x %d", lives);
2338 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2346 /* Load a level-specific graphic... */
2348 SDL_Surface * load_level_image(char * file, int use_alpha)
2352 snprintf(fname, 1024, "%s/images/level%d/%s", DATA_PREFIX, level, file);
2354 return(load_image(fname, use_alpha));
2358 /* Load graphics: */
2360 void loadlevelgfx(void)
2362 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2363 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2365 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2366 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2367 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2368 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2370 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2371 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2372 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2373 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2375 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2376 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2377 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2378 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2384 void loadlevelsong(void)
2388 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2389 strlen(song_title) + 8));
2391 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2393 song = load_song(DATA_PREFIX "/music/ji_turn.it");
2399 /* Free graphics data for this level: */
2401 void unloadlevelgfx(void)
2405 for (i = 0; i < 2; i++)
2407 SDL_FreeSurface(img_brick[i]);
2409 for (i = 0; i < 4; i++)
2411 SDL_FreeSurface(img_solid[i]);
2412 SDL_FreeSurface(img_bkgd[0][i]);
2413 SDL_FreeSurface(img_bkgd[1][i]);
2418 /* Free music data for this level: */
2420 void unloadlevelsong(void)
2424 Mix_FreeMusic(song);
2429 /* Load graphics shared between all levels: */
2431 void loadshared(void)
2438 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2441 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2444 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2447 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2450 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2453 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2456 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2459 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2462 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2465 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2468 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2471 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2474 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2478 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2480 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2483 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2486 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2490 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2493 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2497 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2501 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2505 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2508 ducktux_right = load_image(DATA_PREFIX
2509 "/images/shared/ducktux-right.png",
2512 ducktux_left = load_image(DATA_PREFIX
2513 "/images/shared/ducktux-left.png",
2516 skidtux_right = load_image(DATA_PREFIX
2517 "/images/shared/skidtux-right.png",
2520 skidtux_left = load_image(DATA_PREFIX
2521 "/images/shared/skidtux-left.png",
2527 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2529 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2536 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2538 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2541 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2544 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2550 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2551 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2557 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2559 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2565 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2568 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2571 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2574 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2578 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2581 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2584 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2587 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2595 img_bsod_left[0] = load_image(DATA_PREFIX
2596 "/images/shared/bsod-left-0.png",
2599 img_bsod_left[1] = load_image(DATA_PREFIX
2600 "/images/shared/bsod-left-1.png",
2603 img_bsod_left[2] = load_image(DATA_PREFIX
2604 "/images/shared/bsod-left-2.png",
2607 img_bsod_left[3] = load_image(DATA_PREFIX
2608 "/images/shared/bsod-left-3.png",
2611 img_bsod_right[0] = load_image(DATA_PREFIX
2612 "/images/shared/bsod-right-0.png",
2615 img_bsod_right[1] = load_image(DATA_PREFIX
2616 "/images/shared/bsod-right-1.png",
2619 img_bsod_right[2] = load_image(DATA_PREFIX
2620 "/images/shared/bsod-right-2.png",
2623 img_bsod_right[3] = load_image(DATA_PREFIX
2624 "/images/shared/bsod-right-3.png",
2627 img_bsod_squished_left = load_image(DATA_PREFIX
2628 "/images/shared/bsod-squished-left.png",
2631 img_bsod_squished_right = load_image(DATA_PREFIX
2632 "/images/shared/bsod-squished-right.png",
2635 img_bsod_falling_left = load_image(DATA_PREFIX
2636 "/images/shared/bsod-falling-left.png",
2639 img_bsod_falling_right = load_image(DATA_PREFIX
2640 "/images/shared/bsod-falling-right.png",
2646 img_laptop_left[0] = load_image(DATA_PREFIX
2647 "/images/shared/laptop-left-0.png",
2650 img_laptop_left[1] = load_image(DATA_PREFIX
2651 "/images/shared/laptop-left-1.png",
2654 img_laptop_left[2] = load_image(DATA_PREFIX
2655 "/images/shared/laptop-left-2.png",
2658 img_laptop_right[0] = load_image(DATA_PREFIX
2659 "/images/shared/laptop-right-0.png",
2662 img_laptop_right[1] = load_image(DATA_PREFIX
2663 "/images/shared/laptop-right-1.png",
2666 img_laptop_right[2] = load_image(DATA_PREFIX
2667 "/images/shared/laptop-right-2.png",
2670 img_laptop_flat_left = load_image(DATA_PREFIX
2671 "/images/shared/laptop-flat-left.png",
2674 img_laptop_flat_right = load_image(DATA_PREFIX
2675 "/images/shared/laptop-flat-right.png",
2678 img_laptop_falling_left =
2679 load_image(DATA_PREFIX
2680 "/images/shared/laptop-falling-left.png",
2683 img_laptop_falling_right =
2684 load_image(DATA_PREFIX
2685 "/images/shared/laptop-falling-right.png",
2691 img_money_left[0] = load_image(DATA_PREFIX
2692 "/images/shared/bag-left-0.png",
2695 img_money_left[1] = load_image(DATA_PREFIX
2696 "/images/shared/bag-left-1.png",
2699 img_money_right[0] = load_image(DATA_PREFIX
2700 "/images/shared/bag-right-0.png",
2703 img_money_right[1] = load_image(DATA_PREFIX
2704 "/images/shared/bag-right-1.png",
2711 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2712 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2717 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2719 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2725 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2728 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2731 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2734 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2740 img_golden_herring =
2741 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2745 /* Super background: */
2747 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2751 /* Sound effects: */
2755 for (i = 0; i < NUM_SOUNDS; i++)
2756 sounds[i] = load_sound(soundfilenames[i]);
2762 /* Free shared data: */
2764 void unloadshared(void)
2768 for (i = 0; i < 3; i++)
2770 SDL_FreeSurface(tux_right[i]);
2771 SDL_FreeSurface(tux_left[i]);
2772 SDL_FreeSurface(bigtux_right[i]);
2773 SDL_FreeSurface(bigtux_left[i]);
2776 SDL_FreeSurface(bigtux_right_jump);
2777 SDL_FreeSurface(bigtux_left_jump);
2779 for (i = 0; i < 2; i++)
2781 SDL_FreeSurface(cape_right[i]);
2782 SDL_FreeSurface(cape_left[i]);
2783 SDL_FreeSurface(bigcape_right[i]);
2784 SDL_FreeSurface(bigcape_left[i]);
2787 SDL_FreeSurface(ducktux_left);
2788 SDL_FreeSurface(ducktux_right);
2790 SDL_FreeSurface(skidtux_left);
2791 SDL_FreeSurface(skidtux_right);
2793 for (i = 0; i < 4; i++)
2795 SDL_FreeSurface(img_bsod_left[i]);
2796 SDL_FreeSurface(img_bsod_right[i]);
2799 SDL_FreeSurface(img_bsod_squished_left);
2800 SDL_FreeSurface(img_bsod_squished_right);
2802 SDL_FreeSurface(img_bsod_falling_left);
2803 SDL_FreeSurface(img_bsod_falling_right);
2805 for (i = 0; i < 3; i++)
2807 SDL_FreeSurface(img_laptop_left[i]);
2808 SDL_FreeSurface(img_laptop_right[i]);
2811 SDL_FreeSurface(img_laptop_flat_left);
2812 SDL_FreeSurface(img_laptop_flat_right);
2814 SDL_FreeSurface(img_laptop_falling_left);
2815 SDL_FreeSurface(img_laptop_falling_right);
2817 for (i = 0; i < 2; i++)
2819 SDL_FreeSurface(img_money_left[i]);
2820 SDL_FreeSurface(img_money_right[i]);
2823 SDL_FreeSurface(img_box_full);
2824 SDL_FreeSurface(img_box_empty);
2826 SDL_FreeSurface(img_water);
2827 for (i = 0; i < 3; i++)
2828 SDL_FreeSurface(img_waves[i]);
2830 SDL_FreeSurface(img_pole);
2831 SDL_FreeSurface(img_poletop);
2833 for (i = 0; i < 2; i++)
2834 SDL_FreeSurface(img_flag[i]);
2836 SDL_FreeSurface(img_mints);
2837 SDL_FreeSurface(img_coffee);
2839 for (i = 0; i < 4; i++)
2841 SDL_FreeSurface(img_distro[i]);
2842 SDL_FreeSurface(img_cloud[0][i]);
2843 SDL_FreeSurface(img_cloud[1][i]);
2846 SDL_FreeSurface(img_golden_herring);
2850 for (i = 0; i < NUM_SOUNDS; i++)
2851 Mix_FreeChunk(sounds[i]);
2856 /* Draw a tile on the screen: */
2858 void drawshape(int x, int y, unsigned char c)
2862 if (c == 'X' || c == 'x')
2863 drawimage(img_brick[0], x, y, NO_UPDATE);
2864 else if (c == 'Y' || c == 'y')
2865 drawimage(img_brick[1], x, y, NO_UPDATE);
2866 else if (c == 'A' || c =='B' || c == '!')
2867 drawimage(img_box_full, x, y, NO_UPDATE);
2869 drawimage(img_box_empty, x, y, NO_UPDATE);
2870 else if (c >= 'C' && c <= 'F')
2871 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
2872 else if (c >= 'c' && c <= 'f')
2873 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
2874 else if (c >= 'G' && c <= 'J')
2875 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
2876 else if (c >= 'g' && c <= 'j')
2877 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
2879 drawimage(img_solid[0], x, y, NO_UPDATE);
2881 drawimage(img_solid[1], x, y, NO_UPDATE);
2883 drawimage(img_solid[2], x, y, NO_UPDATE);
2885 drawimage(img_solid[3], x, y, NO_UPDATE);
2888 z = (frame / 2) % 6;
2891 drawimage(img_distro[z], x, y, NO_UPDATE);
2893 drawimage(img_distro[2], x, y, NO_UPDATE);
2895 drawimage(img_distro[1], x, y, NO_UPDATE);
2899 z = (frame / 3) % 3;
2901 drawimage(img_waves[z], x, y, NO_UPDATE);
2904 drawimage(img_poletop, x, y, NO_UPDATE);
2907 drawimage(img_pole, x, y, NO_UPDATE);
2909 /* Mark this as the end position of the level! */
2915 z = (frame / 3) % 2;
2917 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
2920 drawimage(img_water, x, y, NO_UPDATE);
2924 /* What shape is at some position? */
2926 unsigned char shape(int x, int y, int sx)
2932 xx = ((x + sx) / 32);
2934 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
2945 int issolid(int x, int y, int sx)
2951 if (isbrick(x, y, sx) ||
2952 isbrick(x + 31, y, sx) ||
2954 isice(x + 31, y, sx) ||
2955 (shape(x, y, sx) == '[' ||
2956 shape(x + 31, y, sx) == '[') ||
2957 (shape(x, y, sx) == '=' ||
2958 shape(x + 31, y, sx) == '=') ||
2959 (shape(x, y, sx) == ']' ||
2960 shape(x + 31, y, sx) == ']') ||
2961 (shape(x, y, sx) == 'A' ||
2962 shape(x + 31, y, sx) == 'A') ||
2963 (shape(x, y, sx) == 'B' ||
2964 shape(x + 31, y, sx) == 'B') ||
2965 (shape(x, y, sx) == '!' ||
2966 shape(x + 31, y, sx) == '!') ||
2967 (shape(x, y, sx) == 'a' ||
2968 shape(x + 31, y, sx) == 'a'))
2977 /* Is it a brick? */
2979 int isbrick(int x, int y, int sx)
2985 if (shape(x, y, sx) == 'X' ||
2986 shape(x, y, sx) == 'x' ||
2987 shape(x, y, sx) == 'Y' ||
2988 shape(x, y, sx) == 'y')
2999 int isice(int x, int y, int sx)
3005 if (shape(x, y, sx) == '#')
3014 /* Is it a full box? */
3016 int isfullbox(int x, int y, int sx)
3022 if (shape(x, y, sx) == 'A' ||
3023 shape(x, y, sx) == 'B' ||
3024 shape(x, y, sx) == '!')
3033 /* Edit a piece of the map! */
3035 void change(int x, int y, int sx, unsigned char c)
3040 xx = ((x + sx) / 32);
3042 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3047 /* Break a brick: */
3049 void trybreakbrick(int x, int y, int sx)
3051 if (isbrick(x, y, sx))
3053 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3055 /* Get a distro from it: */
3057 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3060 if (counting_distros == NO)
3062 counting_distros = YES;
3063 distro_counter = 50;
3066 if (distro_counter <= 0)
3067 change(x, y, sx, 'a');
3069 playsound(sounds[SND_DISTRO]);
3070 score = score + SCORE_DISTRO;
3075 /* Get rid of it: */
3077 change(x, y, sx, '.');
3081 /* Replace it with broken bits: */
3083 add_broken_brick(((x + sx + 1) / 32) * 32,
3087 /* Get some score: */
3089 playsound(sounds[SND_BRICK]);
3090 score = score + SCORE_BRICK;
3095 /* Bounce a brick: */
3097 void bumpbrick(int x, int y, int sx)
3099 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3102 playsound(sounds[SND_BRICK]);
3108 void tryemptybox(int x, int y, int sx)
3110 if (isfullbox(x, y, sx))
3112 if (shape(x, y, sx) == 'A')
3114 /* Box with a distro! */
3116 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3117 (y / 32) * 32 - 32);
3119 playsound(sounds[SND_DISTRO]);
3120 score = score + SCORE_DISTRO;
3123 else if (shape(x, y, sx) == 'B')
3125 /* Add an upgrade! */
3127 if (tux_size == SMALL)
3129 /* Tux is small, add mints! */
3131 add_upgrade(((x + sx + 1) / 32) * 32,
3137 /* Tux is big, add coffee: */
3139 add_upgrade(((x + sx + 1) / 32) * 32,
3144 playsound(sounds[SND_UPGRADE]);
3146 else if (shape(x, y, sx) == '!')
3148 /* Add a golden herring */
3150 add_upgrade(((x + sx + 1) / 32) * 32,
3155 /* Empty the box: */
3157 change(x, y, sx, 'a');
3162 /* Try to grab a distro: */
3164 void trygrabdistro(int x, int y, int sx, int bounciness)
3166 if (shape(x, y, sx) == '$')
3168 change(x, y, sx, '.');
3169 playsound(sounds[SND_DISTRO]);
3171 if (bounciness == BOUNCE)
3173 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3177 score = score + SCORE_DISTRO;
3183 /* Add a bouncy distro: */
3185 void add_bouncy_distro(int x, int y)
3191 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3193 if (!bouncy_distros[i].alive)
3199 bouncy_distros[found].alive = YES;
3200 bouncy_distros[found].x = x;
3201 bouncy_distros[found].y = y;
3202 bouncy_distros[found].ym = -6;
3207 /* Add broken brick pieces: */
3209 void add_broken_brick(int x, int y)
3211 add_broken_brick_piece(x, y, -4, -16);
3212 add_broken_brick_piece(x, y + 16, -6, -12);
3214 add_broken_brick_piece(x + 16, y, 4, -16);
3215 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3219 /* Add a broken brick piece: */
3221 void add_broken_brick_piece(int x, int y, int xm, int ym)
3227 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3229 if (!broken_bricks[i].alive)
3235 broken_bricks[found].alive = YES;
3236 broken_bricks[found].x = x;
3237 broken_bricks[found].y = y;
3238 broken_bricks[found].xm = xm;
3239 broken_bricks[found].ym = ym;
3244 /* Add a bouncy brick piece: */
3246 void add_bouncy_brick(int x, int y)
3252 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3254 if (!bouncy_bricks[i].alive)
3260 bouncy_bricks[found].alive = YES;
3261 bouncy_bricks[found].x = x;
3262 bouncy_bricks[found].y = y;
3263 bouncy_bricks[found].offset = 0;
3264 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3265 bouncy_bricks[found].shape = shape(x, y, 0);
3270 /* Add a bad guy: */
3272 void add_bad_guy(int x, int y, int kind)
3278 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3280 if (!bad_guys[i].alive)
3286 bad_guys[found].alive = YES;
3287 bad_guys[found].mode = NORMAL;
3288 bad_guys[found].dying = NO;
3289 bad_guys[found].timer = 0;
3290 bad_guys[found].kind = kind;
3291 bad_guys[found].x = x;
3292 bad_guys[found].y = y;
3293 bad_guys[found].xm = 0;
3294 bad_guys[found].ym = 0;
3295 bad_guys[found].dir = LEFT;
3296 bad_guys[found].seen = NO;
3303 void add_score(int x, int y, int s)
3308 /* Add the score: */
3313 /* Add a floating score thing to the game: */
3317 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3319 if (!floating_scores[i].alive)
3326 floating_scores[found].alive = YES;
3327 floating_scores[found].x = x;
3328 floating_scores[found].y = y - 16;
3329 floating_scores[found].timer = 8;
3330 floating_scores[found].value = s;
3335 /* Try to bump a bad guy from below: */
3337 void trybumpbadguy(int x, int y, int sx)
3344 for (i = 0; i < NUM_BAD_GUYS; i++)
3346 if (bad_guys[i].alive &&
3347 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3348 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3350 if (bad_guys[i].kind == BAD_BSOD ||
3351 bad_guys[i].kind == BAD_LAPTOP)
3353 bad_guys[i].dying = FALLING;
3354 bad_guys[i].ym = -8;
3355 playsound(sounds[SND_FALL]);
3363 for (i = 0; i < NUM_UPGRADES; i++)
3365 if (upgrades[i].alive && upgrades[i].height == 32 &&
3366 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3367 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3369 upgrades[i].xm = -upgrades[i].xm;
3370 upgrades[i].ym = -8;
3371 playsound(sounds[SND_BUMP_UPGRADE]);
3377 /* Add an upgrade: */
3379 void add_upgrade(int x, int y, int kind)
3385 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3387 if (!upgrades[i].alive)
3393 upgrades[found].alive = YES;
3394 upgrades[found].kind = kind;
3395 upgrades[found].x = x;
3396 upgrades[found].y = y;
3397 upgrades[found].xm = 4;
3398 upgrades[found].ym = -4;
3399 upgrades[found].height = 0;
3406 void killtux(int mode)
3410 playsound(sounds[SND_HURT]);
3412 if (tux_dir == RIGHT)
3414 else if (tux_dir == LEFT)
3417 if (mode == SHRINK && tux_size == BIG)
3420 tux_got_coffee = NO;
3424 tux_safe = TUX_SAFE_TIME;
3435 void add_bullet(int x, int y, int dir, int xm)
3441 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3443 if (!bullets[i].alive)
3449 bullets[found].alive = YES;
3453 bullets[found].x = x + 32;
3454 bullets[found].xm = BULLET_XM + xm;
3458 bullets[found].x = x;
3459 bullets[found].xm = -BULLET_XM + xm;
3462 bullets[found].y = y;
3463 bullets[found].ym = BULLET_STARTING_YM;
3465 playsound(sounds[SND_SHOOT]);
3470 void drawendscreen(void)
3474 clearscreen(0, 0, 0);
3476 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3478 sprintf(str, "SCORE: %d", score);
3479 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3481 sprintf(str, "DISTROS: %d", distros);
3482 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);