7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 28, 2003
22 #include <sys/types.h>
32 #include "high_scores.h"
60 char * soundfilenames[NUM_SOUNDS] = {
61 DATA_PREFIX "/sounds/jump.wav",
62 DATA_PREFIX "/sounds/bigjump.wav",
63 DATA_PREFIX "/sounds/skid.wav",
64 DATA_PREFIX "/sounds/distro.wav",
65 DATA_PREFIX "/sounds/herring.wav",
66 DATA_PREFIX "/sounds/brick.wav",
67 DATA_PREFIX "/sounds/hurt.wav",
68 DATA_PREFIX "/sounds/squish.wav",
69 DATA_PREFIX "/sounds/fall.wav",
70 DATA_PREFIX "/sounds/ricochet.wav",
71 DATA_PREFIX "/sounds/bump-upgrade.wav",
72 DATA_PREFIX "/sounds/upgrade.wav",
73 DATA_PREFIX "/sounds/excellent.wav",
74 DATA_PREFIX "/sounds/coffee.wav",
75 DATA_PREFIX "/sounds/shoot.wav",
76 DATA_PREFIX "/sounds/lifeup.wav"
80 /* Local variables: */
82 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
83 done, quit, 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, * tux_life;
114 unsigned char * tiles[15];
115 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
116 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
117 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
118 bad_guy_type bad_guys[NUM_BAD_GUYS];
119 floating_score_type floating_scores[NUM_FLOATING_SCORES];
120 upgrade_type upgrades[NUM_UPGRADES];
121 bullet_type bullets[NUM_BULLETS];
128 /* Local function prototypes: */
131 void loadlevel(void);
132 void loadlevelgfx(void);
133 void loadlevelsong(void);
134 void unloadlevelgfx(void);
135 void unloadlevelsong(void);
136 void loadshared(void);
137 void unloadshared(void);
138 void drawshape(int x, int y, unsigned char c);
140 unsigned char shape(int x, int y, int sx);
141 int issolid(int x, int y, int sx);
142 int isbrick(int x, int y, int sx);
143 int isice(int x, int y, int sx);
144 int isfullbox(int x, int y, int sx);
145 void change(int x, int y, int sx, unsigned char c);
146 void trybreakbrick(int x, int y, int sx);
147 void bumpbrick(int x, int y, int sx);
148 void tryemptybox(int x, int y, int sx);
149 void trygrabdistro(int x, int y, int sx, int bounciness);
150 void add_bouncy_distro(int x, int y);
151 void add_broken_brick(int x, int y);
152 void add_broken_brick_piece(int x, int y, int xm, int ym);
153 void add_bouncy_brick(int x, int y);
154 void add_bad_guy(int x, int y, int kind);
155 void add_score(int x, int y, int s);
156 void trybumpbadguy(int x, int y, int sx);
157 void add_upgrade(int x, int y, int kind);
158 void killtux(int mode);
159 void add_bullet(int x, int y, int dir, int xm);
160 void drawendscreen(void);
161 void drawresultscreen(void);
163 /* --- GAME EVENT! --- */
165 void game_event(void)
168 while (SDL_PollEvent(&event))
171 if (event.type == SDL_QUIT)
173 /* Quit event - quit: */
177 else if (event.type == SDL_KEYDOWN)
181 key = event.key.keysym.sym;
183 /* Check for menu-events, if the menu is shown */
187 if (key == SDLK_ESCAPE)
189 /* Escape: Open/Close the menu: */
198 else if (key == SDLK_RIGHT)
202 else if (key == SDLK_LEFT)
206 else if (key == SDLK_UP)
210 else if (key == SDLK_DOWN)
214 else if (key == SDLK_LCTRL)
219 else if (event.type == SDL_KEYUP)
223 key = event.key.keysym.sym;
225 if (key == SDLK_RIGHT)
229 else if (key == SDLK_LEFT)
233 else if (key == SDLK_UP)
237 else if (key == SDLK_DOWN)
241 else if (key == SDLK_LCTRL)
245 else if (key == SDLK_p)
255 else if (key == SDLK_TAB && debug_mode == YES)
257 tux_size = !tux_size;
259 else if (key == SDLK_END && debug_mode == YES)
263 else if (key == SDLK_SPACE && debug_mode == YES)
269 else if (event.type == SDL_JOYAXISMOTION)
271 if (event.jaxis.axis == JOY_X)
273 if (event.jaxis.value < -256)
278 if (event.jaxis.value > 256)
283 else if (event.jaxis.axis == JOY_Y)
285 if (event.jaxis.value > 256)
290 /* Handle joystick for the menu */
294 menuaction = MN_DOWN;
300 else if (event.type == SDL_JOYBUTTONDOWN)
302 if (event.jbutton.button == JOY_A)
304 else if (event.jbutton.button == JOY_B)
307 else if (event.type == SDL_JOYBUTTONUP)
309 if (event.jbutton.button == JOY_A)
311 else if (event.jbutton.button == JOY_B)
324 /* --- GAME ACTION! --- */
326 int game_action(void)
330 /* --- HANDLE TUX! --- */
332 /* Handle key and joystick state: */
334 if (!(tux_dying || next_level))
336 if (right == DOWN && left == UP)
340 if (tux_xm < -SKID_XM && !tux_skidding &&
343 tux_skidding = SKID_TIME;
345 play_sound(sounds[SND_SKID]);
351 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
359 if (tux_dir == RIGHT)
361 /* Facing the direction we're jumping? Go full-speed: */
365 tux_xm = tux_xm + WALK_SPEED;
367 if (tux_xm > MAX_WALK_XM)
368 tux_xm = MAX_WALK_XM;
370 else if (fire == DOWN)
372 tux_xm = tux_xm + RUN_SPEED;
374 if (tux_xm > MAX_RUN_XM)
380 /* Not facing the direction we're jumping?
383 tux_xm = tux_xm + WALK_SPEED / 2;
385 if (tux_xm > MAX_WALK_XM / 2)
386 tux_xm = MAX_WALK_XM / 2;
390 else if (left == DOWN && right == UP)
394 if (tux_xm > SKID_XM && !tux_skidding &&
397 tux_skidding = SKID_TIME;
398 play_sound(sounds[SND_SKID]);
403 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
413 /* Facing the direction we're jumping? Go full-speed: */
417 tux_xm = tux_xm - WALK_SPEED;
419 if (tux_xm < -MAX_WALK_XM)
420 tux_xm = -MAX_WALK_XM;
422 else if (fire == DOWN)
424 tux_xm = tux_xm - RUN_SPEED;
426 if (tux_xm < -MAX_RUN_XM)
427 tux_xm = -MAX_RUN_XM;
432 /* Not facing the direction we're jumping?
435 tux_xm = tux_xm - WALK_SPEED / 2;
437 if (tux_xm < -MAX_WALK_XM / 2)
438 tux_xm = -MAX_WALK_XM / 2;
446 if (tux_x >= endpos && endpos != 0)
456 if (jump_counter == 0)
460 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
463 /* If they're not on the ground, or are currently moving
464 vertically, don't jump! */
466 jump_counter = MAX_JUMP_COUNT;
470 /* Make sure we're not standing back up into a solid! */
472 if (tux_size == SMALL || tux_duck == NO ||
473 !issolid(tux_x, tux_y, scroll_x))
477 if (tux_size == SMALL)
478 play_sound(sounds[SND_JUMP]);
480 play_sound(sounds[SND_BIGJUMP]);
486 /* Keep jumping for a while: */
488 if (jump_counter < MAX_JUMP_COUNT)
490 tux_ym = tux_ym - JUMP_SPEED;
500 if (fire == DOWN && old_fire == UP && tux_got_coffee)
502 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
515 if (tux_size == BIG && tux_duck == YES)
517 /* Make sure we're not standing back up into a solid! */
519 if (!issolid(tux_x, tux_y - 32, scroll_x))
525 } /* (tux_dying || next_level) */
528 /* Tux either died, or reached the end of a level! */
537 /* End of a level! */
545 tux_ym = tux_ym + GRAVITY;
553 /* No more lives!? */
559 if (score > highscore)
566 } /* if (lives < 0) */
569 /* Either way, (re-)load the (next) level... */
580 tux_x = tux_x + tux_xm;
581 tux_y = tux_y + tux_ym;
584 /* Keep tux in bounds: */
587 else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
589 scroll_x = scroll_x - ( 160 - tux_x);
596 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
598 /* Scroll the screen in past center: */
600 scroll_x = scroll_x + (tux_x - 320);
603 if (scroll_x > ((level_width * 32) - 640))
604 scroll_x = ((level_width * 32) - 640);
606 else if (tux_x > 608)
608 /* ... unless there's no more to scroll! */
618 if (issolid(tux_x, tux_y + 31, scroll_x) &&
619 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
621 while (issolid(tux_x, tux_y + 31, scroll_x))
632 if (issolid(tux_x, tux_y, scroll_x) &&
633 !issolid(tux_x - tux_xm, tux_y, scroll_x))
635 while (issolid(tux_x, tux_y, scroll_x))
646 if (issolid(tux_x, tux_y + 31, scroll_x))
648 /* Set down properly: */
650 while (issolid(tux_x, tux_y + 31, scroll_x))
659 /* Reset score multiplier (for mutli-hits): */
662 score_multiplier = 1;
672 /* Bump into things: */
674 if (issolid(tux_x, tux_y, scroll_x) ||
675 (tux_size == BIG && !tux_duck &&
676 (issolid(tux_x, tux_y - 32, scroll_x))))
678 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
679 (tux_size == SMALL || tux_duck ||
680 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
682 tux_x = tux_x - tux_xm;
685 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
686 (tux_size == SMALL || tux_duck ||
687 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
695 /* Break bricks and empty boxes: */
699 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
700 isfullbox(tux_x, tux_y - 32, scroll_x))
702 trygrabdistro(tux_x, tux_y - 64, scroll_x,
704 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
706 if (isfullbox(tux_x, tux_y - 32,
709 bumpbrick(tux_x, tux_y - 32,
713 trybreakbrick(tux_x, tux_y - 32, scroll_x);
714 tryemptybox(tux_x, tux_y - 32, scroll_x);
717 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
718 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
720 trygrabdistro(tux_x + 31,
724 trybumpbadguy(tux_x + 31,
728 if (isfullbox(tux_x + 31, tux_y - 32,
731 bumpbrick(tux_x + 31, tux_y - 32,
735 trybreakbrick(tux_x + 31,
738 tryemptybox(tux_x + 31,
745 if (isbrick(tux_x, tux_y, scroll_x) ||
746 isfullbox(tux_x, tux_y, scroll_x))
748 trygrabdistro(tux_x, tux_y - 32, scroll_x,
750 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
751 if (isfullbox(tux_x, tux_y, scroll_x))
752 bumpbrick(tux_x, tux_y, scroll_x);
753 trybreakbrick(tux_x, tux_y, scroll_x);
754 tryemptybox(tux_x, tux_y, scroll_x);
757 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
758 isfullbox(tux_x + 31, tux_y, scroll_x))
760 trygrabdistro(tux_x + 31,
764 trybumpbadguy(tux_x + 31,
767 if (isfullbox(tux_x + 31, tux_y, scroll_x))
768 bumpbrick(tux_x + 31, tux_y, scroll_x);
769 trybreakbrick(tux_x + 31, tux_y, scroll_x);
770 tryemptybox(tux_x + 31, tux_y, scroll_x);
776 /* It's a brick and we're small, make the brick
777 bounce, and grab any distros above it: */
779 if (isbrick(tux_x, tux_y, scroll_x) ||
780 isfullbox(tux_x, tux_y, scroll_x))
782 trygrabdistro(tux_x, tux_y - 32, scroll_x,
784 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
785 bumpbrick(tux_x, tux_y, scroll_x);
786 tryemptybox(tux_x, tux_y, scroll_x);
789 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
790 isfullbox(tux_x + 31, tux_y, scroll_x))
792 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
794 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
795 bumpbrick(tux_x + 31, tux_y, scroll_x);
796 tryemptybox(tux_x + 31, tux_y, scroll_x);
800 /* Get a distro from a brick? */
802 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
803 shape(tux_x, tux_y, scroll_x) == 'y')
805 add_bouncy_distro(((tux_x + scroll_x + 1)
809 if (counting_distros == NO)
811 counting_distros = YES;
812 distro_counter = 100;
815 if (distro_counter <= 0)
816 change(tux_x, tux_y, scroll_x, 'a');
818 play_sound(sounds[SND_DISTRO]);
819 score = score + SCORE_DISTRO;
822 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
823 shape(tux_x + 31, tux_y, scroll_x) == 'y')
825 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
829 if (counting_distros == NO)
831 counting_distros = YES;
832 distro_counter = 100;
835 if (distro_counter <= 0)
836 change(tux_x + 31, tux_y, scroll_x, 'a');
838 play_sound(sounds[SND_DISTRO]);
839 score = score + SCORE_DISTRO;
847 tux_y = (tux_y / 32) * 32 + 30;
853 tux_y = (tux_y / 32) * 32 - 32;
858 jump_counter = MAX_JUMP_COUNT;
868 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
869 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
871 if (tux_size == BIG && !tux_duck)
873 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
874 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
879 /* Enough distros for a One-up? */
881 if (distros >= DISTROS_LIFEUP)
883 distros = distros - DISTROS_LIFEUP;
884 if(lives < MAX_LIVES)
886 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
890 /* Keep in-bounds, vertically: */
894 else if (tux_y > 480)
900 /* Slow down horizontally: */
904 if (right == UP && left == UP)
906 if (isice(tux_x, tux_y + 32, scroll_x) ||
907 !issolid(tux_x, tux_y + 32, scroll_x))
909 /* Slowly on ice or in air: */
918 /* Quickly, otherwise: */
925 /* Drop vertically: */
927 if (!issolid(tux_x, tux_y + 32, scroll_x))
929 tux_ym = tux_ym + GRAVITY;
941 /* ---- DONE HANDLING TUX! --- */
944 /* Handle bouncy distros: */
946 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
948 if (bouncy_distros[i].alive)
950 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
952 bouncy_distros[i].ym++;
954 if (bouncy_distros[i].ym >= 0)
955 bouncy_distros[i].alive = NO;
960 /* Handle broken bricks: */
962 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
964 if (broken_bricks[i].alive)
966 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
967 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
969 broken_bricks[i].ym++;
971 if (broken_bricks[i].ym >= 0)
972 broken_bricks[i].alive = NO;
977 /* Handle distro counting: */
979 if (counting_distros == YES)
983 if (distro_counter <= 0)
984 counting_distros = -1;
988 /* Handle bouncy bricks: */
990 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
992 if (bouncy_bricks[i].alive)
994 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
995 bouncy_bricks[i].offset_m);
999 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
1000 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
1003 /* Stop bouncing? */
1005 if (bouncy_bricks[i].offset == 0)
1006 bouncy_bricks[i].alive = NO;
1011 /* Handle floating scores: */
1013 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1015 if (floating_scores[i].alive)
1017 floating_scores[i].y = floating_scores[i].y - 2;
1018 floating_scores[i].timer--;
1020 if (floating_scores[i].timer <= 0)
1021 floating_scores[i].alive = NO;
1026 /* Handle bullets: */
1028 for (i = 0; i < NUM_BULLETS; i++)
1030 if (bullets[i].alive)
1032 bullets[i].x = bullets[i].x + bullets[i].xm;
1033 bullets[i].y = bullets[i].y + bullets[i].ym;
1035 if (issolid(bullets[i].x, bullets[i].y, 0))
1037 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1038 bullets[i].alive = NO;
1041 if (bullets[i].ym >= 0)
1043 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1045 bullets[i].ym = -bullets[i].ym;
1049 bullets[i].ym = bullets[i].ym + GRAVITY;
1051 if (bullets[i].x < scroll_x ||
1052 bullets[i].x > scroll_x + 640)
1054 bullets[i].alive = NO;
1059 if (bullets[i].alive)
1061 for (j = 0; j < NUM_BAD_GUYS; j++)
1063 if (bad_guys[j].alive && !bad_guys[j].dying)
1065 if (bullets[i].x >= bad_guys[j].x - 4 &&
1066 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1067 bullets[i].y >= bad_guys[j].y - 4 &&
1068 bullets[i].y <= bad_guys[j].y + 32 + 4)
1070 /* Kill the bad guy! */
1072 bullets[i].alive = 0;
1073 bad_guys[j].dying = FALLING;
1074 bad_guys[j].ym = -8;
1077 /* Gain some points: */
1079 if (bad_guys[j].kind == BAD_BSOD)
1081 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1082 50 * score_multiplier);
1084 else if (bad_guys[j].kind == BAD_LAPTOP)
1086 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1087 25 * score_multiplier);
1091 /* Play death sound: */
1092 play_sound(sounds[SND_FALL]);
1100 /* Handle background timer: */
1102 if (super_bkgd_time)
1106 /* Handle invincibility timer: */
1109 if (tux_invincible_time > 50)
1111 tux_invincible_time--;
1114 if (!playing_music())
1115 play_music( herring_song, 1 );
1119 if (current_music == HERRING_MUSIC)
1121 /* stop the herring_song, now play the level_song ! */
1122 current_music = LEVEL_MUSIC;
1126 if (!playing_music())
1128 if (time_left <= TIME_WARNING)
1129 play_music( level_song_fast, 1 );
1131 play_music( level_song, 1 );
1134 if (tux_invincible_time > 0)
1135 tux_invincible_time--;
1139 /* Handle upgrades: */
1141 for (i = 0; i < NUM_UPGRADES; i++)
1143 if (upgrades[i].alive)
1145 if (upgrades[i].height < 32)
1149 upgrades[i].height++;
1155 if (upgrades[i].kind == UPGRADE_MINTS ||
1156 upgrades[i].kind == UPGRADE_HERRING)
1158 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1159 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1161 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1162 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1164 if (upgrades[i].ym > 0)
1166 if (upgrades[i].kind == UPGRADE_MINTS)
1170 else if (upgrades[i].kind == UPGRADE_HERRING)
1172 upgrades[i].ym = -24;
1175 upgrades[i].y = (upgrades[i].y / 32) * 32;
1179 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1181 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1183 upgrades[i].xm = -upgrades[i].xm;
1188 /* Off the screen? Kill it! */
1190 if (upgrades[i].x < scroll_x)
1191 upgrades[i].alive = NO;
1194 /* Did the player grab it? */
1196 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1197 tux_x + scroll_x <= upgrades[i].x + 32 &&
1198 tux_y >= upgrades[i].y - 32 &&
1199 tux_y <= upgrades[i].y + 32)
1201 /* Remove the upgrade: */
1203 upgrades[i].alive = NO;
1206 /* Affect the player: */
1208 if (upgrades[i].kind == UPGRADE_MINTS)
1210 play_sound(sounds[SND_EXCELLENT]);
1212 super_bkgd_time = 8;
1214 else if (upgrades[i].kind == UPGRADE_COFFEE)
1216 play_sound(sounds[SND_COFFEE]);
1217 tux_got_coffee = YES;
1218 super_bkgd_time = 4;
1220 else if (upgrades[i].kind == UPGRADE_HERRING)
1222 play_sound(sounds[SND_HERRING]);
1223 tux_invincible_time = TUX_INVINCIBLE_TIME;
1224 super_bkgd_time = 4;
1225 /* play the herring song ^^ */
1226 current_music = HERRING_MUSIC;
1227 if (playing_music())
1229 play_music( herring_song, 1 );
1237 /* Handle bad guys: */
1239 for (i = 0; i < NUM_BAD_GUYS; i++)
1241 if (bad_guys[i].alive)
1243 if (bad_guys[i].seen)
1245 if (bad_guys[i].kind == BAD_BSOD)
1247 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1249 /* Move left/right: */
1251 if (bad_guys[i].dying == NO ||
1252 bad_guys[i].dying == FALLING)
1254 if (bad_guys[i].dir == RIGHT)
1255 bad_guys[i].x = bad_guys[i].x + 4;
1256 else if (bad_guys[i].dir == LEFT)
1257 bad_guys[i].x = bad_guys[i].x - 4;
1261 /* Move vertically: */
1263 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1266 /* Bump into things horizontally: */
1268 if (!bad_guys[i].dying)
1270 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1271 bad_guys[i].dir = !bad_guys[i].dir;
1275 /* Bump into other bad guys: */
1277 for (j = 0; j < NUM_BAD_GUYS; j++)
1279 if (j != i && bad_guys[j].alive &&
1280 !bad_guys[j].dying && !bad_guys[i].dying &&
1281 bad_guys[i].x >= bad_guys[j].x - 32 &&
1282 bad_guys[i].x <= bad_guys[j].x + 32 &&
1283 bad_guys[i].y >= bad_guys[j].y - 32 &&
1284 bad_guys[i].y <= bad_guys[j].y + 32)
1286 bad_guys[i].dir = !bad_guys[i].dir;
1291 /* Fall if we get off the ground: */
1293 if (bad_guys[i].dying != FALLING)
1295 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1296 bad_guys[i].ym < MAX_YM)
1298 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1304 if (bad_guys[i].ym > 0)
1306 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1312 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1314 if (bad_guys[i].y > 480)
1315 bad_guys[i].alive = NO;
1317 else if (bad_guys[i].kind == BAD_LAPTOP)
1319 /* --- LAPTOP MONSTER: --- */
1321 /* Move left/right: */
1323 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1325 if (bad_guys[i].dying == NO ||
1326 bad_guys[i].dying == FALLING)
1328 if (bad_guys[i].dir == RIGHT)
1329 bad_guys[i].x = bad_guys[i].x + 4;
1330 else if (bad_guys[i].dir == LEFT)
1331 bad_guys[i].x = bad_guys[i].x - 4;
1334 else if (bad_guys[i].mode == KICK)
1336 if (bad_guys[i].dir == RIGHT)
1337 bad_guys[i].x = bad_guys[i].x + 16;
1338 else if (bad_guys[i].dir == LEFT)
1339 bad_guys[i].x = bad_guys[i].x - 16;
1343 /* Move vertically: */
1345 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1348 /* Bump into things horizontally: */
1350 if (!bad_guys[i].dying)
1352 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1354 bad_guys[i].dir = !bad_guys[i].dir;
1356 if (bad_guys[i].mode == KICK)
1357 play_sound(sounds[SND_RICOCHET]);
1362 /* Bump into other bad guys: */
1364 for (j = 0; j < NUM_BAD_GUYS; j++)
1366 if (j != i && bad_guys[j].alive &&
1367 !bad_guys[j].dying && !bad_guys[i].dying &&
1368 bad_guys[i].x >= bad_guys[j].x - 32 &&
1369 bad_guys[i].x <= bad_guys[j].x + 32 &&
1370 bad_guys[i].y >= bad_guys[j].y - 32 &&
1371 bad_guys[i].y <= bad_guys[j].y + 32)
1373 if (bad_guys[i].mode != KICK)
1374 bad_guys[i].dir = !bad_guys[i].dir;
1377 /* We're in kick mode, kill the other guy: */
1379 bad_guys[j].dying = FALLING;
1380 bad_guys[j].ym = -8;
1381 play_sound(sounds[SND_FALL]);
1383 add_score(bad_guys[i].x - scroll_x,
1384 bad_guys[i].y, 100);
1390 /* Fall if we get off the ground: */
1392 if (bad_guys[i].dying != FALLING)
1394 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1395 bad_guys[i].ym < MAX_YM)
1397 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1403 if (bad_guys[i].ym > 0)
1405 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1411 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1413 if (bad_guys[i].y > 480)
1414 bad_guys[i].alive = NO;
1416 else if (bad_guys[i].kind == BAD_MONEY)
1418 /* --- MONEY BAGS: --- */
1421 /* Move vertically: */
1423 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1426 /* Fall if we get off the ground: */
1428 if (bad_guys[i].dying != FALLING)
1430 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1432 if (bad_guys[i].ym < MAX_YM)
1434 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1441 if (bad_guys[i].ym > 0)
1443 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1444 bad_guys[i].ym = -MAX_YM;
1449 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1451 if (bad_guys[i].y > 480)
1452 bad_guys[i].alive = NO;
1454 else if (bad_guys[i].kind == -1)
1458 /* Kill it if the player jumped on it: */
1460 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1461 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1462 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1463 tux_y >= bad_guys[i].y - 32 &&
1464 tux_y <= bad_guys[i].y - 8
1468 if (bad_guys[i].kind == BAD_BSOD)
1470 bad_guys[i].dying = SQUISHED;
1471 bad_guys[i].timer = 16;
1472 tux_ym = -KILL_BOUNCE_YM;
1474 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1475 50 * score_multiplier);
1477 play_sound(sounds[SND_SQUISH]);
1479 else if (bad_guys[i].kind == BAD_LAPTOP)
1481 if (bad_guys[i].mode != FLAT)
1485 bad_guys[i].mode = FLAT;
1487 bad_guys[i].timer = 64;
1495 bad_guys[i].mode = KICK;
1497 if (tux_x + scroll_x <= bad_guys[i].x)
1498 bad_guys[i].dir = RIGHT;
1500 bad_guys[i].dir = LEFT;
1502 bad_guys[i].timer = 8;
1505 tux_ym = -KILL_BOUNCE_YM;
1507 add_score(bad_guys[i].x - scroll_x,
1509 25 * score_multiplier);
1511 /* play_sound(sounds[SND_SQUISH]); */
1513 else if (bad_guys[i].kind == -1)
1520 /* Hurt the player if he just touched it: */
1522 if (!bad_guys[i].dying && !tux_dying &&
1524 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1525 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1526 tux_y >= bad_guys[i].y - 32 &&
1527 tux_y <= bad_guys[i].y + 32)
1529 if (bad_guys[i].mode == FLAT)
1533 bad_guys[i].mode = KICK;
1535 if (tux_x + scroll_x <= bad_guys[i].x)
1537 bad_guys[i].dir = RIGHT;
1538 bad_guys[i].x = bad_guys[i].x + 16;
1542 bad_guys[i].dir = LEFT;
1543 bad_guys[i].x = bad_guys[i].x - 16;
1546 bad_guys[i].timer = 8;
1548 else if (bad_guys[i].mode == KICK)
1550 if (tux_y < bad_guys[i].y - 16 &&
1551 bad_guys[i].timer == 0)
1553 /* Step on (stop being kicked) */
1555 bad_guys[i].mode = FLAT;
1556 bad_guys[i].timer = 64;
1560 /* Hurt if you get hit by kicked laptop: */
1562 if (bad_guys[i].timer == 0)
1564 if (tux_invincible_time == 0)
1570 bad_guys[i].dying = FALLING;
1571 bad_guys[i].ym = -8;
1572 play_sound(sounds[SND_FALL]);
1579 if (tux_invincible_time == 0)
1585 bad_guys[i].dying = FALLING;
1586 bad_guys[i].ym = -8;
1587 play_sound(sounds[SND_FALL]);
1593 /* Handle mode timer: */
1595 if (bad_guys[i].mode == FLAT)
1597 bad_guys[i].timer--;
1599 if (bad_guys[i].timer <= 0)
1600 bad_guys[i].mode = NORMAL;
1602 else if (bad_guys[i].mode == KICK)
1604 if (bad_guys[i].timer > 0)
1605 bad_guys[i].timer--;
1609 /* Handle dying timer: */
1611 if (bad_guys[i].dying == SQUISHED)
1613 bad_guys[i].timer--;
1616 /* Remove it if time's up: */
1618 if (bad_guys[i].timer <= 0)
1619 bad_guys[i].alive = NO;
1623 /* Remove if it's far off the screen: */
1625 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1626 bad_guys[i].alive = NO;
1630 /* Once it's on screen, it's activated! */
1632 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1633 bad_guys[i].seen = YES;
1639 /* Handle skidding: */
1641 if (tux_skidding > 0)
1649 /* --- GAME DRAW! --- */
1657 if (tux_dying && (frame % 4) == 0)
1658 clearscreen(255, 255, 255);
1661 if (super_bkgd_time == 0)
1662 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1664 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1668 /* Draw background: */
1670 for (y = 0; y < 15; y++)
1672 for (x = 0; x < 21; x++)
1674 drawshape(x * 32 - (scroll_x % 32), y * 32,
1675 tiles[y][x + (scroll_x / 32)]);
1680 /* (Bouncy bricks): */
1682 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1684 if (bouncy_bricks[i].alive)
1686 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1687 bouncy_bricks[i].x <= scroll_x + 640)
1689 dest.x = bouncy_bricks[i].x - scroll_x;
1690 dest.y = bouncy_bricks[i].y;
1694 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1699 drawshape(bouncy_bricks[i].x - scroll_x,
1700 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1701 bouncy_bricks[i].shape);
1709 for (i = 0; i < NUM_BAD_GUYS; i++)
1711 if (bad_guys[i].alive &&
1712 bad_guys[i].x > scroll_x - 32 &&
1713 bad_guys[i].x < scroll_x + 640)
1715 if (bad_guys[i].kind == BAD_BSOD)
1717 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1719 if (bad_guys[i].dying == NO)
1723 if (bad_guys[i].dir == LEFT)
1725 drawimage(img_bsod_left[(frame / 5) % 4],
1726 bad_guys[i].x - scroll_x,
1732 drawimage(img_bsod_right[(frame / 5) % 4],
1733 bad_guys[i].x - scroll_x,
1738 else if (bad_guys[i].dying == FALLING)
1742 if (bad_guys[i].dir == LEFT)
1744 drawimage(img_bsod_falling_left,
1745 bad_guys[i].x - scroll_x,
1751 drawimage(img_bsod_falling_right,
1752 bad_guys[i].x - scroll_x,
1757 else if (bad_guys[i].dying == SQUISHED)
1759 /* Dying - Squished: */
1761 if (bad_guys[i].dir == LEFT)
1763 drawimage(img_bsod_squished_left,
1764 bad_guys[i].x - scroll_x,
1770 drawimage(img_bsod_squished_right,
1771 bad_guys[i].x - scroll_x,
1777 else if (bad_guys[i].kind == BAD_LAPTOP)
1779 /* --- LAPTOP MONSTER: --- */
1781 if (bad_guys[i].dying == NO)
1785 if (bad_guys[i].mode == NORMAL)
1789 if (bad_guys[i].dir == LEFT)
1791 drawimage(img_laptop_left[(frame / 5) % 3],
1792 bad_guys[i].x - scroll_x,
1798 drawimage(img_laptop_right[(frame / 5) % 3],
1799 bad_guys[i].x - scroll_x,
1808 if (bad_guys[i].dir == LEFT)
1810 drawimage(img_laptop_flat_left,
1811 bad_guys[i].x - scroll_x,
1817 drawimage(img_laptop_flat_right,
1818 bad_guys[i].x - scroll_x,
1824 else if (bad_guys[i].dying == FALLING)
1828 if (bad_guys[i].dir == LEFT)
1830 drawimage(img_laptop_falling_left,
1831 bad_guys[i].x - scroll_x,
1837 drawimage(img_laptop_falling_right,
1838 bad_guys[i].x - scroll_x,
1844 else if (bad_guys[i].kind == BAD_MONEY)
1846 if (bad_guys[i].ym > -16)
1848 if (bad_guys[i].dir == LEFT)
1850 drawimage(img_money_left[0],
1851 bad_guys[i].x - scroll_x,
1857 drawimage(img_money_right[0],
1858 bad_guys[i].x - scroll_x,
1865 if (bad_guys[i].dir == LEFT)
1867 drawimage(img_money_left[1],
1868 bad_guys[i].x - scroll_x,
1874 drawimage(img_money_right[1],
1875 bad_guys[i].x - scroll_x,
1881 else if (bad_guys[i].kind == -1)
1889 if (right == UP && left == UP)
1896 if ((fire == DOWN && (frame % 2) == 0) ||
1898 tux_frame_main = (tux_frame_main + 1) % 4;
1900 tux_frame = tux_frame_main;
1907 if (tux_got_coffee && (frame % 2) == 1)
1911 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1915 if (tux_safe == 0 || (frame % 2) == 0)
1917 if (tux_size == SMALL)
1919 if (tux_invincible_time)
1923 if (tux_dir == RIGHT)
1925 drawimage(cape_right[frame % 2],
1931 drawimage(cape_left[frame % 2],
1938 if (tux_dir == RIGHT)
1940 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1944 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1949 if (tux_invincible_time)
1953 if (tux_dir == RIGHT)
1955 drawimage(bigcape_right[frame % 2],
1956 tux_x - 8 - 16, tux_y - 32,
1961 drawimage(bigcape_left[frame % 2],
1962 tux_x - 8, tux_y - 32,
1971 if (!jumping || tux_ym > 0)
1973 if (tux_dir == RIGHT)
1975 drawimage(bigtux_right[tux_frame],
1976 tux_x - 8, tux_y - 32,
1981 drawimage(bigtux_left[tux_frame],
1982 tux_x - 8, tux_y - 32,
1988 if (tux_dir == RIGHT)
1990 drawimage(bigtux_right_jump,
1991 tux_x - 8, tux_y - 32,
1996 drawimage(bigtux_left_jump,
1997 tux_x - 8, tux_y - 32,
2004 if (tux_dir == RIGHT)
2006 drawimage(skidtux_right,
2007 tux_x - 8, tux_y - 32,
2012 drawimage(skidtux_left,
2013 tux_x - 8, tux_y - 32,
2020 if (tux_dir == RIGHT)
2022 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2027 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2037 for (i = 0; i < NUM_BULLETS; i++)
2039 if (bullets[i].alive &&
2040 bullets[i].x >= scroll_x - 4 &&
2041 bullets[i].x <= scroll_x + 640)
2043 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2049 /* (Floating scores): */
2051 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2053 if (floating_scores[i].alive)
2055 sprintf(str, "%d", floating_scores[i].value);
2057 floating_scores[i].x + 16 - strlen(str) * 8,
2058 floating_scores[i].y,
2059 letters_gold, NO_UPDATE);
2066 for (i = 0; i < NUM_UPGRADES; i++)
2068 if (upgrades[i].alive)
2070 if (upgrades[i].height < 32)
2074 dest.x = upgrades[i].x - scroll_x;
2075 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2077 dest.h = upgrades[i].height;
2082 src.h = upgrades[i].height;
2084 if (upgrades[i].kind == UPGRADE_MINTS)
2085 SDL_BlitSurface(img_mints, &src, screen, &dest);
2086 else if (upgrades[i].kind == UPGRADE_COFFEE)
2087 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2088 else if (upgrades[i].kind == UPGRADE_HERRING)
2089 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2093 if (upgrades[i].kind == UPGRADE_MINTS)
2095 drawimage(img_mints,
2096 upgrades[i].x - scroll_x, upgrades[i].y,
2099 else if (upgrades[i].kind == UPGRADE_COFFEE)
2101 drawimage(img_coffee,
2102 upgrades[i].x - scroll_x, upgrades[i].y,
2105 else if (upgrades[i].kind == UPGRADE_HERRING)
2107 drawimage(img_golden_herring,
2108 upgrades[i].x - scroll_x, upgrades[i].y,
2116 /* (Bouncy distros): */
2118 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2120 if (bouncy_distros[i].alive)
2122 drawimage(img_distro[0],
2123 bouncy_distros[i].x - scroll_x,
2124 bouncy_distros[i].y,
2130 /* (Broken bricks): */
2132 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2134 if (broken_bricks[i].alive)
2136 src.x = rand() % 16;
2137 src.y = rand() % 16;
2141 dest.x = broken_bricks[i].x - scroll_x;
2142 dest.y = broken_bricks[i].y;
2146 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2153 sprintf(str, "%d", score);
2154 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2155 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2157 sprintf(str, "%d", highscore);
2158 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2159 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2161 if (time_left >= TIME_WARNING || (frame % 10) < 5)
2163 sprintf(str, "%d", time_left);
2164 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2165 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2168 sprintf(str, "%d", distros);
2169 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2170 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2172 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE);
2174 for(i=0; i < lives; ++i)
2176 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2180 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2185 /* (Update it all!) */
2192 /* --- GAME LOOP! --- */
2197 Uint32 last_time, now_time;
2201 clearscreen(0, 0, 0);
2205 /* Init the game: */
2213 highscore = load_hs();
2216 /* --- MAIN GAME LOOP!!! --- */
2228 last_time = SDL_GetTicks();
2232 /* Handle events: */
2238 /* Handle actions: */
2240 if(!game_pause && !show_menu)
2242 if (game_action() == 0)
2244 /* == 0: no more lives */
2245 /* == -1: continues */
2252 /*Draw the current scene to the screen */
2255 /* Keep playing music: */
2258 if (!playing_music())
2260 switch (current_music)
2263 if (time_left <= TIME_WARNING)
2264 play_music(level_song_fast, 1);
2266 play_music(level_song, 1);
2269 play_music(herring_song, 1);
2271 case HURRYUP_MUSIC: // keep the compiler happy
2272 case NO_MUSIC: // keep the compiler happy for the moment :-)
2278 /* Time stops in pause mode */
2279 if(game_pause || show_menu )
2284 /* Pause til next frame: */
2286 now_time = SDL_GetTicks();
2287 if (now_time < last_time + FPS)
2288 SDL_Delay(last_time + FPS - now_time);
2293 if ((frame % 10) == 0 && time_left > 0)
2297 /* Stop the music; it will start again, faster! */
2298 if (time_left == TIME_WARNING)
2305 while (!done && !quit);
2307 if (playing_music())
2318 /* Initialize the game stuff: */
2330 /* Load data for this level: */
2332 void loadlevel(void)
2343 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2344 bouncy_distros[i].alive = NO;
2346 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2347 broken_bricks[i].alive = NO;
2349 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2350 bouncy_bricks[i].alive = NO;
2352 for (i = 0; i < NUM_BAD_GUYS; i++)
2353 bad_guys[i].alive = NO;
2355 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2356 floating_scores[i].alive = NO;
2358 for (i = 0; i < NUM_UPGRADES; i++)
2359 upgrades[i].alive = NO;
2361 for (i = 0; i < NUM_BULLETS; i++)
2362 bullets[i].alive = NO;
2365 /* Load data file: */
2367 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2368 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2369 fi = fopen(filename, "r");
2380 /* Load header info: */
2385 strcpy(levelname, str);
2386 levelname[strlen(levelname)-1] = '\0';
2390 strcpy(leveltheme, str);
2391 leveltheme[strlen(leveltheme)-1] = '\0';
2395 /* (Time to beat level) */
2397 time_left = atoi(str);
2399 /* (Song file for this level) */
2400 fgets(str, sizeof(song_title), fi);
2401 strcpy(song_title, str);
2402 song_title[strlen(song_title)-1] = '\0';
2406 /* (Level background color) */
2408 bkgd_red = atoi(str);
2410 bkgd_green= atoi(str);
2412 bkgd_blue = atoi(str);
2416 level_width = atoi(str);
2419 /* Allocate some space for the line-reading! */
2421 line = (char *) malloc(sizeof(char) * (level_width + 5));
2424 fprintf(stderr, "Couldn't allocate space to load level data!");
2429 /* Load the level lines: */
2431 for (y = 0; y < 15; y++)
2433 if(fgets(line, level_width + 5, fi) == NULL)
2435 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2438 line[strlen(line) - 1] = '\0';
2439 tiles[y] = strdup(line);
2445 /* Activate bad guys: */
2447 for (y = 0; y < 15; y++)
2449 for (x = 0; x < level_width; x++)
2451 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2453 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2468 tux_got_coffee = NO;
2469 tux_invincible_time = 0;
2473 tux_safe = TUX_SAFE_TIME;
2489 score_multiplier = 1;
2490 super_bkgd_time = 0;
2492 counting_distros = NO;
2497 /* set current song/music */
2498 current_music = LEVEL_MUSIC;
2502 clearscreen(0, 0, 0);
2504 sprintf(str, "LEVEL %d", level);
2505 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2507 sprintf(str, "%s", levelname);
2508 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2510 sprintf(str, "TUX x %d", lives);
2511 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2521 /* Load a level-specific graphic... */
2523 SDL_Surface * load_level_image(char * file, int use_alpha)
2527 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2529 return(load_image(fname, use_alpha));
2533 /* Load graphics: */
2535 void loadlevelgfx(void)
2537 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2538 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2540 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2541 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2542 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2543 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2545 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2546 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2547 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2548 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2550 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2551 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2552 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2553 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2559 void loadlevelsong(void)
2563 char * song_subtitle;
2565 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2566 strlen(song_title) + 8));
2567 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2568 level_song = load_song(song_path);
2572 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2573 strlen(song_title) + 8 + 5));
2574 song_subtitle = strdup(song_title);
2575 strcpy(strstr(song_subtitle, "."), "\0");
2576 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(song_title, "."));
2577 level_song_fast = load_song(song_path);
2578 free(song_subtitle);
2583 /* Free graphics data for this level: */
2585 void unloadlevelgfx(void)
2589 for (i = 0; i < 2; i++)
2591 SDL_FreeSurface(img_brick[i]);
2593 for (i = 0; i < 4; i++)
2595 SDL_FreeSurface(img_solid[i]);
2596 SDL_FreeSurface(img_bkgd[0][i]);
2597 SDL_FreeSurface(img_bkgd[1][i]);
2602 /* Free music data for this level: */
2604 void unloadlevelsong(void)
2606 free_music(level_song);
2610 /* Load graphics/sounds shared between all levels: */
2612 void loadshared(void)
2615 char * herring_song_path; /* for loading herring song*/
2619 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2622 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2625 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2628 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2631 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2634 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2637 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2640 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2643 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2646 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2649 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2652 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2655 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2659 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2661 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2664 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2667 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2671 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2674 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2678 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2682 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2686 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2689 ducktux_right = load_image(DATA_PREFIX
2690 "/images/shared/ducktux-right.png",
2693 ducktux_left = load_image(DATA_PREFIX
2694 "/images/shared/ducktux-left.png",
2697 skidtux_right = load_image(DATA_PREFIX
2698 "/images/shared/skidtux-right.png",
2701 skidtux_left = load_image(DATA_PREFIX
2702 "/images/shared/skidtux-left.png",
2708 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2710 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2717 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2719 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2722 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2725 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2731 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2732 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2738 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2740 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2746 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2749 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2752 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2755 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2759 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2762 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2765 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2768 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2776 img_bsod_left[0] = load_image(DATA_PREFIX
2777 "/images/shared/bsod-left-0.png",
2780 img_bsod_left[1] = load_image(DATA_PREFIX
2781 "/images/shared/bsod-left-1.png",
2784 img_bsod_left[2] = load_image(DATA_PREFIX
2785 "/images/shared/bsod-left-2.png",
2788 img_bsod_left[3] = load_image(DATA_PREFIX
2789 "/images/shared/bsod-left-3.png",
2792 img_bsod_right[0] = load_image(DATA_PREFIX
2793 "/images/shared/bsod-right-0.png",
2796 img_bsod_right[1] = load_image(DATA_PREFIX
2797 "/images/shared/bsod-right-1.png",
2800 img_bsod_right[2] = load_image(DATA_PREFIX
2801 "/images/shared/bsod-right-2.png",
2804 img_bsod_right[3] = load_image(DATA_PREFIX
2805 "/images/shared/bsod-right-3.png",
2808 img_bsod_squished_left = load_image(DATA_PREFIX
2809 "/images/shared/bsod-squished-left.png",
2812 img_bsod_squished_right = load_image(DATA_PREFIX
2813 "/images/shared/bsod-squished-right.png",
2816 img_bsod_falling_left = load_image(DATA_PREFIX
2817 "/images/shared/bsod-falling-left.png",
2820 img_bsod_falling_right = load_image(DATA_PREFIX
2821 "/images/shared/bsod-falling-right.png",
2827 img_laptop_left[0] = load_image(DATA_PREFIX
2828 "/images/shared/laptop-left-0.png",
2831 img_laptop_left[1] = load_image(DATA_PREFIX
2832 "/images/shared/laptop-left-1.png",
2835 img_laptop_left[2] = load_image(DATA_PREFIX
2836 "/images/shared/laptop-left-2.png",
2839 img_laptop_right[0] = load_image(DATA_PREFIX
2840 "/images/shared/laptop-right-0.png",
2843 img_laptop_right[1] = load_image(DATA_PREFIX
2844 "/images/shared/laptop-right-1.png",
2847 img_laptop_right[2] = load_image(DATA_PREFIX
2848 "/images/shared/laptop-right-2.png",
2851 img_laptop_flat_left = load_image(DATA_PREFIX
2852 "/images/shared/laptop-flat-left.png",
2855 img_laptop_flat_right = load_image(DATA_PREFIX
2856 "/images/shared/laptop-flat-right.png",
2859 img_laptop_falling_left =
2860 load_image(DATA_PREFIX
2861 "/images/shared/laptop-falling-left.png",
2864 img_laptop_falling_right =
2865 load_image(DATA_PREFIX
2866 "/images/shared/laptop-falling-right.png",
2872 img_money_left[0] = load_image(DATA_PREFIX
2873 "/images/shared/bag-left-0.png",
2876 img_money_left[1] = load_image(DATA_PREFIX
2877 "/images/shared/bag-left-1.png",
2880 img_money_right[0] = load_image(DATA_PREFIX
2881 "/images/shared/bag-right-0.png",
2884 img_money_right[1] = load_image(DATA_PREFIX
2885 "/images/shared/bag-right-1.png",
2892 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2893 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2898 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2900 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2906 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2909 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2912 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2915 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2920 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
2925 img_golden_herring =
2926 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2930 /* Super background: */
2932 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2936 /* Sound effects: */
2938 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
2939 // initialize sounds[i] with the correct pointer's value:
2940 // NULL or something else. And it will be dangerous to
2941 // play with not-initialized pointers.
2942 // This is also true with if (use_music)
2943 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
2945 for (i = 0; i < NUM_SOUNDS; i++)
2946 sounds[i] = load_sound(soundfilenames[i]);
2949 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2950 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
2952 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
2954 herring_song = load_song(herring_song_path);
2956 free(herring_song_path);
2961 /* Free shared data: */
2963 void unloadshared(void)
2967 for (i = 0; i < 3; i++)
2969 SDL_FreeSurface(tux_right[i]);
2970 SDL_FreeSurface(tux_left[i]);
2971 SDL_FreeSurface(bigtux_right[i]);
2972 SDL_FreeSurface(bigtux_left[i]);
2975 SDL_FreeSurface(bigtux_right_jump);
2976 SDL_FreeSurface(bigtux_left_jump);
2978 for (i = 0; i < 2; i++)
2980 SDL_FreeSurface(cape_right[i]);
2981 SDL_FreeSurface(cape_left[i]);
2982 SDL_FreeSurface(bigcape_right[i]);
2983 SDL_FreeSurface(bigcape_left[i]);
2986 SDL_FreeSurface(ducktux_left);
2987 SDL_FreeSurface(ducktux_right);
2989 SDL_FreeSurface(skidtux_left);
2990 SDL_FreeSurface(skidtux_right);
2992 for (i = 0; i < 4; i++)
2994 SDL_FreeSurface(img_bsod_left[i]);
2995 SDL_FreeSurface(img_bsod_right[i]);
2998 SDL_FreeSurface(img_bsod_squished_left);
2999 SDL_FreeSurface(img_bsod_squished_right);
3001 SDL_FreeSurface(img_bsod_falling_left);
3002 SDL_FreeSurface(img_bsod_falling_right);
3004 for (i = 0; i < 3; i++)
3006 SDL_FreeSurface(img_laptop_left[i]);
3007 SDL_FreeSurface(img_laptop_right[i]);
3010 SDL_FreeSurface(img_laptop_flat_left);
3011 SDL_FreeSurface(img_laptop_flat_right);
3013 SDL_FreeSurface(img_laptop_falling_left);
3014 SDL_FreeSurface(img_laptop_falling_right);
3016 for (i = 0; i < 2; i++)
3018 SDL_FreeSurface(img_money_left[i]);
3019 SDL_FreeSurface(img_money_right[i]);
3022 SDL_FreeSurface(img_box_full);
3023 SDL_FreeSurface(img_box_empty);
3025 SDL_FreeSurface(img_water);
3026 for (i = 0; i < 3; i++)
3027 SDL_FreeSurface(img_waves[i]);
3029 SDL_FreeSurface(img_pole);
3030 SDL_FreeSurface(img_poletop);
3032 for (i = 0; i < 2; i++)
3033 SDL_FreeSurface(img_flag[i]);
3035 SDL_FreeSurface(img_mints);
3036 SDL_FreeSurface(img_coffee);
3038 for (i = 0; i < 4; i++)
3040 SDL_FreeSurface(img_distro[i]);
3041 SDL_FreeSurface(img_cloud[0][i]);
3042 SDL_FreeSurface(img_cloud[1][i]);
3045 SDL_FreeSurface(img_golden_herring);
3047 for (i = 0; i < NUM_SOUNDS; i++)
3048 free_chunk(sounds[i]);
3050 /* free the herring song */
3051 free_music( herring_song );
3055 /* Draw a tile on the screen: */
3057 void drawshape(int x, int y, unsigned char c)
3061 if (c == 'X' || c == 'x')
3062 drawimage(img_brick[0], x, y, NO_UPDATE);
3063 else if (c == 'Y' || c == 'y')
3064 drawimage(img_brick[1], x, y, NO_UPDATE);
3065 else if (c == 'A' || c =='B' || c == '!')
3066 drawimage(img_box_full, x, y, NO_UPDATE);
3068 drawimage(img_box_empty, x, y, NO_UPDATE);
3069 else if (c >= 'C' && c <= 'F')
3070 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3071 else if (c >= 'c' && c <= 'f')
3072 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3073 else if (c >= 'G' && c <= 'J')
3074 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3075 else if (c >= 'g' && c <= 'j')
3076 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3078 drawimage(img_solid[0], x, y, NO_UPDATE);
3080 drawimage(img_solid[1], x, y, NO_UPDATE);
3082 drawimage(img_solid[2], x, y, NO_UPDATE);
3084 drawimage(img_solid[3], x, y, NO_UPDATE);
3087 z = (frame / 2) % 6;
3090 drawimage(img_distro[z], x, y, NO_UPDATE);
3092 drawimage(img_distro[2], x, y, NO_UPDATE);
3094 drawimage(img_distro[1], x, y, NO_UPDATE);
3098 z = (frame / 3) % 3;
3100 drawimage(img_waves[z], x, y, NO_UPDATE);
3103 drawimage(img_poletop, x, y, NO_UPDATE);
3106 drawimage(img_pole, x, y, NO_UPDATE);
3108 /* Mark this as the end position of the level! */
3114 z = (frame / 3) % 2;
3116 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3119 drawimage(img_water, x, y, NO_UPDATE);
3123 /* What shape is at some position? */
3125 unsigned char shape(int x, int y, int sx)
3131 xx = ((x + sx) / 32);
3133 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3144 int issolid(int x, int y, int sx)
3150 if (isbrick(x, y, sx) ||
3151 isbrick(x + 31, y, sx) ||
3153 isice(x + 31, y, sx) ||
3154 (shape(x, y, sx) == '[' ||
3155 shape(x + 31, y, sx) == '[') ||
3156 (shape(x, y, sx) == '=' ||
3157 shape(x + 31, y, sx) == '=') ||
3158 (shape(x, y, sx) == ']' ||
3159 shape(x + 31, y, sx) == ']') ||
3160 (shape(x, y, sx) == 'A' ||
3161 shape(x + 31, y, sx) == 'A') ||
3162 (shape(x, y, sx) == 'B' ||
3163 shape(x + 31, y, sx) == 'B') ||
3164 (shape(x, y, sx) == '!' ||
3165 shape(x + 31, y, sx) == '!') ||
3166 (shape(x, y, sx) == 'a' ||
3167 shape(x + 31, y, sx) == 'a'))
3176 /* Is it a brick? */
3178 int isbrick(int x, int y, int sx)
3184 if (shape(x, y, sx) == 'X' ||
3185 shape(x, y, sx) == 'x' ||
3186 shape(x, y, sx) == 'Y' ||
3187 shape(x, y, sx) == 'y')
3198 int isice(int x, int y, int sx)
3204 if (shape(x, y, sx) == '#')
3213 /* Is it a full box? */
3215 int isfullbox(int x, int y, int sx)
3221 if (shape(x, y, sx) == 'A' ||
3222 shape(x, y, sx) == 'B' ||
3223 shape(x, y, sx) == '!')
3232 /* Edit a piece of the map! */
3234 void change(int x, int y, int sx, unsigned char c)
3239 xx = ((x + sx) / 32);
3241 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3246 /* Break a brick: */
3248 void trybreakbrick(int x, int y, int sx)
3250 if (isbrick(x, y, sx))
3252 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3254 /* Get a distro from it: */
3256 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3259 if (counting_distros == NO)
3261 counting_distros = YES;
3262 distro_counter = 50;
3265 if (distro_counter <= 0)
3266 change(x, y, sx, 'a');
3268 play_sound(sounds[SND_DISTRO]);
3269 score = score + SCORE_DISTRO;
3274 /* Get rid of it: */
3276 change(x, y, sx, '.');
3280 /* Replace it with broken bits: */
3282 add_broken_brick(((x + sx + 1) / 32) * 32,
3286 /* Get some score: */
3288 play_sound(sounds[SND_BRICK]);
3289 score = score + SCORE_BRICK;
3294 /* Bounce a brick: */
3296 void bumpbrick(int x, int y, int sx)
3298 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3301 play_sound(sounds[SND_BRICK]);
3307 void tryemptybox(int x, int y, int sx)
3309 if (isfullbox(x, y, sx))
3311 if (shape(x, y, sx) == 'A')
3313 /* Box with a distro! */
3315 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3316 (y / 32) * 32 - 32);
3318 play_sound(sounds[SND_DISTRO]);
3319 score = score + SCORE_DISTRO;
3322 else if (shape(x, y, sx) == 'B')
3324 /* Add an upgrade! */
3326 if (tux_size == SMALL)
3328 /* Tux is small, add mints! */
3330 add_upgrade(((x + sx + 1) / 32) * 32,
3336 /* Tux is big, add coffee: */
3338 add_upgrade(((x + sx + 1) / 32) * 32,
3343 play_sound(sounds[SND_UPGRADE]);
3345 else if (shape(x, y, sx) == '!')
3347 /* Add a golden herring */
3349 add_upgrade(((x + sx + 1) / 32) * 32,
3354 /* Empty the box: */
3356 change(x, y, sx, 'a');
3361 /* Try to grab a distro: */
3363 void trygrabdistro(int x, int y, int sx, int bounciness)
3365 if (shape(x, y, sx) == '$')
3367 change(x, y, sx, '.');
3368 play_sound(sounds[SND_DISTRO]);
3370 if (bounciness == BOUNCE)
3372 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3376 score = score + SCORE_DISTRO;
3382 /* Add a bouncy distro: */
3384 void add_bouncy_distro(int x, int y)
3390 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3392 if (!bouncy_distros[i].alive)
3398 bouncy_distros[found].alive = YES;
3399 bouncy_distros[found].x = x;
3400 bouncy_distros[found].y = y;
3401 bouncy_distros[found].ym = -6;
3406 /* Add broken brick pieces: */
3408 void add_broken_brick(int x, int y)
3410 add_broken_brick_piece(x, y, -4, -16);
3411 add_broken_brick_piece(x, y + 16, -6, -12);
3413 add_broken_brick_piece(x + 16, y, 4, -16);
3414 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3418 /* Add a broken brick piece: */
3420 void add_broken_brick_piece(int x, int y, int xm, int ym)
3426 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3428 if (!broken_bricks[i].alive)
3434 broken_bricks[found].alive = YES;
3435 broken_bricks[found].x = x;
3436 broken_bricks[found].y = y;
3437 broken_bricks[found].xm = xm;
3438 broken_bricks[found].ym = ym;
3443 /* Add a bouncy brick piece: */
3445 void add_bouncy_brick(int x, int y)
3451 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3453 if (!bouncy_bricks[i].alive)
3459 bouncy_bricks[found].alive = YES;
3460 bouncy_bricks[found].x = x;
3461 bouncy_bricks[found].y = y;
3462 bouncy_bricks[found].offset = 0;
3463 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3464 bouncy_bricks[found].shape = shape(x, y, 0);
3469 /* Add a bad guy: */
3471 void add_bad_guy(int x, int y, int kind)
3477 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3479 if (!bad_guys[i].alive)
3485 bad_guys[found].alive = YES;
3486 bad_guys[found].mode = NORMAL;
3487 bad_guys[found].dying = NO;
3488 bad_guys[found].timer = 0;
3489 bad_guys[found].kind = kind;
3490 bad_guys[found].x = x;
3491 bad_guys[found].y = y;
3492 bad_guys[found].xm = 0;
3493 bad_guys[found].ym = 0;
3494 bad_guys[found].dir = LEFT;
3495 bad_guys[found].seen = NO;
3502 void add_score(int x, int y, int s)
3507 /* Add the score: */
3512 /* Add a floating score thing to the game: */
3516 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3518 if (!floating_scores[i].alive)
3525 floating_scores[found].alive = YES;
3526 floating_scores[found].x = x;
3527 floating_scores[found].y = y - 16;
3528 floating_scores[found].timer = 8;
3529 floating_scores[found].value = s;
3534 /* Try to bump a bad guy from below: */
3536 void trybumpbadguy(int x, int y, int sx)
3543 for (i = 0; i < NUM_BAD_GUYS; i++)
3545 if (bad_guys[i].alive &&
3546 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3547 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3549 if (bad_guys[i].kind == BAD_BSOD ||
3550 bad_guys[i].kind == BAD_LAPTOP)
3552 bad_guys[i].dying = FALLING;
3553 bad_guys[i].ym = -8;
3554 play_sound(sounds[SND_FALL]);
3562 for (i = 0; i < NUM_UPGRADES; i++)
3564 if (upgrades[i].alive && upgrades[i].height == 32 &&
3565 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3566 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3568 upgrades[i].xm = -upgrades[i].xm;
3569 upgrades[i].ym = -8;
3570 play_sound(sounds[SND_BUMP_UPGRADE]);
3576 /* Add an upgrade: */
3578 void add_upgrade(int x, int y, int kind)
3584 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3586 if (!upgrades[i].alive)
3592 upgrades[found].alive = YES;
3593 upgrades[found].kind = kind;
3594 upgrades[found].x = x;
3595 upgrades[found].y = y;
3596 upgrades[found].xm = 4;
3597 upgrades[found].ym = -4;
3598 upgrades[found].height = 0;
3605 void killtux(int mode)
3609 play_sound(sounds[SND_HURT]);
3611 if (tux_dir == RIGHT)
3613 else if (tux_dir == LEFT)
3616 if (mode == SHRINK && tux_size == BIG)
3619 tux_got_coffee = NO;
3623 tux_safe = TUX_SAFE_TIME;
3634 void add_bullet(int x, int y, int dir, int xm)
3640 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3642 if (!bullets[i].alive)
3648 bullets[found].alive = YES;
3652 bullets[found].x = x + 32;
3653 bullets[found].xm = BULLET_XM + xm;
3657 bullets[found].x = x;
3658 bullets[found].xm = -BULLET_XM + xm;
3661 bullets[found].y = y;
3662 bullets[found].ym = BULLET_STARTING_YM;
3664 play_sound(sounds[SND_SHOOT]);
3669 void drawendscreen(void)
3673 clearscreen(0, 0, 0);
3675 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3677 sprintf(str, "SCORE: %d", score);
3678 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3680 sprintf(str, "DISTROS: %d", distros);
3681 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3687 void drawresultscreen(void)
3691 clearscreen(0, 0, 0);
3693 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3695 sprintf(str, "SCORE: %d", score);
3696 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3698 sprintf(str, "DISTROS: %d", distros);
3699 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3702 /*SDL_Delay(2000);*/