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_life,
105 * tux_right[3], * tux_left[3],
106 * bigtux_right[3], * bigtux_left[3],
107 * bigtux_right_jump, * bigtux_left_jump,
108 * ducktux_right, * ducktux_left,
109 * skidtux_right, * skidtux_left,
110 * firetux_right[3], * firetux_left[3],
111 * bigfiretux_right[3], * bigfiretux_left[3],
112 * bigfiretux_right_jump, * bigfiretux_left_jump,
113 * duckfiretux_right, * duckfiretux_left,
114 * skidfiretux_right, * skidfiretux_left,
115 * cape_right[2], * cape_left[2],
116 * bigcape_right[2], * bigcape_left[2];
120 unsigned char * tiles[15];
121 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
122 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
123 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
124 bad_guy_type bad_guys[NUM_BAD_GUYS];
125 floating_score_type floating_scores[NUM_FLOATING_SCORES];
126 upgrade_type upgrades[NUM_UPGRADES];
127 bullet_type bullets[NUM_BULLETS];
134 /* Local function prototypes: */
137 void loadlevel(void);
138 void loadlevelgfx(void);
139 void loadlevelsong(void);
140 void unloadlevelgfx(void);
141 void unloadlevelsong(void);
142 void loadshared(void);
143 void unloadshared(void);
144 void drawshape(int x, int y, unsigned char c);
146 unsigned char shape(int x, int y, int sx);
147 int issolid(int x, int y, int sx);
148 int isbrick(int x, int y, int sx);
149 int isice(int x, int y, int sx);
150 int isfullbox(int x, int y, int sx);
151 void change(int x, int y, int sx, unsigned char c);
152 void trybreakbrick(int x, int y, int sx);
153 void bumpbrick(int x, int y, int sx);
154 void tryemptybox(int x, int y, int sx);
155 void trygrabdistro(int x, int y, int sx, int bounciness);
156 void add_bouncy_distro(int x, int y);
157 void add_broken_brick(int x, int y);
158 void add_broken_brick_piece(int x, int y, int xm, int ym);
159 void add_bouncy_brick(int x, int y);
160 void add_bad_guy(int x, int y, int kind);
161 void add_score(int x, int y, int s);
162 void trybumpbadguy(int x, int y, int sx);
163 void add_upgrade(int x, int y, int kind);
164 void killtux(int mode);
165 void add_bullet(int x, int y, int dir, int xm);
166 void drawendscreen(void);
167 void drawresultscreen(void);
169 /* --- GAME EVENT! --- */
171 void game_event(void)
174 while (SDL_PollEvent(&event))
177 if (event.type == SDL_QUIT)
179 /* Quit event - quit: */
183 else if (event.type == SDL_KEYDOWN)
187 key = event.key.keysym.sym;
189 /* Check for menu-events, if the menu is shown */
193 if (key == SDLK_ESCAPE)
195 /* Escape: Open/Close the menu: */
204 else if (key == SDLK_RIGHT)
208 else if (key == SDLK_LEFT)
212 else if (key == SDLK_UP)
216 else if (key == SDLK_DOWN)
220 else if (key == SDLK_LCTRL)
225 else if (event.type == SDL_KEYUP)
229 key = event.key.keysym.sym;
231 if (key == SDLK_RIGHT)
235 else if (key == SDLK_LEFT)
239 else if (key == SDLK_UP)
243 else if (key == SDLK_DOWN)
247 else if (key == SDLK_LCTRL)
251 else if (key == SDLK_p)
261 else if (key == SDLK_TAB && debug_mode == YES)
263 tux_size = !tux_size;
265 else if (key == SDLK_END && debug_mode == YES)
269 else if (key == SDLK_SPACE && debug_mode == YES)
275 else if (event.type == SDL_JOYAXISMOTION)
277 if (event.jaxis.axis == JOY_X)
279 if (event.jaxis.value < -256)
284 if (event.jaxis.value > 256)
289 else if (event.jaxis.axis == JOY_Y)
291 if (event.jaxis.value > 256)
296 /* Handle joystick for the menu */
300 menuaction = MN_DOWN;
306 else if (event.type == SDL_JOYBUTTONDOWN)
308 if (event.jbutton.button == JOY_A)
310 else if (event.jbutton.button == JOY_B)
313 else if (event.type == SDL_JOYBUTTONUP)
315 if (event.jbutton.button == JOY_A)
317 else if (event.jbutton.button == JOY_B)
330 /* --- GAME ACTION! --- */
332 int game_action(void)
336 /* --- HANDLE TUX! --- */
338 /* Handle key and joystick state: */
340 if (!(tux_dying || next_level))
342 if (right == DOWN && left == UP)
346 if (tux_xm < -SKID_XM && !tux_skidding &&
349 tux_skidding = SKID_TIME;
351 play_sound(sounds[SND_SKID]);
357 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
365 if (tux_dir == RIGHT)
367 /* Facing the direction we're jumping? Go full-speed: */
371 tux_xm = tux_xm + WALK_SPEED;
373 if (tux_xm > MAX_WALK_XM)
374 tux_xm = MAX_WALK_XM;
376 else if (fire == DOWN)
378 tux_xm = tux_xm + RUN_SPEED;
380 if (tux_xm > MAX_RUN_XM)
386 /* Not facing the direction we're jumping?
389 tux_xm = tux_xm + WALK_SPEED / 2;
391 if (tux_xm > MAX_WALK_XM / 2)
392 tux_xm = MAX_WALK_XM / 2;
396 else if (left == DOWN && right == UP)
400 if (tux_xm > SKID_XM && !tux_skidding &&
403 tux_skidding = SKID_TIME;
404 play_sound(sounds[SND_SKID]);
409 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
419 /* Facing the direction we're jumping? Go full-speed: */
423 tux_xm = tux_xm - WALK_SPEED;
425 if (tux_xm < -MAX_WALK_XM)
426 tux_xm = -MAX_WALK_XM;
428 else if (fire == DOWN)
430 tux_xm = tux_xm - RUN_SPEED;
432 if (tux_xm < -MAX_RUN_XM)
433 tux_xm = -MAX_RUN_XM;
438 /* Not facing the direction we're jumping?
441 tux_xm = tux_xm - WALK_SPEED / 2;
443 if (tux_xm < -MAX_WALK_XM / 2)
444 tux_xm = -MAX_WALK_XM / 2;
452 if (tux_x >= endpos && endpos != 0)
462 if (jump_counter == 0)
466 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
469 /* If they're not on the ground, or are currently moving
470 vertically, don't jump! */
472 jump_counter = MAX_JUMP_COUNT;
476 /* Make sure we're not standing back up into a solid! */
478 if (tux_size == SMALL || tux_duck == NO ||
479 !issolid(tux_x, tux_y, scroll_x))
483 if (tux_size == SMALL)
484 play_sound(sounds[SND_JUMP]);
486 play_sound(sounds[SND_BIGJUMP]);
492 /* Keep jumping for a while: */
494 if (jump_counter < MAX_JUMP_COUNT)
496 tux_ym = tux_ym - JUMP_SPEED;
506 if (fire == DOWN && old_fire == UP && tux_got_coffee)
508 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
521 if (tux_size == BIG && tux_duck == YES)
523 /* Make sure we're not standing back up into a solid! */
525 if (!issolid(tux_x, tux_y - 32, scroll_x))
531 } /* (tux_dying || next_level) */
534 /* Tux either died, or reached the end of a level! */
543 /* End of a level! */
551 tux_ym = tux_ym + GRAVITY;
559 /* No more lives!? */
565 if (score > highscore)
572 } /* if (lives < 0) */
575 /* Either way, (re-)load the (next) level... */
586 tux_x = tux_x + tux_xm;
587 tux_y = tux_y + tux_ym;
590 /* Keep tux in bounds: */
593 else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
595 scroll_x = scroll_x - ( 160 - tux_x);
602 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
604 /* Scroll the screen in past center: */
606 scroll_x = scroll_x + (tux_x - 320);
609 if (scroll_x > ((level_width * 32) - 640))
610 scroll_x = ((level_width * 32) - 640);
612 else if (tux_x > 608)
614 /* ... unless there's no more to scroll! */
624 if (issolid(tux_x, tux_y + 31, scroll_x) &&
625 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
627 while (issolid(tux_x, tux_y + 31, scroll_x))
638 if (issolid(tux_x, tux_y, scroll_x) &&
639 !issolid(tux_x - tux_xm, tux_y, scroll_x))
641 while (issolid(tux_x, tux_y, scroll_x))
652 if (issolid(tux_x, tux_y + 31, scroll_x))
654 /* Set down properly: */
656 while (issolid(tux_x, tux_y + 31, scroll_x))
665 /* Reset score multiplier (for mutli-hits): */
668 score_multiplier = 1;
678 /* Bump into things: */
680 if (issolid(tux_x, tux_y, scroll_x) ||
681 (tux_size == BIG && !tux_duck &&
682 (issolid(tux_x, tux_y - 32, scroll_x))))
684 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
685 (tux_size == SMALL || tux_duck ||
686 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
688 tux_x = tux_x - tux_xm;
691 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
692 (tux_size == SMALL || tux_duck ||
693 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
701 /* Break bricks and empty boxes: */
705 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
706 isfullbox(tux_x, tux_y - 32, scroll_x))
708 trygrabdistro(tux_x, tux_y - 64, scroll_x,
710 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
712 if (isfullbox(tux_x, tux_y - 32,
715 bumpbrick(tux_x, tux_y - 32,
719 trybreakbrick(tux_x, tux_y - 32, scroll_x);
720 tryemptybox(tux_x, tux_y - 32, scroll_x);
723 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
724 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
726 trygrabdistro(tux_x + 31,
730 trybumpbadguy(tux_x + 31,
734 if (isfullbox(tux_x + 31, tux_y - 32,
737 bumpbrick(tux_x + 31, tux_y - 32,
741 trybreakbrick(tux_x + 31,
744 tryemptybox(tux_x + 31,
751 if (isbrick(tux_x, tux_y, scroll_x) ||
752 isfullbox(tux_x, tux_y, scroll_x))
754 trygrabdistro(tux_x, tux_y - 32, scroll_x,
756 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
757 if (isfullbox(tux_x, tux_y, scroll_x))
758 bumpbrick(tux_x, tux_y, scroll_x);
759 trybreakbrick(tux_x, tux_y, scroll_x);
760 tryemptybox(tux_x, tux_y, scroll_x);
763 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
764 isfullbox(tux_x + 31, tux_y, scroll_x))
766 trygrabdistro(tux_x + 31,
770 trybumpbadguy(tux_x + 31,
773 if (isfullbox(tux_x + 31, tux_y, scroll_x))
774 bumpbrick(tux_x + 31, tux_y, scroll_x);
775 trybreakbrick(tux_x + 31, tux_y, scroll_x);
776 tryemptybox(tux_x + 31, tux_y, scroll_x);
782 /* It's a brick and we're small, make the brick
783 bounce, and grab any distros above it: */
785 if (isbrick(tux_x, tux_y, scroll_x) ||
786 isfullbox(tux_x, tux_y, scroll_x))
788 trygrabdistro(tux_x, tux_y - 32, scroll_x,
790 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
791 bumpbrick(tux_x, tux_y, scroll_x);
792 tryemptybox(tux_x, tux_y, scroll_x);
795 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
796 isfullbox(tux_x + 31, tux_y, scroll_x))
798 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
800 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
801 bumpbrick(tux_x + 31, tux_y, scroll_x);
802 tryemptybox(tux_x + 31, tux_y, scroll_x);
806 /* Get a distro from a brick? */
808 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
809 shape(tux_x, tux_y, scroll_x) == 'y')
811 add_bouncy_distro(((tux_x + scroll_x + 1)
815 if (counting_distros == NO)
817 counting_distros = YES;
818 distro_counter = 100;
821 if (distro_counter <= 0)
822 change(tux_x, tux_y, scroll_x, 'a');
824 play_sound(sounds[SND_DISTRO]);
825 score = score + SCORE_DISTRO;
828 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
829 shape(tux_x + 31, tux_y, scroll_x) == 'y')
831 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
835 if (counting_distros == NO)
837 counting_distros = YES;
838 distro_counter = 100;
841 if (distro_counter <= 0)
842 change(tux_x + 31, tux_y, scroll_x, 'a');
844 play_sound(sounds[SND_DISTRO]);
845 score = score + SCORE_DISTRO;
853 tux_y = (tux_y / 32) * 32 + 30;
859 tux_y = (tux_y / 32) * 32 - 32;
864 jump_counter = MAX_JUMP_COUNT;
874 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
875 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
877 if (tux_size == BIG && !tux_duck)
879 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
880 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
885 /* Enough distros for a One-up? */
887 if (distros >= DISTROS_LIFEUP)
889 distros = distros - DISTROS_LIFEUP;
890 if(lives < MAX_LIVES)
892 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
896 /* Keep in-bounds, vertically: */
900 else if (tux_y > 480)
906 /* Slow down horizontally: */
910 if (right == UP && left == UP)
912 if (isice(tux_x, tux_y + 32, scroll_x) ||
913 !issolid(tux_x, tux_y + 32, scroll_x))
915 /* Slowly on ice or in air: */
924 /* Quickly, otherwise: */
931 /* Drop vertically: */
933 if (!issolid(tux_x, tux_y + 32, scroll_x))
935 tux_ym = tux_ym + GRAVITY;
947 /* ---- DONE HANDLING TUX! --- */
950 /* Handle bouncy distros: */
952 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
954 if (bouncy_distros[i].alive)
956 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
958 bouncy_distros[i].ym++;
960 if (bouncy_distros[i].ym >= 0)
961 bouncy_distros[i].alive = NO;
966 /* Handle broken bricks: */
968 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
970 if (broken_bricks[i].alive)
972 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
973 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
975 broken_bricks[i].ym++;
977 if (broken_bricks[i].ym >= 0)
978 broken_bricks[i].alive = NO;
983 /* Handle distro counting: */
985 if (counting_distros == YES)
989 if (distro_counter <= 0)
990 counting_distros = -1;
994 /* Handle bouncy bricks: */
996 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
998 if (bouncy_bricks[i].alive)
1000 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
1001 bouncy_bricks[i].offset_m);
1005 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
1006 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
1009 /* Stop bouncing? */
1011 if (bouncy_bricks[i].offset == 0)
1012 bouncy_bricks[i].alive = NO;
1017 /* Handle floating scores: */
1019 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1021 if (floating_scores[i].alive)
1023 floating_scores[i].y = floating_scores[i].y - 2;
1024 floating_scores[i].timer--;
1026 if (floating_scores[i].timer <= 0)
1027 floating_scores[i].alive = NO;
1032 /* Handle bullets: */
1034 for (i = 0; i < NUM_BULLETS; i++)
1036 if (bullets[i].alive)
1038 bullets[i].x = bullets[i].x + bullets[i].xm;
1039 bullets[i].y = bullets[i].y + bullets[i].ym;
1041 if (issolid(bullets[i].x, bullets[i].y, 0))
1043 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1044 bullets[i].alive = NO;
1047 if (bullets[i].ym >= 0)
1049 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1051 bullets[i].ym = -bullets[i].ym;
1055 bullets[i].ym = bullets[i].ym + GRAVITY;
1057 if (bullets[i].x < scroll_x ||
1058 bullets[i].x > scroll_x + 640)
1060 bullets[i].alive = NO;
1065 if (bullets[i].alive)
1067 for (j = 0; j < NUM_BAD_GUYS; j++)
1069 if (bad_guys[j].alive && !bad_guys[j].dying)
1071 if (bullets[i].x >= bad_guys[j].x - 4 &&
1072 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1073 bullets[i].y >= bad_guys[j].y - 4 &&
1074 bullets[i].y <= bad_guys[j].y + 32 + 4)
1076 /* Kill the bad guy! */
1078 bullets[i].alive = 0;
1079 bad_guys[j].dying = FALLING;
1080 bad_guys[j].ym = -8;
1083 /* Gain some points: */
1085 if (bad_guys[j].kind == BAD_BSOD)
1087 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1088 50 * score_multiplier);
1090 else if (bad_guys[j].kind == BAD_LAPTOP)
1092 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1093 25 * score_multiplier);
1097 /* Play death sound: */
1098 play_sound(sounds[SND_FALL]);
1106 /* Handle background timer: */
1108 if (super_bkgd_time)
1112 /* Handle invincibility timer: */
1115 if (tux_invincible_time > 50)
1117 tux_invincible_time--;
1120 if (!playing_music())
1121 play_music( herring_song, 1 );
1125 if (current_music == HERRING_MUSIC)
1127 /* stop the herring_song, now play the level_song ! */
1128 current_music = LEVEL_MUSIC;
1132 if (!playing_music())
1134 if (time_left <= TIME_WARNING)
1135 play_music( level_song_fast, 1 );
1137 play_music( level_song, 1 );
1140 if (tux_invincible_time > 0)
1141 tux_invincible_time--;
1145 /* Handle upgrades: */
1147 for (i = 0; i < NUM_UPGRADES; i++)
1149 if (upgrades[i].alive)
1151 if (upgrades[i].height < 32)
1155 upgrades[i].height++;
1161 if (upgrades[i].kind == UPGRADE_MINTS ||
1162 upgrades[i].kind == UPGRADE_HERRING)
1164 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1165 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1167 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1168 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1170 if (upgrades[i].ym > 0)
1172 if (upgrades[i].kind == UPGRADE_MINTS)
1176 else if (upgrades[i].kind == UPGRADE_HERRING)
1178 upgrades[i].ym = -24;
1181 upgrades[i].y = (upgrades[i].y / 32) * 32;
1185 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1187 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1189 upgrades[i].xm = -upgrades[i].xm;
1194 /* Off the screen? Kill it! */
1196 if (upgrades[i].x < scroll_x)
1197 upgrades[i].alive = NO;
1200 /* Did the player grab it? */
1202 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1203 tux_x + scroll_x <= upgrades[i].x + 32 &&
1204 tux_y >= upgrades[i].y - 32 &&
1205 tux_y <= upgrades[i].y + 32)
1207 /* Remove the upgrade: */
1209 upgrades[i].alive = NO;
1212 /* Affect the player: */
1214 if (upgrades[i].kind == UPGRADE_MINTS)
1216 play_sound(sounds[SND_EXCELLENT]);
1218 super_bkgd_time = 8;
1220 else if (upgrades[i].kind == UPGRADE_COFFEE)
1222 play_sound(sounds[SND_COFFEE]);
1223 tux_got_coffee = YES;
1224 super_bkgd_time = 4;
1226 else if (upgrades[i].kind == UPGRADE_HERRING)
1228 play_sound(sounds[SND_HERRING]);
1229 tux_invincible_time = TUX_INVINCIBLE_TIME;
1230 super_bkgd_time = 4;
1231 /* play the herring song ^^ */
1232 current_music = HERRING_MUSIC;
1233 if (playing_music())
1235 play_music( herring_song, 1 );
1243 /* Handle bad guys: */
1245 for (i = 0; i < NUM_BAD_GUYS; i++)
1247 if (bad_guys[i].alive)
1249 if (bad_guys[i].seen)
1251 if (bad_guys[i].kind == BAD_BSOD)
1253 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1255 /* Move left/right: */
1257 if (bad_guys[i].dying == NO ||
1258 bad_guys[i].dying == FALLING)
1260 if (bad_guys[i].dir == RIGHT)
1261 bad_guys[i].x = bad_guys[i].x + 4;
1262 else if (bad_guys[i].dir == LEFT)
1263 bad_guys[i].x = bad_guys[i].x - 4;
1267 /* Move vertically: */
1269 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1272 /* Bump into things horizontally: */
1274 if (!bad_guys[i].dying)
1276 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1277 bad_guys[i].dir = !bad_guys[i].dir;
1281 /* Bump into other bad guys: */
1283 for (j = 0; j < NUM_BAD_GUYS; j++)
1285 if (j != i && bad_guys[j].alive &&
1286 !bad_guys[j].dying && !bad_guys[i].dying &&
1287 bad_guys[i].x >= bad_guys[j].x - 32 &&
1288 bad_guys[i].x <= bad_guys[j].x + 32 &&
1289 bad_guys[i].y >= bad_guys[j].y - 32 &&
1290 bad_guys[i].y <= bad_guys[j].y + 32)
1292 bad_guys[i].dir = !bad_guys[i].dir;
1297 /* Fall if we get off the ground: */
1299 if (bad_guys[i].dying != FALLING)
1301 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1302 bad_guys[i].ym < MAX_YM)
1304 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1310 if (bad_guys[i].ym > 0)
1312 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1318 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1320 if (bad_guys[i].y > 480)
1321 bad_guys[i].alive = NO;
1323 else if (bad_guys[i].kind == BAD_LAPTOP)
1325 /* --- LAPTOP MONSTER: --- */
1327 /* Move left/right: */
1329 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1331 if (bad_guys[i].dying == NO ||
1332 bad_guys[i].dying == FALLING)
1334 if (bad_guys[i].dir == RIGHT)
1335 bad_guys[i].x = bad_guys[i].x + 4;
1336 else if (bad_guys[i].dir == LEFT)
1337 bad_guys[i].x = bad_guys[i].x - 4;
1340 else if (bad_guys[i].mode == KICK)
1342 if (bad_guys[i].dir == RIGHT)
1343 bad_guys[i].x = bad_guys[i].x + 16;
1344 else if (bad_guys[i].dir == LEFT)
1345 bad_guys[i].x = bad_guys[i].x - 16;
1349 /* Move vertically: */
1351 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1354 /* Bump into things horizontally: */
1356 if (!bad_guys[i].dying)
1358 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1360 bad_guys[i].dir = !bad_guys[i].dir;
1362 if (bad_guys[i].mode == KICK)
1363 play_sound(sounds[SND_RICOCHET]);
1368 /* Bump into other bad guys: */
1370 for (j = 0; j < NUM_BAD_GUYS; j++)
1372 if (j != i && bad_guys[j].alive &&
1373 !bad_guys[j].dying && !bad_guys[i].dying &&
1374 bad_guys[i].x >= bad_guys[j].x - 32 &&
1375 bad_guys[i].x <= bad_guys[j].x + 32 &&
1376 bad_guys[i].y >= bad_guys[j].y - 32 &&
1377 bad_guys[i].y <= bad_guys[j].y + 32)
1379 if (bad_guys[i].mode != KICK)
1380 bad_guys[i].dir = !bad_guys[i].dir;
1383 /* We're in kick mode, kill the other guy: */
1385 bad_guys[j].dying = FALLING;
1386 bad_guys[j].ym = -8;
1387 play_sound(sounds[SND_FALL]);
1389 add_score(bad_guys[i].x - scroll_x,
1390 bad_guys[i].y, 100);
1396 /* Fall if we get off the ground: */
1398 if (bad_guys[i].dying != FALLING)
1400 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1401 bad_guys[i].ym < MAX_YM)
1403 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1409 if (bad_guys[i].ym > 0)
1411 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1417 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1419 if (bad_guys[i].y > 480)
1420 bad_guys[i].alive = NO;
1422 else if (bad_guys[i].kind == BAD_MONEY)
1424 /* --- MONEY BAGS: --- */
1427 /* Move vertically: */
1429 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1432 /* Fall if we get off the ground: */
1434 if (bad_guys[i].dying != FALLING)
1436 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1438 if (bad_guys[i].ym < MAX_YM)
1440 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1447 if (bad_guys[i].ym > 0)
1449 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1450 bad_guys[i].ym = -MAX_YM;
1455 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1457 if (bad_guys[i].y > 480)
1458 bad_guys[i].alive = NO;
1460 else if (bad_guys[i].kind == -1)
1464 /* Kill it if the player jumped on it: */
1466 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1467 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1468 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1469 tux_y >= bad_guys[i].y - 32 &&
1470 tux_y <= bad_guys[i].y - 8
1474 if (bad_guys[i].kind == BAD_BSOD)
1476 bad_guys[i].dying = SQUISHED;
1477 bad_guys[i].timer = 16;
1478 tux_ym = -KILL_BOUNCE_YM;
1480 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1481 50 * score_multiplier);
1483 play_sound(sounds[SND_SQUISH]);
1485 else if (bad_guys[i].kind == BAD_LAPTOP)
1487 if (bad_guys[i].mode != FLAT)
1491 bad_guys[i].mode = FLAT;
1493 bad_guys[i].timer = 64;
1501 bad_guys[i].mode = KICK;
1503 if (tux_x + scroll_x <= bad_guys[i].x)
1504 bad_guys[i].dir = RIGHT;
1506 bad_guys[i].dir = LEFT;
1508 bad_guys[i].timer = 8;
1511 tux_ym = -KILL_BOUNCE_YM;
1513 add_score(bad_guys[i].x - scroll_x,
1515 25 * score_multiplier);
1517 /* play_sound(sounds[SND_SQUISH]); */
1519 else if (bad_guys[i].kind == -1)
1526 /* Hurt the player if he just touched it: */
1528 if (!bad_guys[i].dying && !tux_dying &&
1530 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1531 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1532 tux_y >= bad_guys[i].y - 32 &&
1533 tux_y <= bad_guys[i].y + 32)
1535 if (bad_guys[i].mode == FLAT)
1539 bad_guys[i].mode = KICK;
1541 if (tux_x + scroll_x <= bad_guys[i].x)
1543 bad_guys[i].dir = RIGHT;
1544 bad_guys[i].x = bad_guys[i].x + 16;
1548 bad_guys[i].dir = LEFT;
1549 bad_guys[i].x = bad_guys[i].x - 16;
1552 bad_guys[i].timer = 8;
1554 else if (bad_guys[i].mode == KICK)
1556 if (tux_y < bad_guys[i].y - 16 &&
1557 bad_guys[i].timer == 0)
1559 /* Step on (stop being kicked) */
1561 bad_guys[i].mode = FLAT;
1562 bad_guys[i].timer = 64;
1566 /* Hurt if you get hit by kicked laptop: */
1568 if (bad_guys[i].timer == 0)
1570 if (tux_invincible_time == 0)
1576 bad_guys[i].dying = FALLING;
1577 bad_guys[i].ym = -8;
1578 play_sound(sounds[SND_FALL]);
1585 if (tux_invincible_time == 0)
1591 bad_guys[i].dying = FALLING;
1592 bad_guys[i].ym = -8;
1593 play_sound(sounds[SND_FALL]);
1599 /* Handle mode timer: */
1601 if (bad_guys[i].mode == FLAT)
1603 bad_guys[i].timer--;
1605 if (bad_guys[i].timer <= 0)
1606 bad_guys[i].mode = NORMAL;
1608 else if (bad_guys[i].mode == KICK)
1610 if (bad_guys[i].timer > 0)
1611 bad_guys[i].timer--;
1615 /* Handle dying timer: */
1617 if (bad_guys[i].dying == SQUISHED)
1619 bad_guys[i].timer--;
1622 /* Remove it if time's up: */
1624 if (bad_guys[i].timer <= 0)
1625 bad_guys[i].alive = NO;
1629 /* Remove if it's far off the screen: */
1631 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1632 bad_guys[i].alive = NO;
1636 /* Once it's on screen, it's activated! */
1638 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1639 bad_guys[i].seen = YES;
1645 /* Handle skidding: */
1647 if (tux_skidding > 0)
1655 /* --- GAME DRAW! --- */
1663 if (tux_dying && (frame % 4) == 0)
1664 clearscreen(255, 255, 255);
1667 if (super_bkgd_time == 0)
1668 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1670 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1674 /* Draw background: */
1676 for (y = 0; y < 15; y++)
1678 for (x = 0; x < 21; x++)
1680 drawshape(x * 32 - (scroll_x % 32), y * 32,
1681 tiles[y][x + (scroll_x / 32)]);
1686 /* (Bouncy bricks): */
1688 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1690 if (bouncy_bricks[i].alive)
1692 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1693 bouncy_bricks[i].x <= scroll_x + 640)
1695 dest.x = bouncy_bricks[i].x - scroll_x;
1696 dest.y = bouncy_bricks[i].y;
1700 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1705 drawshape(bouncy_bricks[i].x - scroll_x,
1706 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1707 bouncy_bricks[i].shape);
1715 for (i = 0; i < NUM_BAD_GUYS; i++)
1717 if (bad_guys[i].alive &&
1718 bad_guys[i].x > scroll_x - 32 &&
1719 bad_guys[i].x < scroll_x + 640)
1721 if (bad_guys[i].kind == BAD_BSOD)
1723 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1725 if (bad_guys[i].dying == NO)
1729 if (bad_guys[i].dir == LEFT)
1731 drawimage(img_bsod_left[(frame / 5) % 4],
1732 bad_guys[i].x - scroll_x,
1738 drawimage(img_bsod_right[(frame / 5) % 4],
1739 bad_guys[i].x - scroll_x,
1744 else if (bad_guys[i].dying == FALLING)
1748 if (bad_guys[i].dir == LEFT)
1750 drawimage(img_bsod_falling_left,
1751 bad_guys[i].x - scroll_x,
1757 drawimage(img_bsod_falling_right,
1758 bad_guys[i].x - scroll_x,
1763 else if (bad_guys[i].dying == SQUISHED)
1765 /* Dying - Squished: */
1767 if (bad_guys[i].dir == LEFT)
1769 drawimage(img_bsod_squished_left,
1770 bad_guys[i].x - scroll_x,
1776 drawimage(img_bsod_squished_right,
1777 bad_guys[i].x - scroll_x,
1783 else if (bad_guys[i].kind == BAD_LAPTOP)
1785 /* --- LAPTOP MONSTER: --- */
1787 if (bad_guys[i].dying == NO)
1791 if (bad_guys[i].mode == NORMAL)
1795 if (bad_guys[i].dir == LEFT)
1797 drawimage(img_laptop_left[(frame / 5) % 3],
1798 bad_guys[i].x - scroll_x,
1804 drawimage(img_laptop_right[(frame / 5) % 3],
1805 bad_guys[i].x - scroll_x,
1814 if (bad_guys[i].dir == LEFT)
1816 drawimage(img_laptop_flat_left,
1817 bad_guys[i].x - scroll_x,
1823 drawimage(img_laptop_flat_right,
1824 bad_guys[i].x - scroll_x,
1830 else if (bad_guys[i].dying == FALLING)
1834 if (bad_guys[i].dir == LEFT)
1836 drawimage(img_laptop_falling_left,
1837 bad_guys[i].x - scroll_x,
1843 drawimage(img_laptop_falling_right,
1844 bad_guys[i].x - scroll_x,
1850 else if (bad_guys[i].kind == BAD_MONEY)
1852 if (bad_guys[i].ym > -16)
1854 if (bad_guys[i].dir == LEFT)
1856 drawimage(img_money_left[0],
1857 bad_guys[i].x - scroll_x,
1863 drawimage(img_money_right[0],
1864 bad_guys[i].x - scroll_x,
1871 if (bad_guys[i].dir == LEFT)
1873 drawimage(img_money_left[1],
1874 bad_guys[i].x - scroll_x,
1880 drawimage(img_money_right[1],
1881 bad_guys[i].x - scroll_x,
1887 else if (bad_guys[i].kind == -1)
1895 if (right == UP && left == UP)
1902 if ((fire == DOWN && (frame % 2) == 0) ||
1904 tux_frame_main = (tux_frame_main + 1) % 4;
1906 tux_frame = tux_frame_main;
1913 if (tux_safe == 0 || (frame % 2) == 0)
1915 if (tux_size == SMALL)
1917 if (tux_invincible_time)
1921 if (tux_dir == RIGHT)
1923 drawimage(cape_right[frame % 2],
1929 drawimage(cape_left[frame % 2],
1936 if (!tux_got_coffee)
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 /* Tux got coffee! */
1951 if (tux_dir == RIGHT)
1953 drawimage(firetux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1957 drawimage(firetux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1963 if (tux_invincible_time)
1967 if (tux_dir == RIGHT)
1969 drawimage(bigcape_right[frame % 2],
1970 tux_x - 8 - 16, tux_y - 32,
1975 drawimage(bigcape_left[frame % 2],
1976 tux_x - 8, tux_y - 32,
1981 if (!tux_got_coffee)
1987 if (!jumping || tux_ym > 0)
1989 if (tux_dir == RIGHT)
1991 drawimage(bigtux_right[tux_frame],
1992 tux_x - 8, tux_y - 32,
1997 drawimage(bigtux_left[tux_frame],
1998 tux_x - 8, tux_y - 32,
2004 if (tux_dir == RIGHT)
2006 drawimage(bigtux_right_jump,
2007 tux_x - 8, tux_y - 32,
2012 drawimage(bigtux_left_jump,
2013 tux_x - 8, tux_y - 32,
2020 if (tux_dir == RIGHT)
2022 drawimage(skidtux_right,
2023 tux_x - 8, tux_y - 32,
2028 drawimage(skidtux_left,
2029 tux_x - 8, tux_y - 32,
2036 if (tux_dir == RIGHT)
2038 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2043 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2050 /* Tux has coffee! */
2056 if (!jumping || tux_ym > 0)
2058 if (tux_dir == RIGHT)
2060 drawimage(bigfiretux_right[tux_frame],
2061 tux_x - 8, tux_y - 32,
2066 drawimage(bigfiretux_left[tux_frame],
2067 tux_x - 8, tux_y - 32,
2073 if (tux_dir == RIGHT)
2075 drawimage(bigfiretux_right_jump,
2076 tux_x - 8, tux_y - 32,
2081 drawimage(bigfiretux_left_jump,
2082 tux_x - 8, tux_y - 32,
2089 if (tux_dir == RIGHT)
2091 drawimage(skidfiretux_right,
2092 tux_x - 8, tux_y - 32,
2097 drawimage(skidfiretux_left,
2098 tux_x - 8, tux_y - 32,
2105 if (tux_dir == RIGHT)
2107 drawimage(duckfiretux_right, tux_x - 8, tux_y - 16,
2112 drawimage(duckfiretux_left, tux_x - 8, tux_y - 16,
2123 for (i = 0; i < NUM_BULLETS; i++)
2125 if (bullets[i].alive &&
2126 bullets[i].x >= scroll_x - 4 &&
2127 bullets[i].x <= scroll_x + 640)
2129 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2135 /* (Floating scores): */
2137 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2139 if (floating_scores[i].alive)
2141 sprintf(str, "%d", floating_scores[i].value);
2143 floating_scores[i].x + 16 - strlen(str) * 8,
2144 floating_scores[i].y,
2145 letters_gold, NO_UPDATE);
2152 for (i = 0; i < NUM_UPGRADES; i++)
2154 if (upgrades[i].alive)
2156 if (upgrades[i].height < 32)
2160 dest.x = upgrades[i].x - scroll_x;
2161 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2163 dest.h = upgrades[i].height;
2168 src.h = upgrades[i].height;
2170 if (upgrades[i].kind == UPGRADE_MINTS)
2171 SDL_BlitSurface(img_mints, &src, screen, &dest);
2172 else if (upgrades[i].kind == UPGRADE_COFFEE)
2173 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2174 else if (upgrades[i].kind == UPGRADE_HERRING)
2175 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2179 if (upgrades[i].kind == UPGRADE_MINTS)
2181 drawimage(img_mints,
2182 upgrades[i].x - scroll_x, upgrades[i].y,
2185 else if (upgrades[i].kind == UPGRADE_COFFEE)
2187 drawimage(img_coffee,
2188 upgrades[i].x - scroll_x, upgrades[i].y,
2191 else if (upgrades[i].kind == UPGRADE_HERRING)
2193 drawimage(img_golden_herring,
2194 upgrades[i].x - scroll_x, upgrades[i].y,
2202 /* (Bouncy distros): */
2204 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2206 if (bouncy_distros[i].alive)
2208 drawimage(img_distro[0],
2209 bouncy_distros[i].x - scroll_x,
2210 bouncy_distros[i].y,
2216 /* (Broken bricks): */
2218 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2220 if (broken_bricks[i].alive)
2222 src.x = rand() % 16;
2223 src.y = rand() % 16;
2227 dest.x = broken_bricks[i].x - scroll_x;
2228 dest.y = broken_bricks[i].y;
2232 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2239 sprintf(str, "%d", score);
2240 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2241 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2243 sprintf(str, "%d", highscore);
2244 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2245 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2247 if (time_left >= TIME_WARNING || (frame % 10) < 5)
2249 sprintf(str, "%d", time_left);
2250 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2251 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2254 sprintf(str, "%d", distros);
2255 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2256 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2258 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE);
2260 for(i=0; i < lives; ++i)
2262 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2266 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2271 /* (Update it all!) */
2278 /* --- GAME LOOP! --- */
2283 Uint32 last_time, now_time;
2287 clearscreen(0, 0, 0);
2291 /* Init the game: */
2299 highscore = load_hs();
2302 /* --- MAIN GAME LOOP!!! --- */
2314 last_time = SDL_GetTicks();
2318 /* Handle events: */
2324 /* Handle actions: */
2326 if(!game_pause && !show_menu)
2328 if (game_action() == 0)
2330 /* == 0: no more lives */
2331 /* == -1: continues */
2338 /*Draw the current scene to the screen */
2341 /* Keep playing music: */
2344 if (!playing_music())
2346 switch (current_music)
2349 if (time_left <= TIME_WARNING)
2350 play_music(level_song_fast, 1);
2352 play_music(level_song, 1);
2355 play_music(herring_song, 1);
2357 case HURRYUP_MUSIC: // keep the compiler happy
2358 case NO_MUSIC: // keep the compiler happy for the moment :-)
2364 /* Time stops in pause mode */
2365 if(game_pause || show_menu )
2370 /* Pause til next frame: */
2372 now_time = SDL_GetTicks();
2373 if (now_time < last_time + FPS)
2374 SDL_Delay(last_time + FPS - now_time);
2379 if ((frame % 10) == 0 && time_left > 0)
2383 /* Stop the music; it will start again, faster! */
2384 if (time_left == TIME_WARNING)
2391 while (!done && !quit);
2393 if (playing_music())
2404 /* Initialize the game stuff: */
2416 /* Load data for this level: */
2418 void loadlevel(void)
2429 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2430 bouncy_distros[i].alive = NO;
2432 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2433 broken_bricks[i].alive = NO;
2435 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2436 bouncy_bricks[i].alive = NO;
2438 for (i = 0; i < NUM_BAD_GUYS; i++)
2439 bad_guys[i].alive = NO;
2441 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2442 floating_scores[i].alive = NO;
2444 for (i = 0; i < NUM_UPGRADES; i++)
2445 upgrades[i].alive = NO;
2447 for (i = 0; i < NUM_BULLETS; i++)
2448 bullets[i].alive = NO;
2451 /* Load data file: */
2453 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2454 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2455 fi = fopen(filename, "r");
2466 /* Load header info: */
2471 strcpy(levelname, str);
2472 levelname[strlen(levelname)-1] = '\0';
2476 strcpy(leveltheme, str);
2477 leveltheme[strlen(leveltheme)-1] = '\0';
2481 /* (Time to beat level) */
2483 time_left = atoi(str);
2485 /* (Song file for this level) */
2486 fgets(str, sizeof(song_title), fi);
2487 strcpy(song_title, str);
2488 song_title[strlen(song_title)-1] = '\0';
2492 /* (Level background color) */
2494 bkgd_red = atoi(str);
2496 bkgd_green= atoi(str);
2498 bkgd_blue = atoi(str);
2502 level_width = atoi(str);
2505 /* Allocate some space for the line-reading! */
2507 line = (char *) malloc(sizeof(char) * (level_width + 5));
2510 fprintf(stderr, "Couldn't allocate space to load level data!");
2515 /* Load the level lines: */
2517 for (y = 0; y < 15; y++)
2519 if(fgets(line, level_width + 5, fi) == NULL)
2521 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2524 line[strlen(line) - 1] = '\0';
2525 tiles[y] = strdup(line);
2531 /* Activate bad guys: */
2533 for (y = 0; y < 15; y++)
2535 for (x = 0; x < level_width; x++)
2537 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2539 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2554 tux_got_coffee = NO;
2555 tux_invincible_time = 0;
2559 tux_safe = TUX_SAFE_TIME;
2575 score_multiplier = 1;
2576 super_bkgd_time = 0;
2578 counting_distros = NO;
2583 /* set current song/music */
2584 current_music = LEVEL_MUSIC;
2588 clearscreen(0, 0, 0);
2590 sprintf(str, "LEVEL %d", level);
2591 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2593 sprintf(str, "%s", levelname);
2594 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2596 sprintf(str, "TUX x %d", lives);
2597 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2607 /* Load a level-specific graphic... */
2609 SDL_Surface * load_level_image(char * file, int use_alpha)
2613 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2615 return(load_image(fname, use_alpha));
2619 /* Load graphics: */
2621 void loadlevelgfx(void)
2623 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2624 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2626 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2627 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2628 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2629 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2631 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2632 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2633 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2634 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2636 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2637 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2638 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2639 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2645 void loadlevelsong(void)
2649 char * song_subtitle;
2651 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2652 strlen(song_title) + 8));
2653 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2654 level_song = load_song(song_path);
2658 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2659 strlen(song_title) + 8 + 5));
2660 song_subtitle = strdup(song_title);
2661 strcpy(strstr(song_subtitle, "."), "\0");
2662 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(song_title, "."));
2663 level_song_fast = load_song(song_path);
2664 free(song_subtitle);
2669 /* Free graphics data for this level: */
2671 void unloadlevelgfx(void)
2675 for (i = 0; i < 2; i++)
2677 SDL_FreeSurface(img_brick[i]);
2679 for (i = 0; i < 4; i++)
2681 SDL_FreeSurface(img_solid[i]);
2682 SDL_FreeSurface(img_bkgd[0][i]);
2683 SDL_FreeSurface(img_bkgd[1][i]);
2688 /* Free music data for this level: */
2690 void unloadlevelsong(void)
2692 free_music(level_song);
2696 /* Load graphics/sounds shared between all levels: */
2698 void loadshared(void)
2701 char * herring_song_path; /* for loading herring song*/
2705 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2708 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2711 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2714 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2717 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2720 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2723 firetux_right[0] = load_image(DATA_PREFIX "/images/shared/firetux-right-0.png",
2726 firetux_right[1] = load_image(DATA_PREFIX "/images/shared/firetux-right-1.png",
2729 firetux_right[2] = load_image(DATA_PREFIX "/images/shared/firetux-right-2.png",
2732 firetux_left[0] = load_image(DATA_PREFIX "/images/shared/firetux-left-0.png",
2735 firetux_left[1] = load_image(DATA_PREFIX "/images/shared/firetux-left-1.png",
2738 firetux_left[2] = load_image(DATA_PREFIX "/images/shared/firetux-left-2.png",
2741 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2744 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2747 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2750 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2753 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2756 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2759 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2763 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2765 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2768 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2771 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2775 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2778 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2782 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2786 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2790 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2793 bigfiretux_right[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
2796 bigfiretux_right[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
2799 bigfiretux_right[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
2802 bigfiretux_right_jump =
2803 load_image(DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
2805 bigfiretux_left[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
2808 bigfiretux_left[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
2811 bigfiretux_left[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
2814 bigfiretux_left_jump =
2815 load_image(DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
2818 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2822 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2826 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2830 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2834 ducktux_right = load_image(DATA_PREFIX
2835 "/images/shared/ducktux-right.png",
2838 ducktux_left = load_image(DATA_PREFIX
2839 "/images/shared/ducktux-left.png",
2842 skidtux_right = load_image(DATA_PREFIX
2843 "/images/shared/skidtux-right.png",
2846 skidtux_left = load_image(DATA_PREFIX
2847 "/images/shared/skidtux-left.png",
2850 duckfiretux_right = load_image(DATA_PREFIX
2851 "/images/shared/duckfiretux-right.png",
2854 duckfiretux_left = load_image(DATA_PREFIX
2855 "/images/shared/duckfiretux-left.png",
2858 skidfiretux_right = load_image(DATA_PREFIX
2859 "/images/shared/skidfiretux-right.png",
2862 skidfiretux_left = load_image(DATA_PREFIX
2863 "/images/shared/skidfiretux-left.png",
2869 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2871 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2878 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2880 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2883 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2886 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2892 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2893 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2899 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2901 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2907 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2910 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2913 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2916 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2920 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2923 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2926 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2929 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2937 img_bsod_left[0] = load_image(DATA_PREFIX
2938 "/images/shared/bsod-left-0.png",
2941 img_bsod_left[1] = load_image(DATA_PREFIX
2942 "/images/shared/bsod-left-1.png",
2945 img_bsod_left[2] = load_image(DATA_PREFIX
2946 "/images/shared/bsod-left-2.png",
2949 img_bsod_left[3] = load_image(DATA_PREFIX
2950 "/images/shared/bsod-left-3.png",
2953 img_bsod_right[0] = load_image(DATA_PREFIX
2954 "/images/shared/bsod-right-0.png",
2957 img_bsod_right[1] = load_image(DATA_PREFIX
2958 "/images/shared/bsod-right-1.png",
2961 img_bsod_right[2] = load_image(DATA_PREFIX
2962 "/images/shared/bsod-right-2.png",
2965 img_bsod_right[3] = load_image(DATA_PREFIX
2966 "/images/shared/bsod-right-3.png",
2969 img_bsod_squished_left = load_image(DATA_PREFIX
2970 "/images/shared/bsod-squished-left.png",
2973 img_bsod_squished_right = load_image(DATA_PREFIX
2974 "/images/shared/bsod-squished-right.png",
2977 img_bsod_falling_left = load_image(DATA_PREFIX
2978 "/images/shared/bsod-falling-left.png",
2981 img_bsod_falling_right = load_image(DATA_PREFIX
2982 "/images/shared/bsod-falling-right.png",
2988 img_laptop_left[0] = load_image(DATA_PREFIX
2989 "/images/shared/laptop-left-0.png",
2992 img_laptop_left[1] = load_image(DATA_PREFIX
2993 "/images/shared/laptop-left-1.png",
2996 img_laptop_left[2] = load_image(DATA_PREFIX
2997 "/images/shared/laptop-left-2.png",
3000 img_laptop_right[0] = load_image(DATA_PREFIX
3001 "/images/shared/laptop-right-0.png",
3004 img_laptop_right[1] = load_image(DATA_PREFIX
3005 "/images/shared/laptop-right-1.png",
3008 img_laptop_right[2] = load_image(DATA_PREFIX
3009 "/images/shared/laptop-right-2.png",
3012 img_laptop_flat_left = load_image(DATA_PREFIX
3013 "/images/shared/laptop-flat-left.png",
3016 img_laptop_flat_right = load_image(DATA_PREFIX
3017 "/images/shared/laptop-flat-right.png",
3020 img_laptop_falling_left =
3021 load_image(DATA_PREFIX
3022 "/images/shared/laptop-falling-left.png",
3025 img_laptop_falling_right =
3026 load_image(DATA_PREFIX
3027 "/images/shared/laptop-falling-right.png",
3033 img_money_left[0] = load_image(DATA_PREFIX
3034 "/images/shared/bag-left-0.png",
3037 img_money_left[1] = load_image(DATA_PREFIX
3038 "/images/shared/bag-left-1.png",
3041 img_money_right[0] = load_image(DATA_PREFIX
3042 "/images/shared/bag-right-0.png",
3045 img_money_right[1] = load_image(DATA_PREFIX
3046 "/images/shared/bag-right-1.png",
3053 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
3054 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
3059 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
3061 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
3068 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
3071 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
3074 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
3077 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
3083 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
3088 img_golden_herring =
3089 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
3093 /* Super background: */
3095 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
3099 /* Sound effects: */
3101 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
3102 // initialize sounds[i] with the correct pointer's value:
3103 // NULL or something else. And it will be dangerous to
3104 // play with not-initialized pointers.
3105 // This is also true with if (use_music)
3106 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
3108 for (i = 0; i < NUM_SOUNDS; i++)
3109 sounds[i] = load_sound(soundfilenames[i]);
3112 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
3113 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
3115 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
3117 herring_song = load_song(herring_song_path);
3119 free(herring_song_path);
3124 /* Free shared data: */
3126 void unloadshared(void)
3130 for (i = 0; i < 3; i++)
3132 SDL_FreeSurface(tux_right[i]);
3133 SDL_FreeSurface(tux_left[i]);
3134 SDL_FreeSurface(bigtux_right[i]);
3135 SDL_FreeSurface(bigtux_left[i]);
3138 SDL_FreeSurface(bigtux_right_jump);
3139 SDL_FreeSurface(bigtux_left_jump);
3141 for (i = 0; i < 2; i++)
3143 SDL_FreeSurface(cape_right[i]);
3144 SDL_FreeSurface(cape_left[i]);
3145 SDL_FreeSurface(bigcape_right[i]);
3146 SDL_FreeSurface(bigcape_left[i]);
3149 SDL_FreeSurface(ducktux_left);
3150 SDL_FreeSurface(ducktux_right);
3152 SDL_FreeSurface(skidtux_left);
3153 SDL_FreeSurface(skidtux_right);
3155 for (i = 0; i < 4; i++)
3157 SDL_FreeSurface(img_bsod_left[i]);
3158 SDL_FreeSurface(img_bsod_right[i]);
3161 SDL_FreeSurface(img_bsod_squished_left);
3162 SDL_FreeSurface(img_bsod_squished_right);
3164 SDL_FreeSurface(img_bsod_falling_left);
3165 SDL_FreeSurface(img_bsod_falling_right);
3167 for (i = 0; i < 3; i++)
3169 SDL_FreeSurface(img_laptop_left[i]);
3170 SDL_FreeSurface(img_laptop_right[i]);
3173 SDL_FreeSurface(img_laptop_flat_left);
3174 SDL_FreeSurface(img_laptop_flat_right);
3176 SDL_FreeSurface(img_laptop_falling_left);
3177 SDL_FreeSurface(img_laptop_falling_right);
3179 for (i = 0; i < 2; i++)
3181 SDL_FreeSurface(img_money_left[i]);
3182 SDL_FreeSurface(img_money_right[i]);
3185 SDL_FreeSurface(img_box_full);
3186 SDL_FreeSurface(img_box_empty);
3188 SDL_FreeSurface(img_water);
3189 for (i = 0; i < 3; i++)
3190 SDL_FreeSurface(img_waves[i]);
3192 SDL_FreeSurface(img_pole);
3193 SDL_FreeSurface(img_poletop);
3195 for (i = 0; i < 2; i++)
3196 SDL_FreeSurface(img_flag[i]);
3198 SDL_FreeSurface(img_mints);
3199 SDL_FreeSurface(img_coffee);
3201 for (i = 0; i < 4; i++)
3203 SDL_FreeSurface(img_distro[i]);
3204 SDL_FreeSurface(img_cloud[0][i]);
3205 SDL_FreeSurface(img_cloud[1][i]);
3208 SDL_FreeSurface(img_golden_herring);
3210 for (i = 0; i < NUM_SOUNDS; i++)
3211 free_chunk(sounds[i]);
3213 /* free the herring song */
3214 free_music( herring_song );
3218 /* Draw a tile on the screen: */
3220 void drawshape(int x, int y, unsigned char c)
3224 if (c == 'X' || c == 'x')
3225 drawimage(img_brick[0], x, y, NO_UPDATE);
3226 else if (c == 'Y' || c == 'y')
3227 drawimage(img_brick[1], x, y, NO_UPDATE);
3228 else if (c == 'A' || c =='B' || c == '!')
3229 drawimage(img_box_full, x, y, NO_UPDATE);
3231 drawimage(img_box_empty, x, y, NO_UPDATE);
3232 else if (c >= 'C' && c <= 'F')
3233 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3234 else if (c >= 'c' && c <= 'f')
3235 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3236 else if (c >= 'G' && c <= 'J')
3237 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3238 else if (c >= 'g' && c <= 'j')
3239 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3241 drawimage(img_solid[0], x, y, NO_UPDATE);
3243 drawimage(img_solid[1], x, y, NO_UPDATE);
3245 drawimage(img_solid[2], x, y, NO_UPDATE);
3247 drawimage(img_solid[3], x, y, NO_UPDATE);
3250 z = (frame / 2) % 6;
3253 drawimage(img_distro[z], x, y, NO_UPDATE);
3255 drawimage(img_distro[2], x, y, NO_UPDATE);
3257 drawimage(img_distro[1], x, y, NO_UPDATE);
3261 z = (frame / 3) % 3;
3263 drawimage(img_waves[z], x, y, NO_UPDATE);
3266 drawimage(img_poletop, x, y, NO_UPDATE);
3269 drawimage(img_pole, x, y, NO_UPDATE);
3271 /* Mark this as the end position of the level! */
3277 z = (frame / 3) % 2;
3279 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3282 drawimage(img_water, x, y, NO_UPDATE);
3286 /* What shape is at some position? */
3288 unsigned char shape(int x, int y, int sx)
3294 xx = ((x + sx) / 32);
3296 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3307 int issolid(int x, int y, int sx)
3313 if (isbrick(x, y, sx) ||
3314 isbrick(x + 31, y, sx) ||
3316 isice(x + 31, y, sx) ||
3317 (shape(x, y, sx) == '[' ||
3318 shape(x + 31, y, sx) == '[') ||
3319 (shape(x, y, sx) == '=' ||
3320 shape(x + 31, y, sx) == '=') ||
3321 (shape(x, y, sx) == ']' ||
3322 shape(x + 31, y, sx) == ']') ||
3323 (shape(x, y, sx) == 'A' ||
3324 shape(x + 31, y, sx) == 'A') ||
3325 (shape(x, y, sx) == 'B' ||
3326 shape(x + 31, y, sx) == 'B') ||
3327 (shape(x, y, sx) == '!' ||
3328 shape(x + 31, y, sx) == '!') ||
3329 (shape(x, y, sx) == 'a' ||
3330 shape(x + 31, y, sx) == 'a'))
3339 /* Is it a brick? */
3341 int isbrick(int x, int y, int sx)
3347 if (shape(x, y, sx) == 'X' ||
3348 shape(x, y, sx) == 'x' ||
3349 shape(x, y, sx) == 'Y' ||
3350 shape(x, y, sx) == 'y')
3361 int isice(int x, int y, int sx)
3367 if (shape(x, y, sx) == '#')
3376 /* Is it a full box? */
3378 int isfullbox(int x, int y, int sx)
3384 if (shape(x, y, sx) == 'A' ||
3385 shape(x, y, sx) == 'B' ||
3386 shape(x, y, sx) == '!')
3395 /* Edit a piece of the map! */
3397 void change(int x, int y, int sx, unsigned char c)
3402 xx = ((x + sx) / 32);
3404 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3409 /* Break a brick: */
3411 void trybreakbrick(int x, int y, int sx)
3413 if (isbrick(x, y, sx))
3415 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3417 /* Get a distro from it: */
3419 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3422 if (counting_distros == NO)
3424 counting_distros = YES;
3425 distro_counter = 50;
3428 if (distro_counter <= 0)
3429 change(x, y, sx, 'a');
3431 play_sound(sounds[SND_DISTRO]);
3432 score = score + SCORE_DISTRO;
3437 /* Get rid of it: */
3439 change(x, y, sx, '.');
3443 /* Replace it with broken bits: */
3445 add_broken_brick(((x + sx + 1) / 32) * 32,
3449 /* Get some score: */
3451 play_sound(sounds[SND_BRICK]);
3452 score = score + SCORE_BRICK;
3457 /* Bounce a brick: */
3459 void bumpbrick(int x, int y, int sx)
3461 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3464 play_sound(sounds[SND_BRICK]);
3470 void tryemptybox(int x, int y, int sx)
3472 if (isfullbox(x, y, sx))
3474 if (shape(x, y, sx) == 'A')
3476 /* Box with a distro! */
3478 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3479 (y / 32) * 32 - 32);
3481 play_sound(sounds[SND_DISTRO]);
3482 score = score + SCORE_DISTRO;
3485 else if (shape(x, y, sx) == 'B')
3487 /* Add an upgrade! */
3489 if (tux_size == SMALL)
3491 /* Tux is small, add mints! */
3493 add_upgrade(((x + sx + 1) / 32) * 32,
3499 /* Tux is big, add coffee: */
3501 add_upgrade(((x + sx + 1) / 32) * 32,
3506 play_sound(sounds[SND_UPGRADE]);
3508 else if (shape(x, y, sx) == '!')
3510 /* Add a golden herring */
3512 add_upgrade(((x + sx + 1) / 32) * 32,
3517 /* Empty the box: */
3519 change(x, y, sx, 'a');
3524 /* Try to grab a distro: */
3526 void trygrabdistro(int x, int y, int sx, int bounciness)
3528 if (shape(x, y, sx) == '$')
3530 change(x, y, sx, '.');
3531 play_sound(sounds[SND_DISTRO]);
3533 if (bounciness == BOUNCE)
3535 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3539 score = score + SCORE_DISTRO;
3545 /* Add a bouncy distro: */
3547 void add_bouncy_distro(int x, int y)
3553 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3555 if (!bouncy_distros[i].alive)
3561 bouncy_distros[found].alive = YES;
3562 bouncy_distros[found].x = x;
3563 bouncy_distros[found].y = y;
3564 bouncy_distros[found].ym = -6;
3569 /* Add broken brick pieces: */
3571 void add_broken_brick(int x, int y)
3573 add_broken_brick_piece(x, y, -4, -16);
3574 add_broken_brick_piece(x, y + 16, -6, -12);
3576 add_broken_brick_piece(x + 16, y, 4, -16);
3577 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3581 /* Add a broken brick piece: */
3583 void add_broken_brick_piece(int x, int y, int xm, int ym)
3589 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3591 if (!broken_bricks[i].alive)
3597 broken_bricks[found].alive = YES;
3598 broken_bricks[found].x = x;
3599 broken_bricks[found].y = y;
3600 broken_bricks[found].xm = xm;
3601 broken_bricks[found].ym = ym;
3606 /* Add a bouncy brick piece: */
3608 void add_bouncy_brick(int x, int y)
3614 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3616 if (!bouncy_bricks[i].alive)
3622 bouncy_bricks[found].alive = YES;
3623 bouncy_bricks[found].x = x;
3624 bouncy_bricks[found].y = y;
3625 bouncy_bricks[found].offset = 0;
3626 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3627 bouncy_bricks[found].shape = shape(x, y, 0);
3632 /* Add a bad guy: */
3634 void add_bad_guy(int x, int y, int kind)
3640 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3642 if (!bad_guys[i].alive)
3648 bad_guys[found].alive = YES;
3649 bad_guys[found].mode = NORMAL;
3650 bad_guys[found].dying = NO;
3651 bad_guys[found].timer = 0;
3652 bad_guys[found].kind = kind;
3653 bad_guys[found].x = x;
3654 bad_guys[found].y = y;
3655 bad_guys[found].xm = 0;
3656 bad_guys[found].ym = 0;
3657 bad_guys[found].dir = LEFT;
3658 bad_guys[found].seen = NO;
3665 void add_score(int x, int y, int s)
3670 /* Add the score: */
3675 /* Add a floating score thing to the game: */
3679 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3681 if (!floating_scores[i].alive)
3688 floating_scores[found].alive = YES;
3689 floating_scores[found].x = x;
3690 floating_scores[found].y = y - 16;
3691 floating_scores[found].timer = 8;
3692 floating_scores[found].value = s;
3697 /* Try to bump a bad guy from below: */
3699 void trybumpbadguy(int x, int y, int sx)
3706 for (i = 0; i < NUM_BAD_GUYS; i++)
3708 if (bad_guys[i].alive &&
3709 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3710 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3712 if (bad_guys[i].kind == BAD_BSOD ||
3713 bad_guys[i].kind == BAD_LAPTOP)
3715 bad_guys[i].dying = FALLING;
3716 bad_guys[i].ym = -8;
3717 play_sound(sounds[SND_FALL]);
3725 for (i = 0; i < NUM_UPGRADES; i++)
3727 if (upgrades[i].alive && upgrades[i].height == 32 &&
3728 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3729 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3731 upgrades[i].xm = -upgrades[i].xm;
3732 upgrades[i].ym = -8;
3733 play_sound(sounds[SND_BUMP_UPGRADE]);
3739 /* Add an upgrade: */
3741 void add_upgrade(int x, int y, int kind)
3747 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3749 if (!upgrades[i].alive)
3755 upgrades[found].alive = YES;
3756 upgrades[found].kind = kind;
3757 upgrades[found].x = x;
3758 upgrades[found].y = y;
3759 upgrades[found].xm = 4;
3760 upgrades[found].ym = -4;
3761 upgrades[found].height = 0;
3768 void killtux(int mode)
3772 play_sound(sounds[SND_HURT]);
3774 if (tux_dir == RIGHT)
3776 else if (tux_dir == LEFT)
3779 if (mode == SHRINK && tux_size == BIG)
3782 tux_got_coffee = NO;
3786 tux_safe = TUX_SAFE_TIME;
3797 void add_bullet(int x, int y, int dir, int xm)
3803 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3805 if (!bullets[i].alive)
3811 bullets[found].alive = YES;
3815 bullets[found].x = x + 32;
3816 bullets[found].xm = BULLET_XM + xm;
3820 bullets[found].x = x;
3821 bullets[found].xm = -BULLET_XM + xm;
3824 bullets[found].y = y;
3825 bullets[found].ym = BULLET_STARTING_YM;
3827 play_sound(sounds[SND_SHOOT]);
3832 void drawendscreen(void)
3836 clearscreen(0, 0, 0);
3838 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3840 sprintf(str, "SCORE: %d", score);
3841 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3843 sprintf(str, "DISTROS: %d", distros);
3844 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3850 void drawresultscreen(void)
3854 clearscreen(0, 0, 0);
3856 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3858 sprintf(str, "SCORE: %d", score);
3859 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3861 sprintf(str, "DISTROS: %d", distros);
3862 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3865 /*SDL_Delay(2000);*/