7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 9, 2003
19 #include <SDL_image.h>
22 #include <SDL_mixer.h>
27 #include <sys/types.h>
37 #include "high_scores.h"
61 char * soundfilenames[NUM_SOUNDS] = {
62 DATA_PREFIX "/sounds/jump.wav",
63 DATA_PREFIX "/sounds/bigjump.wav",
64 DATA_PREFIX "/sounds/skid.wav",
65 DATA_PREFIX "/sounds/distro.wav",
66 DATA_PREFIX "/sounds/herring.wav",
67 DATA_PREFIX "/sounds/brick.wav",
68 DATA_PREFIX "/sounds/hurt.wav",
69 DATA_PREFIX "/sounds/squish.wav",
70 DATA_PREFIX "/sounds/fall.wav",
71 DATA_PREFIX "/sounds/ricochet.wav",
72 DATA_PREFIX "/sounds/bump-upgrade.wav",
73 DATA_PREFIX "/sounds/upgrade.wav",
74 DATA_PREFIX "/sounds/excellent.wav",
75 DATA_PREFIX "/sounds/coffee.wav",
76 DATA_PREFIX "/sounds/shoot.wav"
80 /* Local variables: */
82 int score, highscore, distros, level, lives, scroll_x, next_level,
83 tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
84 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
85 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
86 super_bkgd_time, time_left, tux_invincible_time, endpos,
87 counting_distros, distro_counter;
88 int bkgd_red, bkgd_green, bkgd_blue, level_width;
89 int left, right, up, down, fire, old_fire;
90 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
91 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
92 SDL_Surface * img_bkgd[2][4];
93 SDL_Surface * img_golden_herring;
94 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
95 * img_laptop_left[3], * img_laptop_right[3],
96 * img_money_left[2], * img_money_right[2];
97 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
98 * img_bsod_falling_left, * img_bsod_falling_right,
99 * img_laptop_flat_left, * img_laptop_flat_right,
100 * img_laptop_falling_left, * img_laptop_falling_right;
101 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
102 * img_super_bkgd, * img_bullet, * img_red_glow;
103 SDL_Surface * img_cloud[2][4];
104 SDL_Surface * tux_right[3], * tux_left[3],
105 * bigtux_right[3], * bigtux_left[3],
106 * bigtux_right_jump, * bigtux_left_jump,
107 * cape_right[2], * cape_left[2],
108 * bigcape_right[2], * bigcape_left[2],
109 * ducktux_right, * ducktux_left,
110 * skidtux_right, * skidtux_left;
112 Mix_Chunk * sounds[NUM_SOUNDS];
115 unsigned char * tiles[15];
116 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
117 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
118 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
119 bad_guy_type bad_guys[NUM_BAD_GUYS];
120 floating_score_type floating_scores[NUM_FLOATING_SCORES];
121 upgrade_type upgrades[NUM_UPGRADES];
122 bullet_type bullets[NUM_BULLETS];
127 /* Local function prototypes: */
130 void loadlevel(void);
131 void loadlevelgfx(void);
132 void loadlevelsong(void);
133 void unloadlevelgfx(void);
134 void unloadlevelsong(void);
135 void loadshared(void);
136 void unloadshared(void);
137 void drawshape(int x, int y, unsigned char c);
138 unsigned char shape(int x, int y, int sx);
139 int issolid(int x, int y, int sx);
140 int isbrick(int x, int y, int sx);
141 int isice(int x, int y, int sx);
142 int isfullbox(int x, int y, int sx);
143 void change(int x, int y, int sx, unsigned char c);
144 void trybreakbrick(int x, int y, int sx);
145 void bumpbrick(int x, int y, int sx);
146 void tryemptybox(int x, int y, int sx);
147 void trygrabdistro(int x, int y, int sx, int bounciness);
148 void add_bouncy_distro(int x, int y);
149 void add_broken_brick(int x, int y);
150 void add_broken_brick_piece(int x, int y, int xm, int ym);
151 void add_bouncy_brick(int x, int y);
152 void add_bad_guy(int x, int y, int kind);
153 void add_score(int x, int y, int s);
154 void trybumpbadguy(int x, int y, int sx);
155 void add_upgrade(int x, int y, int kind);
156 void killtux(int mode);
157 void add_bullet(int x, int y, int dir, int xm);
158 void drawendscreen(void);
161 /* --- GAME LOOP! --- */
165 int done, quit, x, y, i, j;
169 Uint32 last_time, now_time;
175 clearscreen(0, 0, 0);
186 highscore = load_hs();
189 /* --- MAIN GAME LOOP!!! --- */
199 last_time = SDL_GetTicks();
207 while (SDL_PollEvent(&event))
209 if (event.type == SDL_QUIT)
211 /* Quit event - quit: */
215 else if (event.type == SDL_KEYDOWN)
219 key = event.key.keysym.sym;
221 if (key == SDLK_ESCAPE)
223 /* Escape: Quit the game and return to main menu: */
227 else if (key == SDLK_RIGHT)
231 else if (key == SDLK_LEFT)
235 else if (key == SDLK_UP)
239 else if (key == SDLK_DOWN)
243 else if (key == SDLK_LCTRL)
248 else if (event.type == SDL_KEYUP)
252 key = event.key.keysym.sym;
254 if (key == SDLK_RIGHT)
258 else if (key == SDLK_LEFT)
262 else if (key == SDLK_UP)
266 else if (key == SDLK_DOWN)
270 else if (key == SDLK_LCTRL)
274 else if (key == SDLK_TAB)
276 tux_size = !tux_size;
280 else if (event.type == SDL_JOYAXISMOTION)
282 if (event.jaxis.axis == JOY_X)
284 if (event.jaxis.value < -256)
289 if (event.jaxis.value > 256)
294 else if (event.jaxis.axis == JOY_Y)
296 if (event.jaxis.value > 256)
302 else if (event.type == SDL_JOYBUTTONDOWN)
304 if (event.jbutton.button == JOY_A)
306 else if (event.jbutton.button == JOY_B)
309 else if (event.type == SDL_JOYBUTTONUP)
311 if (event.jbutton.button == JOY_A)
313 else if (event.jbutton.button == JOY_B)
320 /* --- HANDLE TUX! --- */
322 /* Handle key and joystick state: */
324 if (!tux_dying && !next_level)
326 if (right == DOWN && left == UP)
330 if (tux_xm < -SKID_XM && !tux_skidding &&
333 tux_skidding = SKID_TIME;
335 playsound(sounds[SND_SKID]);
341 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
349 if (tux_dir == RIGHT)
351 /* Facing the direction we're jumping? Go full-speed: */
355 tux_xm = tux_xm + WALK_SPEED;
357 if (tux_xm > MAX_WALK_XM)
358 tux_xm = MAX_WALK_XM;
360 else if (fire == DOWN)
362 tux_xm = tux_xm + RUN_SPEED;
364 if (tux_xm > MAX_RUN_XM)
370 /* Not facing the direction we're jumping?
373 tux_xm = tux_xm + WALK_SPEED / 2;
375 if (tux_xm > MAX_WALK_XM / 2)
376 tux_xm = MAX_WALK_XM / 2;
380 else if (left == DOWN && right == UP)
384 if (tux_xm > SKID_XM && !tux_skidding &&
387 tux_skidding = SKID_TIME;
389 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! ;^) */
450 if (jump_counter == 0)
454 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
457 /* If they're not on the ground, or are currently moving
458 vertically, don't jump! */
460 jump_counter = MAX_JUMP_COUNT;
464 /* Make sure we're not standing back up into a solid! */
466 if (tux_size == SMALL || tux_duck == NO ||
467 !issolid(tux_x, tux_y, scroll_x))
472 if (tux_size == SMALL)
473 playsound(sounds[SND_JUMP]);
475 playsound(sounds[SND_BIGJUMP]);
482 /* Keep jumping for a while: */
484 if (jump_counter < MAX_JUMP_COUNT)
486 tux_ym = tux_ym - JUMP_SPEED;
496 if (fire == DOWN && old_fire == UP && tux_got_coffee)
498 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
511 if (tux_size == BIG && tux_duck == YES)
513 /* Make sure we're not standing back up into a solid! */
515 if (!issolid(tux_x, tux_y - 32, scroll_x))
521 } /* !tux_dying && !next_level */
524 /* Tux either died, or reached the end of a level! */
526 tux_ym = tux_ym + GRAVITY;
533 if (Mix_PlayingMusic())
540 /* End of a level! */
553 /* No more lives!? */
559 if (score > highscore)
566 /* Either way, (re-)load the (next) level... */
577 tux_x = tux_x + tux_xm;
578 tux_y = tux_y + tux_ym;
581 /* Keep tux in bounds: */
585 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
587 /* Scroll the screen in past center: */
589 scroll_x = scroll_x + (tux_x - 320);
592 if (scroll_x > ((level_width * 32) - 640))
593 scroll_x = ((level_width * 32) - 640);
595 else if (tux_x > 608)
597 /* ... unless there's no more to scroll! */
607 if (issolid(tux_x, tux_y + 31, scroll_x) &&
608 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
610 while (issolid(tux_x, tux_y + 31, scroll_x))
621 if (issolid(tux_x, tux_y, scroll_x) &&
622 !issolid(tux_x - tux_xm, tux_y, scroll_x))
624 while (issolid(tux_x, tux_y, scroll_x))
635 if (issolid(tux_x, tux_y + 31, scroll_x))
637 /* Set down properly: */
639 while (issolid(tux_x, tux_y + 31, scroll_x))
648 /* Reset score multiplier (for mutli-hits): */
651 score_multiplier = 1;
661 /* Bump into things: */
663 if (issolid(tux_x, tux_y, scroll_x) ||
664 (tux_size == BIG && !tux_duck &&
665 (issolid(tux_x, tux_y - 32, scroll_x))))
667 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
668 (tux_size == SMALL || tux_duck ||
669 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
671 tux_x = tux_x - tux_xm;
674 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
675 (tux_size == SMALL || tux_duck ||
676 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
684 /* Break bricks and empty boxes: */
688 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
689 isfullbox(tux_x, tux_y - 32, scroll_x))
691 trygrabdistro(tux_x, tux_y - 64, scroll_x,
693 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
695 if (isfullbox(tux_x, tux_y - 32,
698 bumpbrick(tux_x, tux_y - 32,
702 trybreakbrick(tux_x, tux_y - 32, scroll_x);
703 tryemptybox(tux_x, tux_y - 32, scroll_x);
706 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
707 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
709 trygrabdistro(tux_x + 31,
713 trybumpbadguy(tux_x + 31,
717 if (isfullbox(tux_x + 31, tux_y - 32,
720 bumpbrick(tux_x + 31, tux_y - 32,
724 trybreakbrick(tux_x + 31,
727 tryemptybox(tux_x + 31,
734 if (isbrick(tux_x, tux_y, scroll_x) ||
735 isfullbox(tux_x, tux_y, scroll_x))
737 trygrabdistro(tux_x, tux_y - 32, scroll_x,
739 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
740 if (isfullbox(tux_x, tux_y, scroll_x))
741 bumpbrick(tux_x, tux_y, scroll_x);
742 trybreakbrick(tux_x, tux_y, scroll_x);
743 tryemptybox(tux_x, tux_y, scroll_x);
746 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
747 isfullbox(tux_x + 31, tux_y, scroll_x))
749 trygrabdistro(tux_x + 31,
753 trybumpbadguy(tux_x + 31,
756 if (isfullbox(tux_x + 31, tux_y, scroll_x))
757 bumpbrick(tux_x + 31, tux_y, scroll_x);
758 trybreakbrick(tux_x + 31, tux_y, scroll_x);
759 tryemptybox(tux_x + 31, tux_y, scroll_x);
765 /* It's a brick and we're small, make the brick
766 bounce, and grab any distros above it: */
768 if (isbrick(tux_x, tux_y, scroll_x) ||
769 isfullbox(tux_x, tux_y, scroll_x))
771 trygrabdistro(tux_x, tux_y - 32, scroll_x,
773 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
774 bumpbrick(tux_x, tux_y, scroll_x);
775 tryemptybox(tux_x, tux_y, scroll_x);
778 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
779 isfullbox(tux_x + 31, tux_y, scroll_x))
781 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
783 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
784 bumpbrick(tux_x + 31, tux_y, scroll_x);
785 tryemptybox(tux_x + 31, tux_y, scroll_x);
789 /* Get a distro from a brick? */
791 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
792 shape(tux_x, tux_y, scroll_x) == 'y')
794 add_bouncy_distro(((tux_x + scroll_x + 1)
798 if (counting_distros == NO)
800 counting_distros = YES;
801 distro_counter = 100;
804 if (distro_counter <= 0)
805 change(tux_x, tux_y, scroll_x, 'a');
808 playsound(sounds[SND_DISTRO]);
810 score = score + SCORE_DISTRO;
813 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
814 shape(tux_x + 31, tux_y, scroll_x) == 'y')
816 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
820 if (counting_distros == NO)
822 counting_distros = YES;
823 distro_counter = 100;
826 if (distro_counter <= 0)
827 change(tux_x + 31, tux_y, scroll_x, 'a');
830 playsound(sounds[SND_DISTRO]);
832 score = score + SCORE_DISTRO;
840 tux_y = (tux_y / 32) * 32 + 30;
846 tux_y = (tux_y / 32) * 32 - 32;
851 jump_counter = MAX_JUMP_COUNT;
861 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
862 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
864 if (tux_size == BIG && !tux_duck)
866 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
867 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
872 /* Enough distros for a One-up? */
874 if (distros >= DISTROS_LIFEUP)
876 /* FIXME: Play a special sound or flash or both! */
878 distros = distros - DISTROS_LIFEUP;
883 /* Keep in-bounds, vertically: */
887 else if (tux_y > 480)
893 /* Slow down horizontally: */
897 if (right == UP && left == UP)
899 if (isice(tux_x, tux_y + 32, scroll_x) ||
900 !issolid(tux_x, tux_y + 32, scroll_x))
902 /* Slowly on ice or in air: */
911 /* Quickly, otherwise: */
918 /* Drop vertically: */
920 if (!issolid(tux_x, tux_y + 32, scroll_x))
922 tux_ym = tux_ym + GRAVITY;
934 /* ---- DONE HANDLING TUX! --- */
937 /* Handle bouncy distros: */
939 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
941 if (bouncy_distros[i].alive)
943 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
945 bouncy_distros[i].ym++;
947 if (bouncy_distros[i].ym >= 0)
948 bouncy_distros[i].alive = NO;
953 /* Handle broken bricks: */
955 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
957 if (broken_bricks[i].alive)
959 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
960 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
962 broken_bricks[i].ym++;
964 if (broken_bricks[i].ym >= 0)
965 broken_bricks[i].alive = NO;
970 /* Handle distro counting: */
972 if (counting_distros == YES)
976 if (distro_counter <= 0)
977 counting_distros = -1;
981 /* Handle bouncy bricks: */
983 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
985 if (bouncy_bricks[i].alive)
987 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
988 bouncy_bricks[i].offset_m);
992 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
993 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
998 if (bouncy_bricks[i].offset == 0)
999 bouncy_bricks[i].alive = NO;
1004 /* Handle floating scores: */
1006 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1008 if (floating_scores[i].alive)
1010 floating_scores[i].y = floating_scores[i].y - 2;
1011 floating_scores[i].timer--;
1013 if (floating_scores[i].timer <= 0)
1014 floating_scores[i].alive = NO;
1019 /* Handle bullets: */
1021 for (i = 0; i < NUM_BULLETS; i++)
1023 if (bullets[i].alive)
1025 bullets[i].x = bullets[i].x + bullets[i].xm;
1026 bullets[i].y = bullets[i].y + bullets[i].ym;
1028 if (issolid(bullets[i].x, bullets[i].y, 0))
1030 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1031 bullets[i].alive = NO;
1034 if (bullets[i].ym >= 0)
1036 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1038 bullets[i].ym = -bullets[i].ym;
1042 bullets[i].ym = bullets[i].ym + GRAVITY;
1044 if (bullets[i].x < scroll_x ||
1045 bullets[i].x > scroll_x + 640)
1047 bullets[i].alive = NO;
1052 if (bullets[i].alive)
1054 for (j = 0; j < NUM_BAD_GUYS; j++)
1056 if (bad_guys[j].alive && !bad_guys[j].dying)
1058 if (bullets[i].x >= bad_guys[j].x - 4 &&
1059 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1060 bullets[i].y >= bad_guys[j].y - 4 &&
1061 bullets[i].y <= bad_guys[j].y + 32 + 4)
1063 /* Kill the bad guy! */
1065 bullets[i].alive = 0;
1066 bad_guys[j].dying = FALLING;
1067 bad_guys[j].ym = -8;
1070 /* Gain some points: */
1072 if (bad_guys[j].kind == BAD_BSOD)
1074 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1075 50 * score_multiplier);
1077 else if (bad_guys[j].kind == BAD_LAPTOP)
1079 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1080 25 * score_multiplier);
1084 /* Play death sound: */
1086 playsound(sounds[SND_FALL]);
1095 /* Handle background timer: */
1097 if (super_bkgd_time)
1101 /* Handle invincibility timer: */
1103 if (tux_invincible_time)
1104 tux_invincible_time--;
1107 /* Handle upgrades: */
1109 for (i = 0; i < NUM_UPGRADES; i++)
1111 if (upgrades[i].alive)
1113 if (upgrades[i].height < 32)
1117 upgrades[i].height++;
1123 if (upgrades[i].kind == UPGRADE_MINTS ||
1124 upgrades[i].kind == UPGRADE_HERRING)
1126 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1127 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1129 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1130 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1132 if (upgrades[i].ym > 0)
1134 if (upgrades[i].kind == UPGRADE_MINTS)
1138 else if (upgrades[i].kind == UPGRADE_HERRING)
1140 upgrades[i].ym = -24;
1143 upgrades[i].y = (upgrades[i].y / 32) * 32;
1147 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1149 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1151 upgrades[i].xm = -upgrades[i].xm;
1156 /* Off the screen? Kill it! */
1158 if (upgrades[i].x < scroll_x)
1159 upgrades[i].alive = NO;
1162 /* Did the player grab it? */
1164 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1165 tux_x + scroll_x <= upgrades[i].x + 32 &&
1166 tux_y >= upgrades[i].y - 32 &&
1167 tux_y <= upgrades[i].y + 32)
1169 /* Remove the upgrade: */
1171 upgrades[i].alive = NO;
1174 /* Affect the player: */
1176 if (upgrades[i].kind == UPGRADE_MINTS)
1179 playsound(sounds[SND_EXCELLENT]);
1182 super_bkgd_time = 8;
1184 else if (upgrades[i].kind == UPGRADE_COFFEE)
1187 playsound(sounds[SND_COFFEE]);
1189 tux_got_coffee = YES;
1190 super_bkgd_time = 4;
1192 else if (upgrades[i].kind == UPGRADE_HERRING)
1195 playsound(sounds[SND_HERRING]);
1197 tux_invincible_time = 200;
1198 super_bkgd_time = 4;
1206 /* Handle bad guys: */
1208 for (i = 0; i < NUM_BAD_GUYS; i++)
1210 if (bad_guys[i].alive)
1212 if (bad_guys[i].seen)
1214 if (bad_guys[i].kind == BAD_BSOD)
1216 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1218 /* Move left/right: */
1220 if (bad_guys[i].dying == NO ||
1221 bad_guys[i].dying == FALLING)
1223 if (bad_guys[i].dir == RIGHT)
1224 bad_guys[i].x = bad_guys[i].x + 4;
1225 else if (bad_guys[i].dir == LEFT)
1226 bad_guys[i].x = bad_guys[i].x - 4;
1230 /* Move vertically: */
1232 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1235 /* Bump into things horizontally: */
1237 if (!bad_guys[i].dying)
1239 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1240 bad_guys[i].dir = !bad_guys[i].dir;
1244 /* Bump into other bad guys: */
1246 for (j = 0; j < NUM_BAD_GUYS; j++)
1248 if (j != i && bad_guys[j].alive &&
1249 !bad_guys[j].dying && !bad_guys[i].dying &&
1250 bad_guys[i].x >= bad_guys[j].x - 32 &&
1251 bad_guys[i].x <= bad_guys[j].x + 32 &&
1252 bad_guys[i].y >= bad_guys[j].y - 32 &&
1253 bad_guys[i].y <= bad_guys[j].y + 32)
1255 bad_guys[i].dir = !bad_guys[i].dir;
1260 /* Fall if we get off the ground: */
1262 if (bad_guys[i].dying != FALLING)
1264 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1265 bad_guys[i].ym < MAX_YM)
1267 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1273 if (bad_guys[i].ym > 0)
1275 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1281 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1283 if (bad_guys[i].y > 480)
1284 bad_guys[i].alive = NO;
1286 else if (bad_guys[i].kind == BAD_LAPTOP)
1288 /* --- LAPTOP MONSTER: --- */
1290 /* Move left/right: */
1292 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1294 if (bad_guys[i].dying == NO ||
1295 bad_guys[i].dying == FALLING)
1297 if (bad_guys[i].dir == RIGHT)
1298 bad_guys[i].x = bad_guys[i].x + 4;
1299 else if (bad_guys[i].dir == LEFT)
1300 bad_guys[i].x = bad_guys[i].x - 4;
1303 else if (bad_guys[i].mode == KICK)
1305 if (bad_guys[i].dir == RIGHT)
1306 bad_guys[i].x = bad_guys[i].x + 16;
1307 else if (bad_guys[i].dir == LEFT)
1308 bad_guys[i].x = bad_guys[i].x - 16;
1312 /* Move vertically: */
1314 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1317 /* Bump into things horizontally: */
1319 if (!bad_guys[i].dying)
1321 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1323 bad_guys[i].dir = !bad_guys[i].dir;
1326 if (bad_guys[i].mode == KICK)
1327 playsound(sounds[SND_RICOCHET]);
1333 /* Bump into other bad guys: */
1335 for (j = 0; j < NUM_BAD_GUYS; j++)
1337 if (j != i && bad_guys[j].alive &&
1338 !bad_guys[j].dying && !bad_guys[i].dying &&
1339 bad_guys[i].x >= bad_guys[j].x - 32 &&
1340 bad_guys[i].x <= bad_guys[j].x + 32 &&
1341 bad_guys[i].y >= bad_guys[j].y - 32 &&
1342 bad_guys[i].y <= bad_guys[j].y + 32)
1344 if (bad_guys[i].mode != KICK)
1345 bad_guys[i].dir = !bad_guys[i].dir;
1348 /* We're in kick mode, kill the other guy: */
1350 bad_guys[j].dying = FALLING;
1351 bad_guys[j].ym = -8;
1353 playsound(sounds[SND_FALL]);
1356 add_score(bad_guys[i].x - scroll_x,
1357 bad_guys[i].y, 100);
1363 /* Fall if we get off the ground: */
1365 if (bad_guys[i].dying != FALLING)
1367 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1368 bad_guys[i].ym < MAX_YM)
1370 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1376 if (bad_guys[i].ym > 0)
1378 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1384 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1386 if (bad_guys[i].y > 480)
1387 bad_guys[i].alive = NO;
1389 else if (bad_guys[i].kind == BAD_MONEY)
1391 /* --- MONEY BAGS: --- */
1394 /* Move vertically: */
1396 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1399 /* Fall if we get off the ground: */
1401 if (bad_guys[i].dying != FALLING)
1403 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1405 if (bad_guys[i].ym < MAX_YM)
1407 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1414 if (bad_guys[i].ym > 0)
1416 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1417 bad_guys[i].ym = -MAX_YM;
1422 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1424 if (bad_guys[i].y > 480)
1425 bad_guys[i].alive = NO;
1427 else if (bad_guys[i].kind == -1)
1432 /* Kill it if the player jumped on it: */
1434 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1435 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1436 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1437 tux_y >= bad_guys[i].y - 32 &&
1438 tux_y <= bad_guys[i].y - 8
1442 if (bad_guys[i].kind == BAD_BSOD)
1444 bad_guys[i].dying = SQUISHED;
1445 bad_guys[i].timer = 16;
1446 tux_ym = -KILL_BOUNCE_YM;
1448 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1449 50 * score_multiplier);
1452 playsound(sounds[SND_SQUISH]);
1455 else if (bad_guys[i].kind == BAD_LAPTOP)
1457 if (bad_guys[i].mode != FLAT)
1461 bad_guys[i].mode = FLAT;
1463 bad_guys[i].timer = 64;
1471 bad_guys[i].mode = KICK;
1473 if (tux_x + scroll_x <= bad_guys[i].x)
1474 bad_guys[i].dir = RIGHT;
1476 bad_guys[i].dir = LEFT;
1478 bad_guys[i].timer = 8;
1481 tux_ym = -KILL_BOUNCE_YM;
1483 add_score(bad_guys[i].x - scroll_x,
1485 25 * score_multiplier);
1488 /* playsound(sounds[SND_SQUISH]); */
1491 else if (bad_guys[i].kind == -1)
1499 /* Hurt the player if he just touched it: */
1501 if (!bad_guys[i].dying && !tux_dying &&
1503 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1504 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1505 tux_y >= bad_guys[i].y - 32 &&
1506 tux_y <= bad_guys[i].y + 32)
1508 if (bad_guys[i].mode == FLAT)
1512 bad_guys[i].mode = KICK;
1514 if (tux_x < bad_guys[i].x)
1516 bad_guys[i].dir = RIGHT;
1517 bad_guys[i].x = bad_guys[i].x + 16;
1521 bad_guys[i].dir = LEFT;
1522 bad_guys[i].x = bad_guys[i].x - 16;
1525 bad_guys[i].timer = 8;
1527 else if (bad_guys[i].mode == KICK)
1529 if (tux_y < bad_guys[i].y - 16 &&
1530 bad_guys[i].timer == 0)
1532 /* Step on (stop being kicked) */
1534 bad_guys[i].mode = FLAT;
1535 bad_guys[i].timer = 64;
1539 /* Hurt if you get hit by kicked laptop: */
1541 if (bad_guys[i].timer == 0)
1543 if (tux_invincible_time == 0)
1549 bad_guys[i].dying = FALLING;
1550 bad_guys[i].ym = -8;
1552 playsound(sounds[SND_FALL]);
1560 if (tux_invincible_time == 0)
1566 bad_guys[i].dying = FALLING;
1567 bad_guys[i].ym = -8;
1569 playsound(sounds[SND_FALL]);
1576 /* Handle mode timer: */
1578 if (bad_guys[i].mode == FLAT)
1580 bad_guys[i].timer--;
1582 if (bad_guys[i].timer <= 0)
1583 bad_guys[i].mode = NORMAL;
1585 else if (bad_guys[i].mode == KICK)
1587 if (bad_guys[i].timer > 0)
1588 bad_guys[i].timer--;
1592 /* Handle dying timer: */
1594 if (bad_guys[i].dying == SQUISHED)
1596 bad_guys[i].timer--;
1599 /* Remove it if time's up: */
1601 if (bad_guys[i].timer <= 0)
1602 bad_guys[i].alive = NO;
1606 /* Remove if it's far off the screen: */
1608 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1609 bad_guys[i].alive = NO;
1613 /* Once it's on screen, it's activated! */
1615 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1616 bad_guys[i].seen = YES;
1622 /* Handle skidding: */
1624 if (tux_skidding > 0)
1632 if (tux_dying && (frame % 4) == 0)
1633 clearscreen(255, 255, 255);
1636 if (super_bkgd_time == 0)
1637 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1639 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1643 /* Draw background: */
1645 for (y = 0; y < 15; y++)
1647 for (x = 0; x < 21; x++)
1649 drawshape(x * 32 - (scroll_x % 32), y * 32,
1650 tiles[y][x + (scroll_x / 32)]);
1655 /* (Bouncy bricks): */
1657 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1659 if (bouncy_bricks[i].alive)
1661 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1662 bouncy_bricks[i].x <= scroll_x + 640)
1664 dest.x = bouncy_bricks[i].x - scroll_x;
1665 dest.y = bouncy_bricks[i].y;
1669 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1674 drawshape(bouncy_bricks[i].x - scroll_x,
1675 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1676 bouncy_bricks[i].shape);
1684 for (i = 0; i < NUM_BAD_GUYS; i++)
1686 if (bad_guys[i].alive &&
1687 bad_guys[i].x > scroll_x - 32 &&
1688 bad_guys[i].x < scroll_x + 640)
1690 if (bad_guys[i].kind == BAD_BSOD)
1692 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1694 if (bad_guys[i].dying == NO)
1698 if (bad_guys[i].dir == LEFT)
1700 drawimage(img_bsod_left[(frame / 5) % 4],
1701 bad_guys[i].x - scroll_x,
1707 drawimage(img_bsod_right[(frame / 5) % 4],
1708 bad_guys[i].x - scroll_x,
1713 else if (bad_guys[i].dying == FALLING)
1717 if (bad_guys[i].dir == LEFT)
1719 drawimage(img_bsod_falling_left,
1720 bad_guys[i].x - scroll_x,
1726 drawimage(img_bsod_falling_right,
1727 bad_guys[i].x - scroll_x,
1732 else if (bad_guys[i].dying == SQUISHED)
1734 /* Dying - Squished: */
1736 if (bad_guys[i].dir == LEFT)
1738 drawimage(img_bsod_squished_left,
1739 bad_guys[i].x - scroll_x,
1745 drawimage(img_bsod_squished_right,
1746 bad_guys[i].x - scroll_x,
1752 else if (bad_guys[i].kind == BAD_LAPTOP)
1754 /* --- LAPTOP MONSTER: --- */
1756 if (bad_guys[i].dying == NO)
1760 if (bad_guys[i].mode == NORMAL)
1764 if (bad_guys[i].dir == LEFT)
1766 drawimage(img_laptop_left[(frame / 5) % 3],
1767 bad_guys[i].x - scroll_x,
1773 drawimage(img_laptop_right[(frame / 5) % 3],
1774 bad_guys[i].x - scroll_x,
1783 if (bad_guys[i].dir == LEFT)
1785 drawimage(img_laptop_flat_left,
1786 bad_guys[i].x - scroll_x,
1792 drawimage(img_laptop_flat_right,
1793 bad_guys[i].x - scroll_x,
1799 else if (bad_guys[i].dying == FALLING)
1803 if (bad_guys[i].dir == LEFT)
1805 drawimage(img_laptop_falling_left,
1806 bad_guys[i].x - scroll_x,
1812 drawimage(img_laptop_falling_right,
1813 bad_guys[i].x - scroll_x,
1819 else if (bad_guys[i].kind == BAD_MONEY)
1821 if (bad_guys[i].ym > -16)
1823 if (bad_guys[i].dir == LEFT)
1825 drawimage(img_money_left[0],
1826 bad_guys[i].x - scroll_x,
1832 drawimage(img_money_right[0],
1833 bad_guys[i].x - scroll_x,
1840 if (bad_guys[i].dir == LEFT)
1842 drawimage(img_money_left[1],
1843 bad_guys[i].x - scroll_x,
1849 drawimage(img_money_right[1],
1850 bad_guys[i].x - scroll_x,
1856 else if (bad_guys[i].kind == -1)
1865 if (right == UP && left == UP)
1872 if ((fire == DOWN && (frame % 2) == 0) ||
1874 tux_frame_main = (tux_frame_main + 1) % 4;
1876 tux_frame = tux_frame_main;
1883 if (tux_got_coffee && (frame % 2) == 1)
1887 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1891 if (tux_safe == 0 || (frame % 2) == 0)
1893 if (tux_size == SMALL)
1895 if (tux_invincible_time)
1899 if (tux_dir == RIGHT)
1901 drawimage(cape_right[frame % 2],
1907 drawimage(cape_left[frame % 2],
1914 if (tux_dir == RIGHT)
1916 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1920 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1925 if (tux_invincible_time)
1929 if (tux_dir == RIGHT)
1931 drawimage(bigcape_right[frame % 2],
1932 tux_x - 8 - 16, tux_y - 32,
1937 drawimage(bigcape_left[frame % 2],
1938 tux_x - 8, tux_y - 32,
1947 if (!jumping || tux_ym > 0)
1949 if (tux_dir == RIGHT)
1951 drawimage(bigtux_right[tux_frame],
1952 tux_x - 8, tux_y - 32,
1957 drawimage(bigtux_left[tux_frame],
1958 tux_x - 8, tux_y - 32,
1964 if (tux_dir == RIGHT)
1966 drawimage(bigtux_right_jump,
1967 tux_x - 8, tux_y - 32,
1972 drawimage(bigtux_left_jump,
1973 tux_x - 8, tux_y - 32,
1980 if (tux_dir == RIGHT)
1982 drawimage(skidtux_right,
1983 tux_x - 8, tux_y - 32,
1988 drawimage(skidtux_left,
1989 tux_x - 8, tux_y - 32,
1996 if (tux_dir == RIGHT)
1998 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2003 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2013 for (i = 0; i < NUM_BULLETS; i++)
2015 if (bullets[i].alive &&
2016 bullets[i].x >= scroll_x - 4 &&
2017 bullets[i].x <= scroll_x + 640)
2019 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2025 /* (Floating scores): */
2027 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2029 if (floating_scores[i].alive)
2031 sprintf(str, "%d", floating_scores[i].value);
2033 floating_scores[i].x + 16 - strlen(str) * 8,
2034 floating_scores[i].y,
2035 letters_gold, NO_UPDATE);
2042 for (i = 0; i < NUM_UPGRADES; i++)
2044 if (upgrades[i].alive)
2046 if (upgrades[i].height < 32)
2050 dest.x = upgrades[i].x - scroll_x;
2051 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2053 dest.h = upgrades[i].height;
2058 src.h = upgrades[i].height;
2060 if (upgrades[i].kind == UPGRADE_MINTS)
2061 SDL_BlitSurface(img_mints, &src, screen, &dest);
2062 else if (upgrades[i].kind == UPGRADE_COFFEE)
2063 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2064 else if (upgrades[i].kind == UPGRADE_HERRING)
2065 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2069 if (upgrades[i].kind == UPGRADE_MINTS)
2071 drawimage(img_mints,
2072 upgrades[i].x - scroll_x, upgrades[i].y,
2075 else if (upgrades[i].kind == UPGRADE_COFFEE)
2077 drawimage(img_coffee,
2078 upgrades[i].x - scroll_x, upgrades[i].y,
2081 else if (upgrades[i].kind == UPGRADE_HERRING)
2083 drawimage(img_golden_herring,
2084 upgrades[i].x - scroll_x, upgrades[i].y,
2092 /* (Bouncy distros): */
2094 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2096 if (bouncy_distros[i].alive)
2098 drawimage(img_distro[0],
2099 bouncy_distros[i].x - scroll_x,
2100 bouncy_distros[i].y,
2106 /* (Broken bricks): */
2108 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2110 if (broken_bricks[i].alive)
2112 src.x = rand() % 16;
2113 src.y = rand() % 16;
2117 dest.x = broken_bricks[i].x - scroll_x;
2118 dest.y = broken_bricks[i].y;
2122 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2129 sprintf(str, "%d", score);
2130 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2131 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2133 sprintf(str, "%d", highscore);
2134 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2135 drawtext(str, 80, 20, letters_gold, NO_UPDATE);
2137 if (time_left >= 50 || (frame % 10) < 5)
2139 sprintf(str, "%d", time_left);
2140 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2141 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2144 sprintf(str, "%d", distros);
2145 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2146 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2149 /* (Update it all!) */
2154 /* Keep playing music: */
2159 if (!Mix_PlayingMusic())
2161 Mix_PlayMusic(song, 1);
2167 /* Pause til next frame: */
2169 now_time = SDL_GetTicks();
2170 if (now_time < last_time + FPS)
2171 SDL_Delay(last_time + FPS - now_time);
2176 if ((frame % 10) == 0 && time_left > 0)
2184 while (!done && !quit);
2189 if (Mix_PlayingMusic())
2202 /* Initialize the game stuff: */
2213 /* Load data for this level: */
2215 void loadlevel(void)
2226 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2227 bouncy_distros[i].alive = NO;
2229 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2230 broken_bricks[i].alive = NO;
2232 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2233 bouncy_bricks[i].alive = NO;
2235 for (i = 0; i < NUM_BAD_GUYS; i++)
2236 bad_guys[i].alive = NO;
2238 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2239 floating_scores[i].alive = NO;
2241 for (i = 0; i < NUM_UPGRADES; i++)
2242 upgrades[i].alive = NO;
2244 for (i = 0; i < NUM_BULLETS; i++)
2245 bullets[i].alive = NO;
2248 /* Load data file: */
2250 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2251 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2252 fi = fopen(filename, "r");
2261 /* Load header info: */
2265 strcpy(levelname, str);
2267 /* (Time to beat level) */
2269 time_left = atoi(str);
2271 /* (Song file for this level) */
2273 strcpy(song_title, str);
2275 /* (Level background color) */
2277 bkgd_red = atoi(str);
2279 bkgd_green= atoi(str);
2281 bkgd_blue = atoi(str);
2285 level_width = atoi(str);
2288 /* Allocate some space for the line-reading! */
2290 line = (char *) malloc(sizeof(char) * (level_width + 5));
2293 fprintf(stderr, "Couldn't allocate space to load level data!");
2298 /* Load the level lines: */
2300 for (y = 0; y < 15; y++)
2302 fgets(line, level_width + 5, fi);
2303 line[strlen(line) - 1] = '\0';
2304 tiles[y] = strdup(line);
2310 /* Activate bad guys: */
2312 for (y = 0; y < 15; y++)
2314 for (x = 0; x < level_width; x++)
2316 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2318 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2333 tux_got_coffee = NO;
2334 tux_invincible_time = 0;
2338 tux_safe = TUX_SAFE_TIME;
2354 score_multiplier = 1;
2355 super_bkgd_time = 0;
2359 counting_distros = NO;
2365 clearscreen(0, 0, 0);
2367 sprintf(str, "LEVEL %d", level);
2368 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2370 sprintf(str, "%s", levelname);
2371 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2373 sprintf(str, "TUX x %d", lives);
2374 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2382 /* Load a level-specific graphic... */
2384 SDL_Surface * load_level_image(char * file, int use_alpha)
2388 snprintf(fname, 1024, "%s/images/level%d/%s", DATA_PREFIX, level, file);
2390 return(load_image(fname, use_alpha));
2394 /* Load graphics: */
2396 void loadlevelgfx(void)
2398 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2399 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2401 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2402 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2403 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2404 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2406 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2407 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2408 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2409 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2411 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2412 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2413 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2414 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2420 void loadlevelsong(void)
2425 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2426 strlen(song_title) + 8));
2428 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2430 song = load_song(DATA_PREFIX "/music/ji_turn.it");
2437 /* Free graphics data for this level: */
2439 void unloadlevelgfx(void)
2443 for (i = 0; i < 2; i++)
2445 SDL_FreeSurface(img_brick[i]);
2447 for (i = 0; i < 4; i++)
2449 SDL_FreeSurface(img_solid[i]);
2450 SDL_FreeSurface(img_bkgd[0][i]);
2451 SDL_FreeSurface(img_bkgd[1][i]);
2456 /* Free music data for this level: */
2458 void unloadlevelsong(void)
2463 Mix_FreeMusic(song);
2469 /* Load graphics shared between all levels: */
2471 void loadshared(void)
2480 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2483 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2486 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2489 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2492 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2495 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2498 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2501 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2504 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2507 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2510 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2513 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2516 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2520 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2522 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2525 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2528 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2532 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2535 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2539 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2543 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2547 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2550 ducktux_right = load_image(DATA_PREFIX
2551 "/images/shared/ducktux-right.png",
2554 ducktux_left = load_image(DATA_PREFIX
2555 "/images/shared/ducktux-left.png",
2558 skidtux_right = load_image(DATA_PREFIX
2559 "/images/shared/skidtux-right.png",
2562 skidtux_left = load_image(DATA_PREFIX
2563 "/images/shared/skidtux-left.png",
2569 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2571 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2578 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2580 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2583 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2586 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2592 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2593 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2599 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2601 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2607 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2610 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2613 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2616 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2620 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2623 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2626 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2629 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2637 img_bsod_left[0] = load_image(DATA_PREFIX
2638 "/images/shared/bsod-left-0.png",
2641 img_bsod_left[1] = load_image(DATA_PREFIX
2642 "/images/shared/bsod-left-1.png",
2645 img_bsod_left[2] = load_image(DATA_PREFIX
2646 "/images/shared/bsod-left-2.png",
2649 img_bsod_left[3] = load_image(DATA_PREFIX
2650 "/images/shared/bsod-left-3.png",
2653 img_bsod_right[0] = load_image(DATA_PREFIX
2654 "/images/shared/bsod-right-0.png",
2657 img_bsod_right[1] = load_image(DATA_PREFIX
2658 "/images/shared/bsod-right-1.png",
2661 img_bsod_right[2] = load_image(DATA_PREFIX
2662 "/images/shared/bsod-right-2.png",
2665 img_bsod_right[3] = load_image(DATA_PREFIX
2666 "/images/shared/bsod-right-3.png",
2669 img_bsod_squished_left = load_image(DATA_PREFIX
2670 "/images/shared/bsod-squished-left.png",
2673 img_bsod_squished_right = load_image(DATA_PREFIX
2674 "/images/shared/bsod-squished-right.png",
2677 img_bsod_falling_left = load_image(DATA_PREFIX
2678 "/images/shared/bsod-falling-left.png",
2681 img_bsod_falling_right = load_image(DATA_PREFIX
2682 "/images/shared/bsod-falling-right.png",
2688 img_laptop_left[0] = load_image(DATA_PREFIX
2689 "/images/shared/laptop-left-0.png",
2692 img_laptop_left[1] = load_image(DATA_PREFIX
2693 "/images/shared/laptop-left-1.png",
2696 img_laptop_left[2] = load_image(DATA_PREFIX
2697 "/images/shared/laptop-left-2.png",
2700 img_laptop_right[0] = load_image(DATA_PREFIX
2701 "/images/shared/laptop-right-0.png",
2704 img_laptop_right[1] = load_image(DATA_PREFIX
2705 "/images/shared/laptop-right-1.png",
2708 img_laptop_right[2] = load_image(DATA_PREFIX
2709 "/images/shared/laptop-right-2.png",
2712 img_laptop_flat_left = load_image(DATA_PREFIX
2713 "/images/shared/laptop-flat-left.png",
2716 img_laptop_flat_right = load_image(DATA_PREFIX
2717 "/images/shared/laptop-flat-right.png",
2720 img_laptop_falling_left =
2721 load_image(DATA_PREFIX
2722 "/images/shared/laptop-falling-left.png",
2725 img_laptop_falling_right =
2726 load_image(DATA_PREFIX
2727 "/images/shared/laptop-falling-right.png",
2733 img_money_left[0] = load_image(DATA_PREFIX
2734 "/images/shared/bag-left-0.png",
2737 img_money_left[1] = load_image(DATA_PREFIX
2738 "/images/shared/bag-left-1.png",
2741 img_money_right[0] = load_image(DATA_PREFIX
2742 "/images/shared/bag-right-0.png",
2745 img_money_right[1] = load_image(DATA_PREFIX
2746 "/images/shared/bag-right-1.png",
2753 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2754 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2759 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2761 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2767 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2770 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2773 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2776 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2782 img_golden_herring =
2783 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2787 /* Super background: */
2789 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2793 /* Sound effects: */
2798 for (i = 0; i < NUM_SOUNDS; i++)
2799 sounds[i] = load_sound(soundfilenames[i]);
2805 /* Free shared data: */
2807 void unloadshared(void)
2811 for (i = 0; i < 3; i++)
2813 SDL_FreeSurface(tux_right[i]);
2814 SDL_FreeSurface(tux_left[i]);
2815 SDL_FreeSurface(bigtux_right[i]);
2816 SDL_FreeSurface(bigtux_left[i]);
2819 SDL_FreeSurface(bigtux_right_jump);
2820 SDL_FreeSurface(bigtux_left_jump);
2822 for (i = 0; i < 2; i++)
2824 SDL_FreeSurface(cape_right[i]);
2825 SDL_FreeSurface(cape_left[i]);
2826 SDL_FreeSurface(bigcape_right[i]);
2827 SDL_FreeSurface(bigcape_left[i]);
2830 SDL_FreeSurface(ducktux_left);
2831 SDL_FreeSurface(ducktux_right);
2833 SDL_FreeSurface(skidtux_left);
2834 SDL_FreeSurface(skidtux_right);
2836 for (i = 0; i < 4; i++)
2838 SDL_FreeSurface(img_bsod_left[i]);
2839 SDL_FreeSurface(img_bsod_right[i]);
2842 SDL_FreeSurface(img_bsod_squished_left);
2843 SDL_FreeSurface(img_bsod_squished_right);
2845 SDL_FreeSurface(img_bsod_falling_left);
2846 SDL_FreeSurface(img_bsod_falling_right);
2848 for (i = 0; i < 3; i++)
2850 SDL_FreeSurface(img_laptop_left[i]);
2851 SDL_FreeSurface(img_laptop_right[i]);
2854 SDL_FreeSurface(img_laptop_flat_left);
2855 SDL_FreeSurface(img_laptop_flat_right);
2857 SDL_FreeSurface(img_laptop_falling_left);
2858 SDL_FreeSurface(img_laptop_falling_right);
2860 for (i = 0; i < 2; i++)
2862 SDL_FreeSurface(img_money_left[i]);
2863 SDL_FreeSurface(img_money_right[i]);
2866 SDL_FreeSurface(img_box_full);
2867 SDL_FreeSurface(img_box_empty);
2869 SDL_FreeSurface(img_water);
2870 for (i = 0; i < 3; i++)
2871 SDL_FreeSurface(img_waves[i]);
2873 SDL_FreeSurface(img_pole);
2874 SDL_FreeSurface(img_poletop);
2876 for (i = 0; i < 2; i++)
2877 SDL_FreeSurface(img_flag[i]);
2879 SDL_FreeSurface(img_mints);
2880 SDL_FreeSurface(img_coffee);
2882 for (i = 0; i < 4; i++)
2884 SDL_FreeSurface(img_distro[i]);
2885 SDL_FreeSurface(img_cloud[0][i]);
2886 SDL_FreeSurface(img_cloud[1][i]);
2889 SDL_FreeSurface(img_golden_herring);
2894 for (i = 0; i < NUM_SOUNDS; i++)
2895 Mix_FreeChunk(sounds[i]);
2901 /* Draw a tile on the screen: */
2903 void drawshape(int x, int y, unsigned char c)
2907 if (c == 'X' || c == 'x')
2908 drawimage(img_brick[0], x, y, NO_UPDATE);
2909 else if (c == 'Y' || c == 'y')
2910 drawimage(img_brick[1], x, y, NO_UPDATE);
2911 else if (c == 'A' || c =='B' || c == '!')
2912 drawimage(img_box_full, x, y, NO_UPDATE);
2914 drawimage(img_box_empty, x, y, NO_UPDATE);
2915 else if (c >= 'C' && c <= 'F')
2916 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
2917 else if (c >= 'c' && c <= 'f')
2918 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
2919 else if (c >= 'G' && c <= 'J')
2920 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
2921 else if (c >= 'g' && c <= 'j')
2922 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
2924 drawimage(img_solid[0], x, y, NO_UPDATE);
2926 drawimage(img_solid[1], x, y, NO_UPDATE);
2928 drawimage(img_solid[2], x, y, NO_UPDATE);
2930 drawimage(img_solid[3], x, y, NO_UPDATE);
2933 z = (frame / 2) % 6;
2936 drawimage(img_distro[z], x, y, NO_UPDATE);
2938 drawimage(img_distro[2], x, y, NO_UPDATE);
2940 drawimage(img_distro[1], x, y, NO_UPDATE);
2944 z = (frame / 3) % 3;
2946 drawimage(img_waves[z], x, y, NO_UPDATE);
2949 drawimage(img_poletop, x, y, NO_UPDATE);
2952 drawimage(img_pole, x, y, NO_UPDATE);
2954 /* Mark this as the end position of the level! */
2960 z = (frame / 3) % 2;
2962 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
2965 drawimage(img_water, x, y, NO_UPDATE);
2969 /* What shape is at some position? */
2971 unsigned char shape(int x, int y, int sx)
2977 xx = ((x + sx) / 32);
2979 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
2990 int issolid(int x, int y, int sx)
2996 if (isbrick(x, y, sx) ||
2997 isbrick(x + 31, y, sx) ||
2999 isice(x + 31, y, sx) ||
3000 (shape(x, y, sx) == '[' ||
3001 shape(x + 31, y, sx) == '[') ||
3002 (shape(x, y, sx) == '=' ||
3003 shape(x + 31, y, sx) == '=') ||
3004 (shape(x, y, sx) == ']' ||
3005 shape(x + 31, y, sx) == ']') ||
3006 (shape(x, y, sx) == 'A' ||
3007 shape(x + 31, y, sx) == 'A') ||
3008 (shape(x, y, sx) == 'B' ||
3009 shape(x + 31, y, sx) == 'B') ||
3010 (shape(x, y, sx) == '!' ||
3011 shape(x + 31, y, sx) == '!') ||
3012 (shape(x, y, sx) == 'a' ||
3013 shape(x + 31, y, sx) == 'a'))
3022 /* Is it a brick? */
3024 int isbrick(int x, int y, int sx)
3030 if (shape(x, y, sx) == 'X' ||
3031 shape(x, y, sx) == 'x' ||
3032 shape(x, y, sx) == 'Y' ||
3033 shape(x, y, sx) == 'y')
3044 int isice(int x, int y, int sx)
3050 if (shape(x, y, sx) == '#')
3059 /* Is it a full box? */
3061 int isfullbox(int x, int y, int sx)
3067 if (shape(x, y, sx) == 'A' ||
3068 shape(x, y, sx) == 'B' ||
3069 shape(x, y, sx) == '!')
3078 /* Edit a piece of the map! */
3080 void change(int x, int y, int sx, unsigned char c)
3085 xx = ((x + sx) / 32);
3087 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3092 /* Break a brick: */
3094 void trybreakbrick(int x, int y, int sx)
3096 if (isbrick(x, y, sx))
3098 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3100 /* Get a distro from it: */
3102 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3105 if (counting_distros == NO)
3107 counting_distros = YES;
3108 distro_counter = 50;
3111 if (distro_counter <= 0)
3112 change(x, y, sx, 'a');
3115 playsound(sounds[SND_DISTRO]);
3117 score = score + SCORE_DISTRO;
3122 /* Get rid of it: */
3124 change(x, y, sx, '.');
3128 /* Replace it with broken bits: */
3130 add_broken_brick(((x + sx + 1) / 32) * 32,
3134 /* Get some score: */
3137 playsound(sounds[SND_BRICK]);
3139 score = score + SCORE_BRICK;
3144 /* Bounce a brick: */
3146 void bumpbrick(int x, int y, int sx)
3148 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3152 playsound(sounds[SND_BRICK]);
3159 void tryemptybox(int x, int y, int sx)
3161 if (isfullbox(x, y, sx))
3163 if (shape(x, y, sx) == 'A')
3165 /* Box with a distro! */
3167 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3168 (y / 32) * 32 - 32);
3171 playsound(sounds[SND_DISTRO]);
3173 score = score + SCORE_DISTRO;
3176 else if (shape(x, y, sx) == 'B')
3178 /* Add an upgrade! */
3180 if (tux_size == SMALL)
3182 /* Tux is small, add mints! */
3184 add_upgrade(((x + sx + 1) / 32) * 32,
3190 /* Tux is big, add coffee: */
3192 add_upgrade(((x + sx + 1) / 32) * 32,
3198 playsound(sounds[SND_UPGRADE]);
3201 else if (shape(x, y, sx) == '!')
3203 /* Add a golden herring */
3205 add_upgrade(((x + sx + 1) / 32) * 32,
3210 /* Empty the box: */
3212 change(x, y, sx, 'a');
3217 /* Try to grab a distro: */
3219 void trygrabdistro(int x, int y, int sx, int bounciness)
3221 if (shape(x, y, sx) == '$')
3223 change(x, y, sx, '.');
3225 playsound(sounds[SND_DISTRO]);
3228 if (bounciness == BOUNCE)
3230 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3234 score = score + SCORE_DISTRO;
3240 /* Add a bouncy distro: */
3242 void add_bouncy_distro(int x, int y)
3248 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3250 if (!bouncy_distros[i].alive)
3256 bouncy_distros[found].alive = YES;
3257 bouncy_distros[found].x = x;
3258 bouncy_distros[found].y = y;
3259 bouncy_distros[found].ym = -6;
3264 /* Add broken brick pieces: */
3266 void add_broken_brick(int x, int y)
3268 add_broken_brick_piece(x, y, -4, -16);
3269 add_broken_brick_piece(x, y + 16, -6, -12);
3271 add_broken_brick_piece(x + 16, y, 4, -16);
3272 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3276 /* Add a broken brick piece: */
3278 void add_broken_brick_piece(int x, int y, int xm, int ym)
3284 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3286 if (!broken_bricks[i].alive)
3292 broken_bricks[found].alive = YES;
3293 broken_bricks[found].x = x;
3294 broken_bricks[found].y = y;
3295 broken_bricks[found].xm = xm;
3296 broken_bricks[found].ym = ym;
3301 /* Add a bouncy brick piece: */
3303 void add_bouncy_brick(int x, int y)
3309 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3311 if (!bouncy_bricks[i].alive)
3317 bouncy_bricks[found].alive = YES;
3318 bouncy_bricks[found].x = x;
3319 bouncy_bricks[found].y = y;
3320 bouncy_bricks[found].offset = 0;
3321 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3322 bouncy_bricks[found].shape = shape(x, y, 0);
3327 /* Add a bad guy: */
3329 void add_bad_guy(int x, int y, int kind)
3335 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3337 if (!bad_guys[i].alive)
3343 bad_guys[found].alive = YES;
3344 bad_guys[found].mode = NORMAL;
3345 bad_guys[found].dying = NO;
3346 bad_guys[found].timer = 0;
3347 bad_guys[found].kind = kind;
3348 bad_guys[found].x = x;
3349 bad_guys[found].y = y;
3350 bad_guys[found].xm = 0;
3351 bad_guys[found].ym = 0;
3352 bad_guys[found].dir = LEFT;
3353 bad_guys[found].seen = NO;
3360 void add_score(int x, int y, int s)
3365 /* Add the score: */
3370 /* Add a floating score thing to the game: */
3374 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3376 if (!floating_scores[i].alive)
3383 floating_scores[found].alive = YES;
3384 floating_scores[found].x = x;
3385 floating_scores[found].y = y - 16;
3386 floating_scores[found].timer = 8;
3387 floating_scores[found].value = s;
3392 /* Try to bump a bad guy from below: */
3394 void trybumpbadguy(int x, int y, int sx)
3401 for (i = 0; i < NUM_BAD_GUYS; i++)
3403 if (bad_guys[i].alive &&
3404 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3405 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3407 if (bad_guys[i].kind == BAD_BSOD ||
3408 bad_guys[i].kind == BAD_LAPTOP)
3410 bad_guys[i].dying = FALLING;
3411 bad_guys[i].ym = -8;
3413 playsound(sounds[SND_FALL]);
3422 for (i = 0; i < NUM_UPGRADES; i++)
3424 if (upgrades[i].alive && upgrades[i].height == 32 &&
3425 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3426 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3428 upgrades[i].xm = -upgrades[i].xm;
3429 upgrades[i].ym = -8;
3431 playsound(sounds[SND_BUMP_UPGRADE]);
3438 /* Add an upgrade: */
3440 void add_upgrade(int x, int y, int kind)
3446 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3448 if (!upgrades[i].alive)
3454 upgrades[found].alive = YES;
3455 upgrades[found].kind = kind;
3456 upgrades[found].x = x;
3457 upgrades[found].y = y;
3458 upgrades[found].xm = 4;
3459 upgrades[found].ym = -4;
3460 upgrades[found].height = 0;
3467 void killtux(int mode)
3472 playsound(sounds[SND_HURT]);
3475 if (tux_dir == RIGHT)
3477 else if (tux_dir == LEFT)
3480 if (mode == SHRINK && tux_size == BIG)
3483 tux_got_coffee = NO;
3487 tux_safe = TUX_SAFE_TIME;
3498 void add_bullet(int x, int y, int dir, int xm)
3504 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3506 if (!bullets[i].alive)
3512 bullets[found].alive = YES;
3516 bullets[found].x = x + 32;
3517 bullets[found].xm = BULLET_XM + xm;
3521 bullets[found].x = x;
3522 bullets[found].xm = -BULLET_XM + xm;
3525 bullets[found].y = y;
3526 bullets[found].ym = BULLET_STARTING_YM;
3529 playsound(sounds[SND_SHOOT]);
3534 void drawendscreen(void)
3538 clearscreen(0, 0, 0);
3540 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3542 sprintf(str, "SCORE: %d", score);
3543 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3545 sprintf(str, "DISTROS: %d", distros);
3546 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);