7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 9, 2003
22 #include <sys/types.h>
32 #include "high_scores.h"
58 char * soundfilenames[NUM_SOUNDS] = {
59 DATA_PREFIX "/sounds/jump.wav",
60 DATA_PREFIX "/sounds/bigjump.wav",
61 DATA_PREFIX "/sounds/skid.wav",
62 DATA_PREFIX "/sounds/distro.wav",
63 DATA_PREFIX "/sounds/herring.wav",
64 DATA_PREFIX "/sounds/brick.wav",
65 DATA_PREFIX "/sounds/hurt.wav",
66 DATA_PREFIX "/sounds/squish.wav",
67 DATA_PREFIX "/sounds/fall.wav",
68 DATA_PREFIX "/sounds/ricochet.wav",
69 DATA_PREFIX "/sounds/bump-upgrade.wav",
70 DATA_PREFIX "/sounds/upgrade.wav",
71 DATA_PREFIX "/sounds/excellent.wav",
72 DATA_PREFIX "/sounds/coffee.wav",
73 DATA_PREFIX "/sounds/shoot.wav",
74 DATA_PREFIX "/sounds/lifeup.wav"
78 /* Local variables: */
80 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
81 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
82 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
83 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
84 super_bkgd_time, time_left, tux_invincible_time, endpos,
85 counting_distros, distro_counter;
86 int bkgd_red, bkgd_green, bkgd_blue, level_width;
87 int left, right, up, down, fire, old_fire;
88 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
89 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
90 SDL_Surface * img_bkgd[2][4];
91 SDL_Surface * img_golden_herring;
92 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
93 * img_laptop_left[3], * img_laptop_right[3],
94 * img_money_left[2], * img_money_right[2];
95 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
96 * img_bsod_falling_left, * img_bsod_falling_right,
97 * img_laptop_flat_left, * img_laptop_flat_right,
98 * img_laptop_falling_left, * img_laptop_falling_right;
99 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
100 * img_super_bkgd, * img_bullet, * img_red_glow;
101 SDL_Surface * img_cloud[2][4];
102 SDL_Surface * tux_right[3], * tux_left[3],
103 * bigtux_right[3], * bigtux_left[3],
104 * bigtux_right_jump, * bigtux_left_jump,
105 * cape_right[2], * cape_left[2],
106 * bigcape_right[2], * bigcape_left[2],
107 * ducktux_right, * ducktux_left,
108 * skidtux_right, * skidtux_left, * tux_life;
112 unsigned char * tiles[15];
113 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
114 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
115 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
116 bad_guy_type bad_guys[NUM_BAD_GUYS];
117 floating_score_type floating_scores[NUM_FLOATING_SCORES];
118 upgrade_type upgrades[NUM_UPGRADES];
119 bullet_type bullets[NUM_BULLETS];
125 /* Local function prototypes: */
128 void loadlevel(void);
129 void loadlevelgfx(void);
130 void loadlevelsong(void);
131 void unloadlevelgfx(void);
132 void unloadlevelsong(void);
133 void loadshared(void);
134 void unloadshared(void);
135 void drawshape(int x, int y, unsigned char c);
137 unsigned char shape(int x, int y, int sx);
138 int issolid(int x, int y, int sx);
139 int isbrick(int x, int y, int sx);
140 int isice(int x, int y, int sx);
141 int isfullbox(int x, int y, int sx);
142 void change(int x, int y, int sx, unsigned char c);
143 void trybreakbrick(int x, int y, int sx);
144 void bumpbrick(int x, int y, int sx);
145 void tryemptybox(int x, int y, int sx);
146 void trygrabdistro(int x, int y, int sx, int bounciness);
147 void add_bouncy_distro(int x, int y);
148 void add_broken_brick(int x, int y);
149 void add_broken_brick_piece(int x, int y, int xm, int ym);
150 void add_bouncy_brick(int x, int y);
151 void add_bad_guy(int x, int y, int kind);
152 void add_score(int x, int y, int s);
153 void trybumpbadguy(int x, int y, int sx);
154 void add_upgrade(int x, int y, int kind);
155 void killtux(int mode);
156 void add_bullet(int x, int y, int dir, int xm);
157 void drawendscreen(void);
158 void drawresultscreen(void);
160 /* --- GAME EVENT! --- */
162 void game_event(void)
165 while (SDL_PollEvent(&event))
168 if (event.type == SDL_QUIT)
170 /* Quit event - quit: */
174 else if (event.type == SDL_KEYDOWN)
178 key = event.key.keysym.sym;
180 /* Check for menu-events, if the menu is shown */
184 if (key == SDLK_ESCAPE)
186 /* Escape: Open/Close the menu: */
195 else if (key == SDLK_RIGHT)
199 else if (key == SDLK_LEFT)
203 else if (key == SDLK_UP)
207 else if (key == SDLK_DOWN)
211 else if (key == SDLK_LCTRL)
216 else if (event.type == SDL_KEYUP)
220 key = event.key.keysym.sym;
222 if (key == SDLK_RIGHT)
226 else if (key == SDLK_LEFT)
230 else if (key == SDLK_UP)
234 else if (key == SDLK_DOWN)
238 else if (key == SDLK_LCTRL)
242 else if (key == SDLK_p)
252 else if (key == SDLK_TAB)
254 tux_size = !tux_size;
256 else if (key == SDLK_END)
260 else if (key == SDLK_SPACE)
266 else if (event.type == SDL_JOYAXISMOTION)
268 if (event.jaxis.axis == JOY_X)
270 if (event.jaxis.value < -256)
275 if (event.jaxis.value > 256)
280 else if (event.jaxis.axis == JOY_Y)
282 if (event.jaxis.value > 256)
287 /* Handle joystick for the menu */
291 menuaction = MN_DOWN;
297 else if (event.type == SDL_JOYBUTTONDOWN)
299 if (event.jbutton.button == JOY_A)
301 else if (event.jbutton.button == JOY_B)
304 else if (event.type == SDL_JOYBUTTONUP)
306 if (event.jbutton.button == JOY_A)
308 else if (event.jbutton.button == JOY_B)
321 /* --- GAME ACTION! --- */
323 int game_action(void)
327 /* --- HANDLE TUX! --- */
329 /* Handle key and joystick state: */
331 if (!(tux_dying || next_level))
333 if (right == DOWN && left == UP)
337 if (tux_xm < -SKID_XM && !tux_skidding &&
340 tux_skidding = SKID_TIME;
342 play_sound(sounds[SND_SKID]);
348 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
356 if (tux_dir == RIGHT)
358 /* Facing the direction we're jumping? Go full-speed: */
362 tux_xm = tux_xm + WALK_SPEED;
364 if (tux_xm > MAX_WALK_XM)
365 tux_xm = MAX_WALK_XM;
367 else if (fire == DOWN)
369 tux_xm = tux_xm + RUN_SPEED;
371 if (tux_xm > MAX_RUN_XM)
377 /* Not facing the direction we're jumping?
380 tux_xm = tux_xm + WALK_SPEED / 2;
382 if (tux_xm > MAX_WALK_XM / 2)
383 tux_xm = MAX_WALK_XM / 2;
387 else if (left == DOWN && right == UP)
391 if (tux_xm > SKID_XM && !tux_skidding &&
394 tux_skidding = SKID_TIME;
395 play_sound(sounds[SND_SKID]);
400 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
410 /* Facing the direction we're jumping? Go full-speed: */
414 tux_xm = tux_xm - WALK_SPEED;
416 if (tux_xm < -MAX_WALK_XM)
417 tux_xm = -MAX_WALK_XM;
419 else if (fire == DOWN)
421 tux_xm = tux_xm - RUN_SPEED;
423 if (tux_xm < -MAX_RUN_XM)
424 tux_xm = -MAX_RUN_XM;
429 /* Not facing the direction we're jumping?
432 tux_xm = tux_xm - WALK_SPEED / 2;
434 if (tux_xm < -MAX_WALK_XM / 2)
435 tux_xm = -MAX_WALK_XM / 2;
443 if (tux_x >= endpos && endpos != 0)
453 if (jump_counter == 0)
457 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
460 /* If they're not on the ground, or are currently moving
461 vertically, don't jump! */
463 jump_counter = MAX_JUMP_COUNT;
467 /* Make sure we're not standing back up into a solid! */
469 if (tux_size == SMALL || tux_duck == NO ||
470 !issolid(tux_x, tux_y, scroll_x))
474 if (tux_size == SMALL)
475 play_sound(sounds[SND_JUMP]);
477 play_sound(sounds[SND_BIGJUMP]);
483 /* Keep jumping for a while: */
485 if (jump_counter < MAX_JUMP_COUNT)
487 tux_ym = tux_ym - JUMP_SPEED;
497 if (fire == DOWN && old_fire == UP && tux_got_coffee)
499 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
512 if (tux_size == BIG && tux_duck == YES)
514 /* Make sure we're not standing back up into a solid! */
516 if (!issolid(tux_x, tux_y - 32, scroll_x))
522 } /* (tux_dying || next_level) */
525 /* Tux either died, or reached the end of a level! */
534 /* End of a level! */
542 tux_ym = tux_ym + GRAVITY;
550 /* No more lives!? */
556 if (score > highscore)
563 } /* if (lives < 0) */
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');
807 play_sound(sounds[SND_DISTRO]);
808 score = score + SCORE_DISTRO;
811 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
812 shape(tux_x + 31, tux_y, scroll_x) == 'y')
814 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
818 if (counting_distros == NO)
820 counting_distros = YES;
821 distro_counter = 100;
824 if (distro_counter <= 0)
825 change(tux_x + 31, tux_y, scroll_x, 'a');
827 play_sound(sounds[SND_DISTRO]);
828 score = score + SCORE_DISTRO;
836 tux_y = (tux_y / 32) * 32 + 30;
842 tux_y = (tux_y / 32) * 32 - 32;
847 jump_counter = MAX_JUMP_COUNT;
857 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
858 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
860 if (tux_size == BIG && !tux_duck)
862 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
863 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
868 /* Enough distros for a One-up? */
870 if (distros >= DISTROS_LIFEUP)
872 distros = distros - DISTROS_LIFEUP;
873 if(lives < MAX_LIVES)
875 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
879 /* Keep in-bounds, vertically: */
883 else if (tux_y > 480)
889 /* Slow down horizontally: */
893 if (right == UP && left == UP)
895 if (isice(tux_x, tux_y + 32, scroll_x) ||
896 !issolid(tux_x, tux_y + 32, scroll_x))
898 /* Slowly on ice or in air: */
907 /* Quickly, otherwise: */
914 /* Drop vertically: */
916 if (!issolid(tux_x, tux_y + 32, scroll_x))
918 tux_ym = tux_ym + GRAVITY;
930 /* ---- DONE HANDLING TUX! --- */
933 /* Handle bouncy distros: */
935 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
937 if (bouncy_distros[i].alive)
939 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
941 bouncy_distros[i].ym++;
943 if (bouncy_distros[i].ym >= 0)
944 bouncy_distros[i].alive = NO;
949 /* Handle broken bricks: */
951 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
953 if (broken_bricks[i].alive)
955 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
956 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
958 broken_bricks[i].ym++;
960 if (broken_bricks[i].ym >= 0)
961 broken_bricks[i].alive = NO;
966 /* Handle distro counting: */
968 if (counting_distros == YES)
972 if (distro_counter <= 0)
973 counting_distros = -1;
977 /* Handle bouncy bricks: */
979 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
981 if (bouncy_bricks[i].alive)
983 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
984 bouncy_bricks[i].offset_m);
988 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
989 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
994 if (bouncy_bricks[i].offset == 0)
995 bouncy_bricks[i].alive = NO;
1000 /* Handle floating scores: */
1002 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1004 if (floating_scores[i].alive)
1006 floating_scores[i].y = floating_scores[i].y - 2;
1007 floating_scores[i].timer--;
1009 if (floating_scores[i].timer <= 0)
1010 floating_scores[i].alive = NO;
1015 /* Handle bullets: */
1017 for (i = 0; i < NUM_BULLETS; i++)
1019 if (bullets[i].alive)
1021 bullets[i].x = bullets[i].x + bullets[i].xm;
1022 bullets[i].y = bullets[i].y + bullets[i].ym;
1024 if (issolid(bullets[i].x, bullets[i].y, 0))
1026 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1027 bullets[i].alive = NO;
1030 if (bullets[i].ym >= 0)
1032 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1034 bullets[i].ym = -bullets[i].ym;
1038 bullets[i].ym = bullets[i].ym + GRAVITY;
1040 if (bullets[i].x < scroll_x ||
1041 bullets[i].x > scroll_x + 640)
1043 bullets[i].alive = NO;
1048 if (bullets[i].alive)
1050 for (j = 0; j < NUM_BAD_GUYS; j++)
1052 if (bad_guys[j].alive && !bad_guys[j].dying)
1054 if (bullets[i].x >= bad_guys[j].x - 4 &&
1055 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1056 bullets[i].y >= bad_guys[j].y - 4 &&
1057 bullets[i].y <= bad_guys[j].y + 32 + 4)
1059 /* Kill the bad guy! */
1061 bullets[i].alive = 0;
1062 bad_guys[j].dying = FALLING;
1063 bad_guys[j].ym = -8;
1066 /* Gain some points: */
1068 if (bad_guys[j].kind == BAD_BSOD)
1070 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1071 50 * score_multiplier);
1073 else if (bad_guys[j].kind == BAD_LAPTOP)
1075 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1076 25 * score_multiplier);
1080 /* Play death sound: */
1081 play_sound(sounds[SND_FALL]);
1089 /* Handle background timer: */
1091 if (super_bkgd_time)
1095 /* Handle invincibility timer: */
1098 if (tux_invincible_time > 50)
1100 tux_invincible_time--;
1103 if (!playing_music())
1104 play_music( herring_song, 1 );
1108 if (current_music == HERRING_MUSIC)
1110 /* stop the herring_song, now play the level_song ! */
1111 current_music = LEVEL_MUSIC;
1114 if (!playing_music())
1115 play_music( level_song, 1 );
1116 if (tux_invincible_time > 0)
1117 tux_invincible_time--;
1121 /* Handle upgrades: */
1123 for (i = 0; i < NUM_UPGRADES; i++)
1125 if (upgrades[i].alive)
1127 if (upgrades[i].height < 32)
1131 upgrades[i].height++;
1137 if (upgrades[i].kind == UPGRADE_MINTS ||
1138 upgrades[i].kind == UPGRADE_HERRING)
1140 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1141 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1143 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1144 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1146 if (upgrades[i].ym > 0)
1148 if (upgrades[i].kind == UPGRADE_MINTS)
1152 else if (upgrades[i].kind == UPGRADE_HERRING)
1154 upgrades[i].ym = -24;
1157 upgrades[i].y = (upgrades[i].y / 32) * 32;
1161 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1163 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1165 upgrades[i].xm = -upgrades[i].xm;
1170 /* Off the screen? Kill it! */
1172 if (upgrades[i].x < scroll_x)
1173 upgrades[i].alive = NO;
1176 /* Did the player grab it? */
1178 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1179 tux_x + scroll_x <= upgrades[i].x + 32 &&
1180 tux_y >= upgrades[i].y - 32 &&
1181 tux_y <= upgrades[i].y + 32)
1183 /* Remove the upgrade: */
1185 upgrades[i].alive = NO;
1188 /* Affect the player: */
1190 if (upgrades[i].kind == UPGRADE_MINTS)
1192 play_sound(sounds[SND_EXCELLENT]);
1194 super_bkgd_time = 8;
1196 else if (upgrades[i].kind == UPGRADE_COFFEE)
1198 play_sound(sounds[SND_COFFEE]);
1199 tux_got_coffee = YES;
1200 super_bkgd_time = 4;
1202 else if (upgrades[i].kind == UPGRADE_HERRING)
1204 play_sound(sounds[SND_HERRING]);
1205 tux_invincible_time = TUX_INVINCIBLE_TIME;
1206 super_bkgd_time = 4;
1207 /* play the herring song ^^ */
1208 current_music = HERRING_MUSIC;
1209 if (playing_music())
1211 play_music( herring_song, 1 );
1219 /* Handle bad guys: */
1221 for (i = 0; i < NUM_BAD_GUYS; i++)
1223 if (bad_guys[i].alive)
1225 if (bad_guys[i].seen)
1227 if (bad_guys[i].kind == BAD_BSOD)
1229 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1231 /* Move left/right: */
1233 if (bad_guys[i].dying == NO ||
1234 bad_guys[i].dying == FALLING)
1236 if (bad_guys[i].dir == RIGHT)
1237 bad_guys[i].x = bad_guys[i].x + 4;
1238 else if (bad_guys[i].dir == LEFT)
1239 bad_guys[i].x = bad_guys[i].x - 4;
1243 /* Move vertically: */
1245 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1248 /* Bump into things horizontally: */
1250 if (!bad_guys[i].dying)
1252 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1253 bad_guys[i].dir = !bad_guys[i].dir;
1257 /* Bump into other bad guys: */
1259 for (j = 0; j < NUM_BAD_GUYS; j++)
1261 if (j != i && bad_guys[j].alive &&
1262 !bad_guys[j].dying && !bad_guys[i].dying &&
1263 bad_guys[i].x >= bad_guys[j].x - 32 &&
1264 bad_guys[i].x <= bad_guys[j].x + 32 &&
1265 bad_guys[i].y >= bad_guys[j].y - 32 &&
1266 bad_guys[i].y <= bad_guys[j].y + 32)
1268 bad_guys[i].dir = !bad_guys[i].dir;
1273 /* Fall if we get off the ground: */
1275 if (bad_guys[i].dying != FALLING)
1277 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1278 bad_guys[i].ym < MAX_YM)
1280 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1286 if (bad_guys[i].ym > 0)
1288 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1294 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1296 if (bad_guys[i].y > 480)
1297 bad_guys[i].alive = NO;
1299 else if (bad_guys[i].kind == BAD_LAPTOP)
1301 /* --- LAPTOP MONSTER: --- */
1303 /* Move left/right: */
1305 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1307 if (bad_guys[i].dying == NO ||
1308 bad_guys[i].dying == FALLING)
1310 if (bad_guys[i].dir == RIGHT)
1311 bad_guys[i].x = bad_guys[i].x + 4;
1312 else if (bad_guys[i].dir == LEFT)
1313 bad_guys[i].x = bad_guys[i].x - 4;
1316 else if (bad_guys[i].mode == KICK)
1318 if (bad_guys[i].dir == RIGHT)
1319 bad_guys[i].x = bad_guys[i].x + 16;
1320 else if (bad_guys[i].dir == LEFT)
1321 bad_guys[i].x = bad_guys[i].x - 16;
1325 /* Move vertically: */
1327 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1330 /* Bump into things horizontally: */
1332 if (!bad_guys[i].dying)
1334 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1336 bad_guys[i].dir = !bad_guys[i].dir;
1338 if (bad_guys[i].mode == KICK)
1339 play_sound(sounds[SND_RICOCHET]);
1344 /* Bump into other bad guys: */
1346 for (j = 0; j < NUM_BAD_GUYS; j++)
1348 if (j != i && bad_guys[j].alive &&
1349 !bad_guys[j].dying && !bad_guys[i].dying &&
1350 bad_guys[i].x >= bad_guys[j].x - 32 &&
1351 bad_guys[i].x <= bad_guys[j].x + 32 &&
1352 bad_guys[i].y >= bad_guys[j].y - 32 &&
1353 bad_guys[i].y <= bad_guys[j].y + 32)
1355 if (bad_guys[i].mode != KICK)
1356 bad_guys[i].dir = !bad_guys[i].dir;
1359 /* We're in kick mode, kill the other guy: */
1361 bad_guys[j].dying = FALLING;
1362 bad_guys[j].ym = -8;
1363 play_sound(sounds[SND_FALL]);
1365 add_score(bad_guys[i].x - scroll_x,
1366 bad_guys[i].y, 100);
1372 /* Fall if we get off the ground: */
1374 if (bad_guys[i].dying != FALLING)
1376 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1377 bad_guys[i].ym < MAX_YM)
1379 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1385 if (bad_guys[i].ym > 0)
1387 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1393 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1395 if (bad_guys[i].y > 480)
1396 bad_guys[i].alive = NO;
1398 else if (bad_guys[i].kind == BAD_MONEY)
1400 /* --- MONEY BAGS: --- */
1403 /* Move vertically: */
1405 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1408 /* Fall if we get off the ground: */
1410 if (bad_guys[i].dying != FALLING)
1412 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1414 if (bad_guys[i].ym < MAX_YM)
1416 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1423 if (bad_guys[i].ym > 0)
1425 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1426 bad_guys[i].ym = -MAX_YM;
1431 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1433 if (bad_guys[i].y > 480)
1434 bad_guys[i].alive = NO;
1436 else if (bad_guys[i].kind == -1)
1440 /* Kill it if the player jumped on it: */
1442 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1443 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1444 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1445 tux_y >= bad_guys[i].y - 32 &&
1446 tux_y <= bad_guys[i].y - 8
1450 if (bad_guys[i].kind == BAD_BSOD)
1452 bad_guys[i].dying = SQUISHED;
1453 bad_guys[i].timer = 16;
1454 tux_ym = -KILL_BOUNCE_YM;
1456 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1457 50 * score_multiplier);
1459 play_sound(sounds[SND_SQUISH]);
1461 else if (bad_guys[i].kind == BAD_LAPTOP)
1463 if (bad_guys[i].mode != FLAT)
1467 bad_guys[i].mode = FLAT;
1469 bad_guys[i].timer = 64;
1477 bad_guys[i].mode = KICK;
1479 if (tux_x + scroll_x <= bad_guys[i].x)
1480 bad_guys[i].dir = RIGHT;
1482 bad_guys[i].dir = LEFT;
1484 bad_guys[i].timer = 8;
1487 tux_ym = -KILL_BOUNCE_YM;
1489 add_score(bad_guys[i].x - scroll_x,
1491 25 * score_multiplier);
1493 /* play_sound(sounds[SND_SQUISH]); */
1495 else if (bad_guys[i].kind == -1)
1502 /* Hurt the player if he just touched it: */
1504 if (!bad_guys[i].dying && !tux_dying &&
1506 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1507 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1508 tux_y >= bad_guys[i].y - 32 &&
1509 tux_y <= bad_guys[i].y + 32)
1511 if (bad_guys[i].mode == FLAT)
1515 bad_guys[i].mode = KICK;
1517 if (tux_x + scroll_x <= bad_guys[i].x)
1519 bad_guys[i].dir = RIGHT;
1520 bad_guys[i].x = bad_guys[i].x + 16;
1524 bad_guys[i].dir = LEFT;
1525 bad_guys[i].x = bad_guys[i].x - 16;
1528 bad_guys[i].timer = 8;
1530 else if (bad_guys[i].mode == KICK)
1532 if (tux_y < bad_guys[i].y - 16 &&
1533 bad_guys[i].timer == 0)
1535 /* Step on (stop being kicked) */
1537 bad_guys[i].mode = FLAT;
1538 bad_guys[i].timer = 64;
1542 /* Hurt if you get hit by kicked laptop: */
1544 if (bad_guys[i].timer == 0)
1546 if (tux_invincible_time == 0)
1552 bad_guys[i].dying = FALLING;
1553 bad_guys[i].ym = -8;
1554 play_sound(sounds[SND_FALL]);
1561 if (tux_invincible_time == 0)
1567 bad_guys[i].dying = FALLING;
1568 bad_guys[i].ym = -8;
1569 play_sound(sounds[SND_FALL]);
1575 /* Handle mode timer: */
1577 if (bad_guys[i].mode == FLAT)
1579 bad_guys[i].timer--;
1581 if (bad_guys[i].timer <= 0)
1582 bad_guys[i].mode = NORMAL;
1584 else if (bad_guys[i].mode == KICK)
1586 if (bad_guys[i].timer > 0)
1587 bad_guys[i].timer--;
1591 /* Handle dying timer: */
1593 if (bad_guys[i].dying == SQUISHED)
1595 bad_guys[i].timer--;
1598 /* Remove it if time's up: */
1600 if (bad_guys[i].timer <= 0)
1601 bad_guys[i].alive = NO;
1605 /* Remove if it's far off the screen: */
1607 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1608 bad_guys[i].alive = NO;
1612 /* Once it's on screen, it's activated! */
1614 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1615 bad_guys[i].seen = YES;
1621 /* Handle skidding: */
1623 if (tux_skidding > 0)
1631 /* --- GAME DRAW! --- */
1639 if (tux_dying && (frame % 4) == 0)
1640 clearscreen(255, 255, 255);
1643 if (super_bkgd_time == 0)
1644 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1646 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1650 /* Draw background: */
1652 for (y = 0; y < 15; y++)
1654 for (x = 0; x < 21; x++)
1656 drawshape(x * 32 - (scroll_x % 32), y * 32,
1657 tiles[y][x + (scroll_x / 32)]);
1662 /* (Bouncy bricks): */
1664 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1666 if (bouncy_bricks[i].alive)
1668 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1669 bouncy_bricks[i].x <= scroll_x + 640)
1671 dest.x = bouncy_bricks[i].x - scroll_x;
1672 dest.y = bouncy_bricks[i].y;
1676 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1681 drawshape(bouncy_bricks[i].x - scroll_x,
1682 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1683 bouncy_bricks[i].shape);
1691 for (i = 0; i < NUM_BAD_GUYS; i++)
1693 if (bad_guys[i].alive &&
1694 bad_guys[i].x > scroll_x - 32 &&
1695 bad_guys[i].x < scroll_x + 640)
1697 if (bad_guys[i].kind == BAD_BSOD)
1699 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1701 if (bad_guys[i].dying == NO)
1705 if (bad_guys[i].dir == LEFT)
1707 drawimage(img_bsod_left[(frame / 5) % 4],
1708 bad_guys[i].x - scroll_x,
1714 drawimage(img_bsod_right[(frame / 5) % 4],
1715 bad_guys[i].x - scroll_x,
1720 else if (bad_guys[i].dying == FALLING)
1724 if (bad_guys[i].dir == LEFT)
1726 drawimage(img_bsod_falling_left,
1727 bad_guys[i].x - scroll_x,
1733 drawimage(img_bsod_falling_right,
1734 bad_guys[i].x - scroll_x,
1739 else if (bad_guys[i].dying == SQUISHED)
1741 /* Dying - Squished: */
1743 if (bad_guys[i].dir == LEFT)
1745 drawimage(img_bsod_squished_left,
1746 bad_guys[i].x - scroll_x,
1752 drawimage(img_bsod_squished_right,
1753 bad_guys[i].x - scroll_x,
1759 else if (bad_guys[i].kind == BAD_LAPTOP)
1761 /* --- LAPTOP MONSTER: --- */
1763 if (bad_guys[i].dying == NO)
1767 if (bad_guys[i].mode == NORMAL)
1771 if (bad_guys[i].dir == LEFT)
1773 drawimage(img_laptop_left[(frame / 5) % 3],
1774 bad_guys[i].x - scroll_x,
1780 drawimage(img_laptop_right[(frame / 5) % 3],
1781 bad_guys[i].x - scroll_x,
1790 if (bad_guys[i].dir == LEFT)
1792 drawimage(img_laptop_flat_left,
1793 bad_guys[i].x - scroll_x,
1799 drawimage(img_laptop_flat_right,
1800 bad_guys[i].x - scroll_x,
1806 else if (bad_guys[i].dying == FALLING)
1810 if (bad_guys[i].dir == LEFT)
1812 drawimage(img_laptop_falling_left,
1813 bad_guys[i].x - scroll_x,
1819 drawimage(img_laptop_falling_right,
1820 bad_guys[i].x - scroll_x,
1826 else if (bad_guys[i].kind == BAD_MONEY)
1828 if (bad_guys[i].ym > -16)
1830 if (bad_guys[i].dir == LEFT)
1832 drawimage(img_money_left[0],
1833 bad_guys[i].x - scroll_x,
1839 drawimage(img_money_right[0],
1840 bad_guys[i].x - scroll_x,
1847 if (bad_guys[i].dir == LEFT)
1849 drawimage(img_money_left[1],
1850 bad_guys[i].x - scroll_x,
1856 drawimage(img_money_right[1],
1857 bad_guys[i].x - scroll_x,
1863 else if (bad_guys[i].kind == -1)
1871 if (right == UP && left == UP)
1878 if ((fire == DOWN && (frame % 2) == 0) ||
1880 tux_frame_main = (tux_frame_main + 1) % 4;
1882 tux_frame = tux_frame_main;
1889 if (tux_got_coffee && (frame % 2) == 1)
1893 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1897 if (tux_safe == 0 || (frame % 2) == 0)
1899 if (tux_size == SMALL)
1901 if (tux_invincible_time)
1905 if (tux_dir == RIGHT)
1907 drawimage(cape_right[frame % 2],
1913 drawimage(cape_left[frame % 2],
1920 if (tux_dir == RIGHT)
1922 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1926 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1931 if (tux_invincible_time)
1935 if (tux_dir == RIGHT)
1937 drawimage(bigcape_right[frame % 2],
1938 tux_x - 8 - 16, tux_y - 32,
1943 drawimage(bigcape_left[frame % 2],
1944 tux_x - 8, tux_y - 32,
1953 if (!jumping || tux_ym > 0)
1955 if (tux_dir == RIGHT)
1957 drawimage(bigtux_right[tux_frame],
1958 tux_x - 8, tux_y - 32,
1963 drawimage(bigtux_left[tux_frame],
1964 tux_x - 8, tux_y - 32,
1970 if (tux_dir == RIGHT)
1972 drawimage(bigtux_right_jump,
1973 tux_x - 8, tux_y - 32,
1978 drawimage(bigtux_left_jump,
1979 tux_x - 8, tux_y - 32,
1986 if (tux_dir == RIGHT)
1988 drawimage(skidtux_right,
1989 tux_x - 8, tux_y - 32,
1994 drawimage(skidtux_left,
1995 tux_x - 8, tux_y - 32,
2002 if (tux_dir == RIGHT)
2004 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2009 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2019 for (i = 0; i < NUM_BULLETS; i++)
2021 if (bullets[i].alive &&
2022 bullets[i].x >= scroll_x - 4 &&
2023 bullets[i].x <= scroll_x + 640)
2025 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2031 /* (Floating scores): */
2033 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2035 if (floating_scores[i].alive)
2037 sprintf(str, "%d", floating_scores[i].value);
2039 floating_scores[i].x + 16 - strlen(str) * 8,
2040 floating_scores[i].y,
2041 letters_gold, NO_UPDATE);
2048 for (i = 0; i < NUM_UPGRADES; i++)
2050 if (upgrades[i].alive)
2052 if (upgrades[i].height < 32)
2056 dest.x = upgrades[i].x - scroll_x;
2057 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2059 dest.h = upgrades[i].height;
2064 src.h = upgrades[i].height;
2066 if (upgrades[i].kind == UPGRADE_MINTS)
2067 SDL_BlitSurface(img_mints, &src, screen, &dest);
2068 else if (upgrades[i].kind == UPGRADE_COFFEE)
2069 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2070 else if (upgrades[i].kind == UPGRADE_HERRING)
2071 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2075 if (upgrades[i].kind == UPGRADE_MINTS)
2077 drawimage(img_mints,
2078 upgrades[i].x - scroll_x, upgrades[i].y,
2081 else if (upgrades[i].kind == UPGRADE_COFFEE)
2083 drawimage(img_coffee,
2084 upgrades[i].x - scroll_x, upgrades[i].y,
2087 else if (upgrades[i].kind == UPGRADE_HERRING)
2089 drawimage(img_golden_herring,
2090 upgrades[i].x - scroll_x, upgrades[i].y,
2098 /* (Bouncy distros): */
2100 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2102 if (bouncy_distros[i].alive)
2104 drawimage(img_distro[0],
2105 bouncy_distros[i].x - scroll_x,
2106 bouncy_distros[i].y,
2112 /* (Broken bricks): */
2114 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2116 if (broken_bricks[i].alive)
2118 src.x = rand() % 16;
2119 src.y = rand() % 16;
2123 dest.x = broken_bricks[i].x - scroll_x;
2124 dest.y = broken_bricks[i].y;
2128 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2135 sprintf(str, "%d", score);
2136 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2137 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2139 sprintf(str, "%d", highscore);
2140 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2141 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2143 if (time_left >= 50 || (frame % 10) < 5)
2145 sprintf(str, "%d", time_left);
2146 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2147 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2150 sprintf(str, "%d", distros);
2151 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2152 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2154 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE);
2156 for(i=0; i < lives; ++i)
2158 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2160 /*drawtext(str, 608, 0, letters_gold, NO_UPDATE);*/
2163 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2168 /* (Update it all!) */
2175 /* --- GAME LOOP! --- */
2180 Uint32 last_time, now_time;
2184 clearscreen(0, 0, 0);
2188 /* Init the game: */
2196 highscore = load_hs();
2199 /* --- MAIN GAME LOOP!!! --- */
2211 last_time = SDL_GetTicks();
2215 /* Handle events: */
2221 /* Handle actions: */
2223 if(!game_pause && !show_menu)
2225 if (game_action() == 0)
2227 /* == 0: no more lives */
2228 /* == -1: continues */
2235 /*Draw the current scene to the screen */
2238 /* Keep playing music: */
2241 if (!playing_music())
2243 switch (current_music)
2246 play_music(level_song, 1);
2249 play_music(herring_song, 1);
2251 case HURRYUP_MUSIC: // keep the compiler happy
2252 case NO_MUSIC: // keep the compiler happy for the moment :-)
2258 /* Time stops in pause mode */
2259 if(game_pause || show_menu )
2264 /* Pause til next frame: */
2266 now_time = SDL_GetTicks();
2267 if (now_time < last_time + FPS)
2268 SDL_Delay(last_time + FPS - now_time);
2273 if ((frame % 10) == 0 && time_left > 0)
2281 while (!done && !quit);
2283 if (playing_music())
2294 /* Initialize the game stuff: */
2306 /* Load data for this level: */
2308 void loadlevel(void)
2319 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2320 bouncy_distros[i].alive = NO;
2322 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2323 broken_bricks[i].alive = NO;
2325 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2326 bouncy_bricks[i].alive = NO;
2328 for (i = 0; i < NUM_BAD_GUYS; i++)
2329 bad_guys[i].alive = NO;
2331 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2332 floating_scores[i].alive = NO;
2334 for (i = 0; i < NUM_UPGRADES; i++)
2335 upgrades[i].alive = NO;
2337 for (i = 0; i < NUM_BULLETS; i++)
2338 bullets[i].alive = NO;
2341 /* Load data file: */
2343 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2344 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2345 fi = fopen(filename, "r");
2356 /* Load header info: */
2361 strcpy(levelname, str);
2362 levelname[strlen(levelname)-1] = '\0';
2366 strcpy(leveltheme, str);
2367 leveltheme[strlen(leveltheme)-1] = '\0';
2371 /* (Time to beat level) */
2373 time_left = atoi(str);
2375 /* (Song file for this level) */
2377 strcpy(song_title, str);
2378 song_title[strlen(song_title)-1] = '\0';
2382 /* (Level background color) */
2384 bkgd_red = atoi(str);
2386 bkgd_green= atoi(str);
2388 bkgd_blue = atoi(str);
2392 level_width = atoi(str);
2395 /* Allocate some space for the line-reading! */
2397 line = (char *) malloc(sizeof(char) * (level_width + 5));
2400 fprintf(stderr, "Couldn't allocate space to load level data!");
2405 /* Load the level lines: */
2407 for (y = 0; y < 15; y++)
2409 if(fgets(line, level_width + 5, fi) == NULL)
2411 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2414 line[strlen(line) - 1] = '\0';
2415 tiles[y] = strdup(line);
2421 /* Activate bad guys: */
2423 for (y = 0; y < 15; y++)
2425 for (x = 0; x < level_width; x++)
2427 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2429 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2444 tux_got_coffee = NO;
2445 tux_invincible_time = 0;
2449 tux_safe = TUX_SAFE_TIME;
2465 score_multiplier = 1;
2466 super_bkgd_time = 0;
2468 counting_distros = NO;
2473 /* set current song/music */
2474 current_music = LEVEL_MUSIC;
2478 clearscreen(0, 0, 0);
2480 sprintf(str, "LEVEL %d", level);
2481 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2483 sprintf(str, "%s", levelname);
2484 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2486 sprintf(str, "TUX x %d", lives);
2487 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2497 /* Load a level-specific graphic... */
2499 SDL_Surface * load_level_image(char * file, int use_alpha)
2503 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2505 return(load_image(fname, use_alpha));
2509 /* Load graphics: */
2511 void loadlevelgfx(void)
2513 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2514 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2516 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2517 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2518 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2519 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2521 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2522 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2523 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2524 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2526 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2527 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2528 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2529 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2535 void loadlevelsong(void)
2540 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2541 strlen(song_title) + 8));
2543 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2545 level_song = load_song(song_path);
2551 /* Free graphics data for this level: */
2553 void unloadlevelgfx(void)
2557 for (i = 0; i < 2; i++)
2559 SDL_FreeSurface(img_brick[i]);
2561 for (i = 0; i < 4; i++)
2563 SDL_FreeSurface(img_solid[i]);
2564 SDL_FreeSurface(img_bkgd[0][i]);
2565 SDL_FreeSurface(img_bkgd[1][i]);
2570 /* Free music data for this level: */
2572 void unloadlevelsong(void)
2574 free_music(level_song);
2578 /* Load graphics/sounds shared between all levels: */
2580 void loadshared(void)
2583 char * herring_song_path; /* for loading herring song*/
2587 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2590 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2593 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2596 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2599 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2602 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2605 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2608 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2611 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2614 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2617 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2620 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2623 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2627 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2629 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2632 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2635 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2639 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2642 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2646 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2650 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2654 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2657 ducktux_right = load_image(DATA_PREFIX
2658 "/images/shared/ducktux-right.png",
2661 ducktux_left = load_image(DATA_PREFIX
2662 "/images/shared/ducktux-left.png",
2665 skidtux_right = load_image(DATA_PREFIX
2666 "/images/shared/skidtux-right.png",
2669 skidtux_left = load_image(DATA_PREFIX
2670 "/images/shared/skidtux-left.png",
2676 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2678 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2685 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2687 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2690 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2693 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2699 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2700 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2706 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2708 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2714 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2717 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2720 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2723 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2727 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2730 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2733 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2736 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2744 img_bsod_left[0] = load_image(DATA_PREFIX
2745 "/images/shared/bsod-left-0.png",
2748 img_bsod_left[1] = load_image(DATA_PREFIX
2749 "/images/shared/bsod-left-1.png",
2752 img_bsod_left[2] = load_image(DATA_PREFIX
2753 "/images/shared/bsod-left-2.png",
2756 img_bsod_left[3] = load_image(DATA_PREFIX
2757 "/images/shared/bsod-left-3.png",
2760 img_bsod_right[0] = load_image(DATA_PREFIX
2761 "/images/shared/bsod-right-0.png",
2764 img_bsod_right[1] = load_image(DATA_PREFIX
2765 "/images/shared/bsod-right-1.png",
2768 img_bsod_right[2] = load_image(DATA_PREFIX
2769 "/images/shared/bsod-right-2.png",
2772 img_bsod_right[3] = load_image(DATA_PREFIX
2773 "/images/shared/bsod-right-3.png",
2776 img_bsod_squished_left = load_image(DATA_PREFIX
2777 "/images/shared/bsod-squished-left.png",
2780 img_bsod_squished_right = load_image(DATA_PREFIX
2781 "/images/shared/bsod-squished-right.png",
2784 img_bsod_falling_left = load_image(DATA_PREFIX
2785 "/images/shared/bsod-falling-left.png",
2788 img_bsod_falling_right = load_image(DATA_PREFIX
2789 "/images/shared/bsod-falling-right.png",
2795 img_laptop_left[0] = load_image(DATA_PREFIX
2796 "/images/shared/laptop-left-0.png",
2799 img_laptop_left[1] = load_image(DATA_PREFIX
2800 "/images/shared/laptop-left-1.png",
2803 img_laptop_left[2] = load_image(DATA_PREFIX
2804 "/images/shared/laptop-left-2.png",
2807 img_laptop_right[0] = load_image(DATA_PREFIX
2808 "/images/shared/laptop-right-0.png",
2811 img_laptop_right[1] = load_image(DATA_PREFIX
2812 "/images/shared/laptop-right-1.png",
2815 img_laptop_right[2] = load_image(DATA_PREFIX
2816 "/images/shared/laptop-right-2.png",
2819 img_laptop_flat_left = load_image(DATA_PREFIX
2820 "/images/shared/laptop-flat-left.png",
2823 img_laptop_flat_right = load_image(DATA_PREFIX
2824 "/images/shared/laptop-flat-right.png",
2827 img_laptop_falling_left =
2828 load_image(DATA_PREFIX
2829 "/images/shared/laptop-falling-left.png",
2832 img_laptop_falling_right =
2833 load_image(DATA_PREFIX
2834 "/images/shared/laptop-falling-right.png",
2840 img_money_left[0] = load_image(DATA_PREFIX
2841 "/images/shared/bag-left-0.png",
2844 img_money_left[1] = load_image(DATA_PREFIX
2845 "/images/shared/bag-left-1.png",
2848 img_money_right[0] = load_image(DATA_PREFIX
2849 "/images/shared/bag-right-0.png",
2852 img_money_right[1] = load_image(DATA_PREFIX
2853 "/images/shared/bag-right-1.png",
2860 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2861 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2866 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2868 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2874 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2877 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2880 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2883 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2888 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
2893 img_golden_herring =
2894 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2898 /* Super background: */
2900 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2904 /* Sound effects: */
2906 /* if (use_sound) // this can help speeding up a little, but
2907 we shouldn't take care about "use_sound" here, it's load_sound's job
2908 / Send a mail to neoneurone@users.sf.net, if you have another opinion. :)
2910 for (i = 0; i < NUM_SOUNDS; i++)
2911 sounds[i] = load_sound(soundfilenames[i]);
2914 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2915 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
2917 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
2919 herring_song = load_song(herring_song_path);
2921 free(herring_song_path);
2926 /* Free shared data: */
2928 void unloadshared(void)
2932 for (i = 0; i < 3; i++)
2934 SDL_FreeSurface(tux_right[i]);
2935 SDL_FreeSurface(tux_left[i]);
2936 SDL_FreeSurface(bigtux_right[i]);
2937 SDL_FreeSurface(bigtux_left[i]);
2940 SDL_FreeSurface(bigtux_right_jump);
2941 SDL_FreeSurface(bigtux_left_jump);
2943 for (i = 0; i < 2; i++)
2945 SDL_FreeSurface(cape_right[i]);
2946 SDL_FreeSurface(cape_left[i]);
2947 SDL_FreeSurface(bigcape_right[i]);
2948 SDL_FreeSurface(bigcape_left[i]);
2951 SDL_FreeSurface(ducktux_left);
2952 SDL_FreeSurface(ducktux_right);
2954 SDL_FreeSurface(skidtux_left);
2955 SDL_FreeSurface(skidtux_right);
2957 for (i = 0; i < 4; i++)
2959 SDL_FreeSurface(img_bsod_left[i]);
2960 SDL_FreeSurface(img_bsod_right[i]);
2963 SDL_FreeSurface(img_bsod_squished_left);
2964 SDL_FreeSurface(img_bsod_squished_right);
2966 SDL_FreeSurface(img_bsod_falling_left);
2967 SDL_FreeSurface(img_bsod_falling_right);
2969 for (i = 0; i < 3; i++)
2971 SDL_FreeSurface(img_laptop_left[i]);
2972 SDL_FreeSurface(img_laptop_right[i]);
2975 SDL_FreeSurface(img_laptop_flat_left);
2976 SDL_FreeSurface(img_laptop_flat_right);
2978 SDL_FreeSurface(img_laptop_falling_left);
2979 SDL_FreeSurface(img_laptop_falling_right);
2981 for (i = 0; i < 2; i++)
2983 SDL_FreeSurface(img_money_left[i]);
2984 SDL_FreeSurface(img_money_right[i]);
2987 SDL_FreeSurface(img_box_full);
2988 SDL_FreeSurface(img_box_empty);
2990 SDL_FreeSurface(img_water);
2991 for (i = 0; i < 3; i++)
2992 SDL_FreeSurface(img_waves[i]);
2994 SDL_FreeSurface(img_pole);
2995 SDL_FreeSurface(img_poletop);
2997 for (i = 0; i < 2; i++)
2998 SDL_FreeSurface(img_flag[i]);
3000 SDL_FreeSurface(img_mints);
3001 SDL_FreeSurface(img_coffee);
3003 for (i = 0; i < 4; i++)
3005 SDL_FreeSurface(img_distro[i]);
3006 SDL_FreeSurface(img_cloud[0][i]);
3007 SDL_FreeSurface(img_cloud[1][i]);
3010 SDL_FreeSurface(img_golden_herring);
3012 for (i = 0; i < NUM_SOUNDS; i++)
3013 free_chunk(sounds[i]);
3015 /* free the herring song */
3016 free_music( herring_song );
3020 /* Draw a tile on the screen: */
3022 void drawshape(int x, int y, unsigned char c)
3026 if (c == 'X' || c == 'x')
3027 drawimage(img_brick[0], x, y, NO_UPDATE);
3028 else if (c == 'Y' || c == 'y')
3029 drawimage(img_brick[1], x, y, NO_UPDATE);
3030 else if (c == 'A' || c =='B' || c == '!')
3031 drawimage(img_box_full, x, y, NO_UPDATE);
3033 drawimage(img_box_empty, x, y, NO_UPDATE);
3034 else if (c >= 'C' && c <= 'F')
3035 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3036 else if (c >= 'c' && c <= 'f')
3037 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3038 else if (c >= 'G' && c <= 'J')
3039 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3040 else if (c >= 'g' && c <= 'j')
3041 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3043 drawimage(img_solid[0], x, y, NO_UPDATE);
3045 drawimage(img_solid[1], x, y, NO_UPDATE);
3047 drawimage(img_solid[2], x, y, NO_UPDATE);
3049 drawimage(img_solid[3], x, y, NO_UPDATE);
3052 z = (frame / 2) % 6;
3055 drawimage(img_distro[z], x, y, NO_UPDATE);
3057 drawimage(img_distro[2], x, y, NO_UPDATE);
3059 drawimage(img_distro[1], x, y, NO_UPDATE);
3063 z = (frame / 3) % 3;
3065 drawimage(img_waves[z], x, y, NO_UPDATE);
3068 drawimage(img_poletop, x, y, NO_UPDATE);
3071 drawimage(img_pole, x, y, NO_UPDATE);
3073 /* Mark this as the end position of the level! */
3079 z = (frame / 3) % 2;
3081 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3084 drawimage(img_water, x, y, NO_UPDATE);
3088 /* What shape is at some position? */
3090 unsigned char shape(int x, int y, int sx)
3096 xx = ((x + sx) / 32);
3098 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3109 int issolid(int x, int y, int sx)
3115 if (isbrick(x, y, sx) ||
3116 isbrick(x + 31, y, sx) ||
3118 isice(x + 31, y, sx) ||
3119 (shape(x, y, sx) == '[' ||
3120 shape(x + 31, y, sx) == '[') ||
3121 (shape(x, y, sx) == '=' ||
3122 shape(x + 31, y, sx) == '=') ||
3123 (shape(x, y, sx) == ']' ||
3124 shape(x + 31, y, sx) == ']') ||
3125 (shape(x, y, sx) == 'A' ||
3126 shape(x + 31, y, sx) == 'A') ||
3127 (shape(x, y, sx) == 'B' ||
3128 shape(x + 31, y, sx) == 'B') ||
3129 (shape(x, y, sx) == '!' ||
3130 shape(x + 31, y, sx) == '!') ||
3131 (shape(x, y, sx) == 'a' ||
3132 shape(x + 31, y, sx) == 'a'))
3141 /* Is it a brick? */
3143 int isbrick(int x, int y, int sx)
3149 if (shape(x, y, sx) == 'X' ||
3150 shape(x, y, sx) == 'x' ||
3151 shape(x, y, sx) == 'Y' ||
3152 shape(x, y, sx) == 'y')
3163 int isice(int x, int y, int sx)
3169 if (shape(x, y, sx) == '#')
3178 /* Is it a full box? */
3180 int isfullbox(int x, int y, int sx)
3186 if (shape(x, y, sx) == 'A' ||
3187 shape(x, y, sx) == 'B' ||
3188 shape(x, y, sx) == '!')
3197 /* Edit a piece of the map! */
3199 void change(int x, int y, int sx, unsigned char c)
3204 xx = ((x + sx) / 32);
3206 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3211 /* Break a brick: */
3213 void trybreakbrick(int x, int y, int sx)
3215 if (isbrick(x, y, sx))
3217 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3219 /* Get a distro from it: */
3221 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3224 if (counting_distros == NO)
3226 counting_distros = YES;
3227 distro_counter = 50;
3230 if (distro_counter <= 0)
3231 change(x, y, sx, 'a');
3233 play_sound(sounds[SND_DISTRO]);
3234 score = score + SCORE_DISTRO;
3239 /* Get rid of it: */
3241 change(x, y, sx, '.');
3245 /* Replace it with broken bits: */
3247 add_broken_brick(((x + sx + 1) / 32) * 32,
3251 /* Get some score: */
3253 play_sound(sounds[SND_BRICK]);
3254 score = score + SCORE_BRICK;
3259 /* Bounce a brick: */
3261 void bumpbrick(int x, int y, int sx)
3263 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3266 play_sound(sounds[SND_BRICK]);
3272 void tryemptybox(int x, int y, int sx)
3274 if (isfullbox(x, y, sx))
3276 if (shape(x, y, sx) == 'A')
3278 /* Box with a distro! */
3280 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3281 (y / 32) * 32 - 32);
3283 play_sound(sounds[SND_DISTRO]);
3284 score = score + SCORE_DISTRO;
3287 else if (shape(x, y, sx) == 'B')
3289 /* Add an upgrade! */
3291 if (tux_size == SMALL)
3293 /* Tux is small, add mints! */
3295 add_upgrade(((x + sx + 1) / 32) * 32,
3301 /* Tux is big, add coffee: */
3303 add_upgrade(((x + sx + 1) / 32) * 32,
3308 play_sound(sounds[SND_UPGRADE]);
3310 else if (shape(x, y, sx) == '!')
3312 /* Add a golden herring */
3314 add_upgrade(((x + sx + 1) / 32) * 32,
3319 /* Empty the box: */
3321 change(x, y, sx, 'a');
3326 /* Try to grab a distro: */
3328 void trygrabdistro(int x, int y, int sx, int bounciness)
3330 if (shape(x, y, sx) == '$')
3332 change(x, y, sx, '.');
3333 play_sound(sounds[SND_DISTRO]);
3335 if (bounciness == BOUNCE)
3337 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3341 score = score + SCORE_DISTRO;
3347 /* Add a bouncy distro: */
3349 void add_bouncy_distro(int x, int y)
3355 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3357 if (!bouncy_distros[i].alive)
3363 bouncy_distros[found].alive = YES;
3364 bouncy_distros[found].x = x;
3365 bouncy_distros[found].y = y;
3366 bouncy_distros[found].ym = -6;
3371 /* Add broken brick pieces: */
3373 void add_broken_brick(int x, int y)
3375 add_broken_brick_piece(x, y, -4, -16);
3376 add_broken_brick_piece(x, y + 16, -6, -12);
3378 add_broken_brick_piece(x + 16, y, 4, -16);
3379 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3383 /* Add a broken brick piece: */
3385 void add_broken_brick_piece(int x, int y, int xm, int ym)
3391 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3393 if (!broken_bricks[i].alive)
3399 broken_bricks[found].alive = YES;
3400 broken_bricks[found].x = x;
3401 broken_bricks[found].y = y;
3402 broken_bricks[found].xm = xm;
3403 broken_bricks[found].ym = ym;
3408 /* Add a bouncy brick piece: */
3410 void add_bouncy_brick(int x, int y)
3416 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3418 if (!bouncy_bricks[i].alive)
3424 bouncy_bricks[found].alive = YES;
3425 bouncy_bricks[found].x = x;
3426 bouncy_bricks[found].y = y;
3427 bouncy_bricks[found].offset = 0;
3428 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3429 bouncy_bricks[found].shape = shape(x, y, 0);
3434 /* Add a bad guy: */
3436 void add_bad_guy(int x, int y, int kind)
3442 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3444 if (!bad_guys[i].alive)
3450 bad_guys[found].alive = YES;
3451 bad_guys[found].mode = NORMAL;
3452 bad_guys[found].dying = NO;
3453 bad_guys[found].timer = 0;
3454 bad_guys[found].kind = kind;
3455 bad_guys[found].x = x;
3456 bad_guys[found].y = y;
3457 bad_guys[found].xm = 0;
3458 bad_guys[found].ym = 0;
3459 bad_guys[found].dir = LEFT;
3460 bad_guys[found].seen = NO;
3467 void add_score(int x, int y, int s)
3472 /* Add the score: */
3477 /* Add a floating score thing to the game: */
3481 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3483 if (!floating_scores[i].alive)
3490 floating_scores[found].alive = YES;
3491 floating_scores[found].x = x;
3492 floating_scores[found].y = y - 16;
3493 floating_scores[found].timer = 8;
3494 floating_scores[found].value = s;
3499 /* Try to bump a bad guy from below: */
3501 void trybumpbadguy(int x, int y, int sx)
3508 for (i = 0; i < NUM_BAD_GUYS; i++)
3510 if (bad_guys[i].alive &&
3511 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3512 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3514 if (bad_guys[i].kind == BAD_BSOD ||
3515 bad_guys[i].kind == BAD_LAPTOP)
3517 bad_guys[i].dying = FALLING;
3518 bad_guys[i].ym = -8;
3519 play_sound(sounds[SND_FALL]);
3527 for (i = 0; i < NUM_UPGRADES; i++)
3529 if (upgrades[i].alive && upgrades[i].height == 32 &&
3530 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3531 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3533 upgrades[i].xm = -upgrades[i].xm;
3534 upgrades[i].ym = -8;
3535 play_sound(sounds[SND_BUMP_UPGRADE]);
3541 /* Add an upgrade: */
3543 void add_upgrade(int x, int y, int kind)
3549 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3551 if (!upgrades[i].alive)
3557 upgrades[found].alive = YES;
3558 upgrades[found].kind = kind;
3559 upgrades[found].x = x;
3560 upgrades[found].y = y;
3561 upgrades[found].xm = 4;
3562 upgrades[found].ym = -4;
3563 upgrades[found].height = 0;
3570 void killtux(int mode)
3574 play_sound(sounds[SND_HURT]);
3576 if (tux_dir == RIGHT)
3578 else if (tux_dir == LEFT)
3581 if (mode == SHRINK && tux_size == BIG)
3584 tux_got_coffee = NO;
3588 tux_safe = TUX_SAFE_TIME;
3599 void add_bullet(int x, int y, int dir, int xm)
3605 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3607 if (!bullets[i].alive)
3613 bullets[found].alive = YES;
3617 bullets[found].x = x + 32;
3618 bullets[found].xm = BULLET_XM + xm;
3622 bullets[found].x = x;
3623 bullets[found].xm = -BULLET_XM + xm;
3626 bullets[found].y = y;
3627 bullets[found].ym = BULLET_STARTING_YM;
3629 play_sound(sounds[SND_SHOOT]);
3634 void drawendscreen(void)
3638 clearscreen(0, 0, 0);
3640 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3642 sprintf(str, "SCORE: %d", score);
3643 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3645 sprintf(str, "DISTROS: %d", distros);
3646 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3652 void drawresultscreen(void)
3656 clearscreen(0, 0, 0);
3658 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3660 sprintf(str, "SCORE: %d", score);
3661 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3663 sprintf(str, "DISTROS: %d", distros);
3664 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3667 /*SDL_Delay(2000);*/