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"
39 /* Local variables: */
41 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
42 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
43 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
44 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
45 super_bkgd_time, time_left, tux_invincible_time, endpos,
46 counting_distros, distro_counter;
47 int bkgd_red, bkgd_green, bkgd_blue, level_width;
48 int left, right, up, down, fire, old_fire;
49 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
50 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
51 SDL_Surface * img_bkgd[2][4];
52 SDL_Surface * img_golden_herring;
53 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
54 * img_laptop_left[3], * img_laptop_right[3],
55 * img_money_left[2], * img_money_right[2];
56 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
57 * img_bsod_falling_left, * img_bsod_falling_right,
58 * img_laptop_flat_left, * img_laptop_flat_right,
59 * img_laptop_falling_left, * img_laptop_falling_right;
60 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
61 * img_super_bkgd, * img_bullet, * img_red_glow;
62 SDL_Surface * img_cloud[2][4];
63 SDL_Surface * tux_life,
64 * tux_right[3], * tux_left[3],
65 * bigtux_right[3], * bigtux_left[3],
66 * bigtux_right_jump, * bigtux_left_jump,
67 * ducktux_right, * ducktux_left,
68 * skidtux_right, * skidtux_left,
69 * firetux_right[3], * firetux_left[3],
70 * bigfiretux_right[3], * bigfiretux_left[3],
71 * bigfiretux_right_jump, * bigfiretux_left_jump,
72 * duckfiretux_right, * duckfiretux_left,
73 * skidfiretux_right, * skidfiretux_left,
74 * cape_right[2], * cape_left[2],
75 * bigcape_right[2], * bigcape_left[2];
79 unsigned char * tiles[15];
80 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
81 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
82 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
83 bad_guy_type bad_guys[NUM_BAD_GUYS];
84 floating_score_type floating_scores[NUM_FLOATING_SCORES];
85 upgrade_type upgrades[NUM_UPGRADES];
86 bullet_type bullets[NUM_BULLETS];
93 /* Local function prototypes: */
97 void loadlevelgfx(void);
98 void loadlevelsong(void);
99 void unloadlevelgfx(void);
100 void unloadlevelsong(void);
101 void loadshared(void);
102 void unloadshared(void);
103 void drawshape(int x, int y, unsigned char c);
105 unsigned char shape(int x, int y, int sx);
106 int issolid(int x, int y, int sx);
107 int isbrick(int x, int y, int sx);
108 int isice(int x, int y, int sx);
109 int isfullbox(int x, int y, int sx);
110 void change(int x, int y, int sx, unsigned char c);
111 void trybreakbrick(int x, int y, int sx);
112 void bumpbrick(int x, int y, int sx);
113 void tryemptybox(int x, int y, int sx);
114 void trygrabdistro(int x, int y, int sx, int bounciness);
115 void add_bouncy_distro(int x, int y);
116 void add_broken_brick(int x, int y);
117 void add_broken_brick_piece(int x, int y, int xm, int ym);
118 void add_bouncy_brick(int x, int y);
119 void add_bad_guy(int x, int y, int kind);
120 void add_score(int x, int y, int s);
121 void trybumpbadguy(int x, int y, int sx);
122 void add_upgrade(int x, int y, int kind);
123 void killtux(int mode);
124 void add_bullet(int x, int y, int dir, int xm);
125 void drawendscreen(void);
126 void drawresultscreen(void);
128 /* --- GAME EVENT! --- */
130 void game_event(void)
133 while (SDL_PollEvent(&event))
136 if (event.type == SDL_QUIT)
138 /* Quit event - quit: */
142 else if (event.type == SDL_KEYDOWN)
146 key = event.key.keysym.sym;
148 /* Check for menu-events, if the menu is shown */
152 if (key == SDLK_ESCAPE)
154 /* Escape: Open/Close the menu: */
163 else if (key == SDLK_RIGHT)
167 else if (key == SDLK_LEFT)
171 else if (key == SDLK_UP)
175 else if (key == SDLK_DOWN)
179 else if (key == SDLK_LCTRL)
184 else if (event.type == SDL_KEYUP)
188 key = event.key.keysym.sym;
190 if (key == SDLK_RIGHT)
194 else if (key == SDLK_LEFT)
198 else if (key == SDLK_UP)
202 else if (key == SDLK_DOWN)
206 else if (key == SDLK_LCTRL)
210 else if (key == SDLK_p)
220 else if (key == SDLK_TAB && debug_mode == YES)
222 tux_size = !tux_size;
224 else if (key == SDLK_END && debug_mode == YES)
228 else if (key == SDLK_SPACE && debug_mode == YES)
234 else if (event.type == SDL_JOYAXISMOTION)
236 if (event.jaxis.axis == JOY_X)
238 if (event.jaxis.value < -256)
243 if (event.jaxis.value > 256)
248 else if (event.jaxis.axis == JOY_Y)
250 if (event.jaxis.value > 256)
255 /* Handle joystick for the menu */
259 menuaction = MN_DOWN;
265 else if (event.type == SDL_JOYBUTTONDOWN)
267 if (event.jbutton.button == JOY_A)
269 else if (event.jbutton.button == JOY_B)
272 else if (event.type == SDL_JOYBUTTONUP)
274 if (event.jbutton.button == JOY_A)
276 else if (event.jbutton.button == JOY_B)
289 /* --- GAME ACTION! --- */
291 int game_action(void)
295 /* --- HANDLE TUX! --- */
297 /* Handle key and joystick state: */
299 if (!(tux_dying || next_level))
301 if (right == DOWN && left == UP)
305 if (tux_xm < -SKID_XM && !tux_skidding &&
308 tux_skidding = SKID_TIME;
310 play_sound(sounds[SND_SKID]);
316 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
324 if (tux_dir == RIGHT)
326 /* Facing the direction we're jumping? Go full-speed: */
330 tux_xm = tux_xm + WALK_SPEED;
332 if (tux_xm > MAX_WALK_XM)
333 tux_xm = MAX_WALK_XM;
335 else if (fire == DOWN)
337 tux_xm = tux_xm + RUN_SPEED;
339 if (tux_xm > MAX_RUN_XM)
345 /* Not facing the direction we're jumping?
348 tux_xm = tux_xm + WALK_SPEED / 2;
350 if (tux_xm > MAX_WALK_XM / 2)
351 tux_xm = MAX_WALK_XM / 2;
355 else if (left == DOWN && right == UP)
359 if (tux_xm > SKID_XM && !tux_skidding &&
362 tux_skidding = SKID_TIME;
363 play_sound(sounds[SND_SKID]);
368 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
378 /* Facing the direction we're jumping? Go full-speed: */
382 tux_xm = tux_xm - WALK_SPEED;
384 if (tux_xm < -MAX_WALK_XM)
385 tux_xm = -MAX_WALK_XM;
387 else if (fire == DOWN)
389 tux_xm = tux_xm - RUN_SPEED;
391 if (tux_xm < -MAX_RUN_XM)
392 tux_xm = -MAX_RUN_XM;
397 /* Not facing the direction we're jumping?
400 tux_xm = tux_xm - WALK_SPEED / 2;
402 if (tux_xm < -MAX_WALK_XM / 2)
403 tux_xm = -MAX_WALK_XM / 2;
411 if (tux_x >= endpos && endpos != 0)
421 if (jump_counter == 0)
425 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
428 /* If they're not on the ground, or are currently moving
429 vertically, don't jump! */
431 jump_counter = MAX_JUMP_COUNT;
435 /* Make sure we're not standing back up into a solid! */
437 if (tux_size == SMALL || tux_duck == NO ||
438 !issolid(tux_x, tux_y, scroll_x))
442 if (tux_size == SMALL)
443 play_sound(sounds[SND_JUMP]);
445 play_sound(sounds[SND_BIGJUMP]);
451 /* Keep jumping for a while: */
453 if (jump_counter < MAX_JUMP_COUNT)
455 tux_ym = tux_ym - JUMP_SPEED;
465 if (fire == DOWN && old_fire == UP && tux_got_coffee)
467 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
480 if (tux_size == BIG && tux_duck == YES)
482 /* Make sure we're not standing back up into a solid! */
484 if (!issolid(tux_x, tux_y - 32, scroll_x))
490 } /* (tux_dying || next_level) */
493 /* Tux either died, or reached the end of a level! */
502 /* End of a level! */
510 tux_ym = tux_ym + GRAVITY;
518 /* No more lives!? */
524 if (score > highscore)
531 } /* if (lives < 0) */
534 /* Either way, (re-)load the (next) level... */
545 tux_x = tux_x + tux_xm;
546 tux_y = tux_y + tux_ym;
549 /* Keep tux in bounds: */
552 else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
554 scroll_x = scroll_x - ( 160 - tux_x);
561 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
563 /* Scroll the screen in past center: */
565 scroll_x = scroll_x + (tux_x - 320);
568 if (scroll_x > ((level_width * 32) - 640))
569 scroll_x = ((level_width * 32) - 640);
571 else if (tux_x > 608)
573 /* ... unless there's no more to scroll! */
583 if (issolid(tux_x, tux_y + 31, scroll_x) &&
584 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
586 while (issolid(tux_x, tux_y + 31, scroll_x))
597 if (issolid(tux_x, tux_y, scroll_x) &&
598 !issolid(tux_x - tux_xm, tux_y, scroll_x))
600 while (issolid(tux_x, tux_y, scroll_x))
611 if (issolid(tux_x, tux_y + 31, scroll_x))
613 /* Set down properly: */
615 while (issolid(tux_x, tux_y + 31, scroll_x))
624 /* Reset score multiplier (for mutli-hits): */
627 score_multiplier = 1;
637 /* Bump into things: */
639 if (issolid(tux_x, tux_y, scroll_x) ||
640 (tux_size == BIG && !tux_duck &&
641 (issolid(tux_x, tux_y - 32, scroll_x))))
643 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
644 (tux_size == SMALL || tux_duck ||
645 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
647 tux_x = tux_x - tux_xm;
650 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
651 (tux_size == SMALL || tux_duck ||
652 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
660 /* Break bricks and empty boxes: */
664 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
665 isfullbox(tux_x, tux_y - 32, scroll_x))
667 trygrabdistro(tux_x, tux_y - 64, scroll_x,
669 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
671 if (isfullbox(tux_x, tux_y - 32,
674 bumpbrick(tux_x, tux_y - 32,
678 trybreakbrick(tux_x, tux_y - 32, scroll_x);
679 tryemptybox(tux_x, tux_y - 32, scroll_x);
682 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
683 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
685 trygrabdistro(tux_x + 31,
689 trybumpbadguy(tux_x + 31,
693 if (isfullbox(tux_x + 31, tux_y - 32,
696 bumpbrick(tux_x + 31, tux_y - 32,
700 trybreakbrick(tux_x + 31,
703 tryemptybox(tux_x + 31,
710 if (isbrick(tux_x, tux_y, scroll_x) ||
711 isfullbox(tux_x, tux_y, scroll_x))
713 trygrabdistro(tux_x, tux_y - 32, scroll_x,
715 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
716 if (isfullbox(tux_x, tux_y, scroll_x))
717 bumpbrick(tux_x, tux_y, scroll_x);
718 trybreakbrick(tux_x, tux_y, scroll_x);
719 tryemptybox(tux_x, tux_y, scroll_x);
722 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
723 isfullbox(tux_x + 31, tux_y, scroll_x))
725 trygrabdistro(tux_x + 31,
729 trybumpbadguy(tux_x + 31,
732 if (isfullbox(tux_x + 31, tux_y, scroll_x))
733 bumpbrick(tux_x + 31, tux_y, scroll_x);
734 trybreakbrick(tux_x + 31, tux_y, scroll_x);
735 tryemptybox(tux_x + 31, tux_y, scroll_x);
741 /* It's a brick and we're small, make the brick
742 bounce, and grab any distros above it: */
744 if (isbrick(tux_x, tux_y, scroll_x) ||
745 isfullbox(tux_x, tux_y, scroll_x))
747 trygrabdistro(tux_x, tux_y - 32, scroll_x,
749 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
750 bumpbrick(tux_x, tux_y, scroll_x);
751 tryemptybox(tux_x, tux_y, scroll_x);
754 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
755 isfullbox(tux_x + 31, tux_y, scroll_x))
757 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
759 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
760 bumpbrick(tux_x + 31, tux_y, scroll_x);
761 tryemptybox(tux_x + 31, tux_y, scroll_x);
765 /* Get a distro from a brick? */
767 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
768 shape(tux_x, tux_y, scroll_x) == 'y')
770 add_bouncy_distro(((tux_x + scroll_x + 1)
774 if (counting_distros == NO)
776 counting_distros = YES;
777 distro_counter = 100;
780 if (distro_counter <= 0)
781 change(tux_x, tux_y, scroll_x, 'a');
783 play_sound(sounds[SND_DISTRO]);
784 score = score + SCORE_DISTRO;
787 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
788 shape(tux_x + 31, tux_y, scroll_x) == 'y')
790 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
794 if (counting_distros == NO)
796 counting_distros = YES;
797 distro_counter = 100;
800 if (distro_counter <= 0)
801 change(tux_x + 31, tux_y, scroll_x, 'a');
803 play_sound(sounds[SND_DISTRO]);
804 score = score + SCORE_DISTRO;
812 tux_y = (tux_y / 32) * 32 + 30;
818 tux_y = (tux_y / 32) * 32 - 32;
823 jump_counter = MAX_JUMP_COUNT;
833 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
834 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
836 if (tux_size == BIG && !tux_duck)
838 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
839 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
844 /* Enough distros for a One-up? */
846 if (distros >= DISTROS_LIFEUP)
848 distros = distros - DISTROS_LIFEUP;
849 if(lives < MAX_LIVES)
851 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
855 /* Keep in-bounds, vertically: */
859 else if (tux_y > 480)
865 /* Slow down horizontally: */
869 if (right == UP && left == UP)
871 if (isice(tux_x, tux_y + 32, scroll_x) ||
872 !issolid(tux_x, tux_y + 32, scroll_x))
874 /* Slowly on ice or in air: */
883 /* Quickly, otherwise: */
890 /* Drop vertically: */
892 if (!issolid(tux_x, tux_y + 32, scroll_x))
894 tux_ym = tux_ym + GRAVITY;
906 /* ---- DONE HANDLING TUX! --- */
909 /* Handle bouncy distros: */
911 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
913 if (bouncy_distros[i].alive)
915 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
917 bouncy_distros[i].ym++;
919 if (bouncy_distros[i].ym >= 0)
920 bouncy_distros[i].alive = NO;
925 /* Handle broken bricks: */
927 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
929 if (broken_bricks[i].alive)
931 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
932 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
934 broken_bricks[i].ym++;
936 if (broken_bricks[i].ym >= 0)
937 broken_bricks[i].alive = NO;
942 /* Handle distro counting: */
944 if (counting_distros == YES)
948 if (distro_counter <= 0)
949 counting_distros = -1;
953 /* Handle bouncy bricks: */
955 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
957 if (bouncy_bricks[i].alive)
959 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
960 bouncy_bricks[i].offset_m);
964 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
965 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
970 if (bouncy_bricks[i].offset == 0)
971 bouncy_bricks[i].alive = NO;
976 /* Handle floating scores: */
978 for (i = 0; i < NUM_FLOATING_SCORES; i++)
980 if (floating_scores[i].alive)
982 floating_scores[i].y = floating_scores[i].y - 2;
983 floating_scores[i].timer--;
985 if (floating_scores[i].timer <= 0)
986 floating_scores[i].alive = NO;
991 /* Handle bullets: */
993 for (i = 0; i < NUM_BULLETS; i++)
995 if (bullets[i].alive)
997 bullets[i].x = bullets[i].x + bullets[i].xm;
998 bullets[i].y = bullets[i].y + bullets[i].ym;
1000 if (issolid(bullets[i].x, bullets[i].y, 0))
1002 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1003 bullets[i].alive = NO;
1006 if (bullets[i].ym >= 0)
1008 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1010 bullets[i].ym = -bullets[i].ym;
1014 bullets[i].ym = bullets[i].ym + GRAVITY;
1016 if (bullets[i].x < scroll_x ||
1017 bullets[i].x > scroll_x + 640)
1019 bullets[i].alive = NO;
1024 if (bullets[i].alive)
1026 for (j = 0; j < NUM_BAD_GUYS; j++)
1028 if (bad_guys[j].alive && !bad_guys[j].dying)
1030 if (bullets[i].x >= bad_guys[j].x - 4 &&
1031 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1032 bullets[i].y >= bad_guys[j].y - 4 &&
1033 bullets[i].y <= bad_guys[j].y + 32 + 4)
1035 /* Kill the bad guy! */
1037 bullets[i].alive = 0;
1038 bad_guys[j].dying = FALLING;
1039 bad_guys[j].ym = -8;
1042 /* Gain some points: */
1044 if (bad_guys[j].kind == BAD_BSOD)
1046 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1047 50 * score_multiplier);
1049 else if (bad_guys[j].kind == BAD_LAPTOP)
1051 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1052 25 * score_multiplier);
1056 /* Play death sound: */
1057 play_sound(sounds[SND_FALL]);
1065 /* Handle background timer: */
1067 if (super_bkgd_time)
1071 /* Handle invincibility timer: */
1074 if (tux_invincible_time > 50)
1076 tux_invincible_time--;
1079 if (!playing_music())
1080 play_music( herring_song, 1 );
1084 if (current_music == HERRING_MUSIC)
1086 /* stop the herring_song, now play the level_song ! */
1087 current_music = LEVEL_MUSIC;
1091 if (!playing_music())
1093 if (time_left <= TIME_WARNING)
1094 play_music( level_song_fast, 1 );
1096 play_music( level_song, 1 );
1099 if (tux_invincible_time > 0)
1100 tux_invincible_time--;
1104 /* Handle upgrades: */
1106 for (i = 0; i < NUM_UPGRADES; i++)
1108 if (upgrades[i].alive)
1110 if (upgrades[i].height < 32)
1114 upgrades[i].height++;
1120 if (upgrades[i].kind == UPGRADE_MINTS ||
1121 upgrades[i].kind == UPGRADE_HERRING)
1123 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1124 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1126 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1127 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1129 if (upgrades[i].ym > 0)
1131 if (upgrades[i].kind == UPGRADE_MINTS)
1135 else if (upgrades[i].kind == UPGRADE_HERRING)
1137 upgrades[i].ym = -24;
1140 upgrades[i].y = (upgrades[i].y / 32) * 32;
1144 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1146 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1148 upgrades[i].xm = -upgrades[i].xm;
1153 /* Off the screen? Kill it! */
1155 if (upgrades[i].x < scroll_x)
1156 upgrades[i].alive = NO;
1159 /* Did the player grab it? */
1161 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1162 tux_x + scroll_x <= upgrades[i].x + 32 &&
1163 tux_y >= upgrades[i].y - 32 &&
1164 tux_y <= upgrades[i].y + 32)
1166 /* Remove the upgrade: */
1168 upgrades[i].alive = NO;
1171 /* Affect the player: */
1173 if (upgrades[i].kind == UPGRADE_MINTS)
1175 play_sound(sounds[SND_EXCELLENT]);
1177 super_bkgd_time = 8;
1179 else if (upgrades[i].kind == UPGRADE_COFFEE)
1181 play_sound(sounds[SND_COFFEE]);
1182 tux_got_coffee = YES;
1183 super_bkgd_time = 4;
1185 else if (upgrades[i].kind == UPGRADE_HERRING)
1187 play_sound(sounds[SND_HERRING]);
1188 tux_invincible_time = TUX_INVINCIBLE_TIME;
1189 super_bkgd_time = 4;
1190 /* play the herring song ^^ */
1191 current_music = HERRING_MUSIC;
1192 if (playing_music())
1194 play_music( herring_song, 1 );
1202 /* Handle bad guys: */
1204 for (i = 0; i < NUM_BAD_GUYS; i++)
1206 if (bad_guys[i].alive)
1208 if (bad_guys[i].seen)
1210 if (bad_guys[i].kind == BAD_BSOD)
1212 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1214 /* Move left/right: */
1216 if (bad_guys[i].dying == NO ||
1217 bad_guys[i].dying == FALLING)
1219 if (bad_guys[i].dir == RIGHT)
1220 bad_guys[i].x = bad_guys[i].x + 4;
1221 else if (bad_guys[i].dir == LEFT)
1222 bad_guys[i].x = bad_guys[i].x - 4;
1226 /* Move vertically: */
1228 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1231 /* Bump into things horizontally: */
1233 if (!bad_guys[i].dying)
1235 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1236 bad_guys[i].dir = !bad_guys[i].dir;
1240 /* Bump into other bad guys: */
1242 for (j = 0; j < NUM_BAD_GUYS; j++)
1244 if (j != i && bad_guys[j].alive &&
1245 !bad_guys[j].dying && !bad_guys[i].dying &&
1246 bad_guys[i].x >= bad_guys[j].x - 32 &&
1247 bad_guys[i].x <= bad_guys[j].x + 32 &&
1248 bad_guys[i].y >= bad_guys[j].y - 32 &&
1249 bad_guys[i].y <= bad_guys[j].y + 32)
1251 bad_guys[i].dir = !bad_guys[i].dir;
1256 /* Fall if we get off the ground: */
1258 if (bad_guys[i].dying != FALLING)
1260 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1261 bad_guys[i].ym < MAX_YM)
1263 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1269 if (bad_guys[i].ym > 0)
1271 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1277 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1279 if (bad_guys[i].y > 480)
1280 bad_guys[i].alive = NO;
1282 else if (bad_guys[i].kind == BAD_LAPTOP)
1284 /* --- LAPTOP MONSTER: --- */
1286 /* Move left/right: */
1288 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1290 if (bad_guys[i].dying == NO ||
1291 bad_guys[i].dying == FALLING)
1293 if (bad_guys[i].dir == RIGHT)
1294 bad_guys[i].x = bad_guys[i].x + 4;
1295 else if (bad_guys[i].dir == LEFT)
1296 bad_guys[i].x = bad_guys[i].x - 4;
1299 else if (bad_guys[i].mode == KICK)
1301 if (bad_guys[i].dir == RIGHT)
1302 bad_guys[i].x = bad_guys[i].x + 16;
1303 else if (bad_guys[i].dir == LEFT)
1304 bad_guys[i].x = bad_guys[i].x - 16;
1308 /* Move vertically: */
1310 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1313 /* Bump into things horizontally: */
1315 if (!bad_guys[i].dying)
1317 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1319 bad_guys[i].dir = !bad_guys[i].dir;
1321 if (bad_guys[i].mode == KICK)
1322 play_sound(sounds[SND_RICOCHET]);
1327 /* Bump into other bad guys: */
1329 for (j = 0; j < NUM_BAD_GUYS; j++)
1331 if (j != i && bad_guys[j].alive &&
1332 !bad_guys[j].dying && !bad_guys[i].dying &&
1333 bad_guys[i].x >= bad_guys[j].x - 32 &&
1334 bad_guys[i].x <= bad_guys[j].x + 32 &&
1335 bad_guys[i].y >= bad_guys[j].y - 32 &&
1336 bad_guys[i].y <= bad_guys[j].y + 32)
1338 if (bad_guys[i].mode != KICK)
1339 bad_guys[i].dir = !bad_guys[i].dir;
1342 /* We're in kick mode, kill the other guy: */
1344 bad_guys[j].dying = FALLING;
1345 bad_guys[j].ym = -8;
1346 play_sound(sounds[SND_FALL]);
1348 add_score(bad_guys[i].x - scroll_x,
1349 bad_guys[i].y, 100);
1355 /* Fall if we get off the ground: */
1357 if (bad_guys[i].dying != FALLING)
1359 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1360 bad_guys[i].ym < MAX_YM)
1362 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1368 if (bad_guys[i].ym > 0)
1370 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1376 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1378 if (bad_guys[i].y > 480)
1379 bad_guys[i].alive = NO;
1381 else if (bad_guys[i].kind == BAD_MONEY)
1383 /* --- MONEY BAGS: --- */
1386 /* Move vertically: */
1388 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1391 /* Fall if we get off the ground: */
1393 if (bad_guys[i].dying != FALLING)
1395 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1397 if (bad_guys[i].ym < MAX_YM)
1399 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1406 if (bad_guys[i].ym > 0)
1408 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1409 bad_guys[i].ym = -MAX_YM;
1414 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1416 if (bad_guys[i].y > 480)
1417 bad_guys[i].alive = NO;
1419 else if (bad_guys[i].kind == -1)
1423 /* Kill it if the player jumped on it: */
1425 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1426 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1427 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1428 tux_y >= bad_guys[i].y - 32 &&
1429 tux_y <= bad_guys[i].y - 8
1433 if (bad_guys[i].kind == BAD_BSOD)
1435 bad_guys[i].dying = SQUISHED;
1436 bad_guys[i].timer = 16;
1437 tux_ym = -KILL_BOUNCE_YM;
1439 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1440 50 * score_multiplier);
1442 play_sound(sounds[SND_SQUISH]);
1444 else if (bad_guys[i].kind == BAD_LAPTOP)
1446 if (bad_guys[i].mode != FLAT)
1450 play_sound(sounds[SND_STOMP]);
1451 bad_guys[i].mode = FLAT;
1453 bad_guys[i].timer = 64;
1461 bad_guys[i].mode = KICK;
1462 play_sound(sounds[SND_KICK]);
1464 if (tux_x + scroll_x <= bad_guys[i].x)
1465 bad_guys[i].dir = RIGHT;
1467 bad_guys[i].dir = LEFT;
1469 bad_guys[i].timer = 8;
1472 tux_ym = -KILL_BOUNCE_YM;
1474 add_score(bad_guys[i].x - scroll_x,
1476 25 * score_multiplier);
1478 /* play_sound(sounds[SND_SQUISH]); */
1480 else if (bad_guys[i].kind == -1)
1487 /* Hurt the player if he just touched it: */
1489 if (!bad_guys[i].dying && !tux_dying &&
1491 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1492 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1493 tux_y >= bad_guys[i].y - 32 &&
1494 tux_y <= bad_guys[i].y + 32)
1496 if (bad_guys[i].mode == FLAT)
1500 bad_guys[i].mode = KICK;
1501 play_sound(sounds[SND_KICK]);
1503 if (tux_x + scroll_x <= bad_guys[i].x)
1505 bad_guys[i].dir = RIGHT;
1506 bad_guys[i].x = bad_guys[i].x + 16;
1510 bad_guys[i].dir = LEFT;
1511 bad_guys[i].x = bad_guys[i].x - 16;
1514 bad_guys[i].timer = 8;
1516 else if (bad_guys[i].mode == KICK)
1518 if (tux_y < bad_guys[i].y - 16 &&
1519 bad_guys[i].timer == 0)
1521 /* Step on (stop being kicked) */
1523 bad_guys[i].mode = FLAT;
1524 play_sound(sounds[SND_STOMP]);
1525 bad_guys[i].timer = 64;
1529 /* Hurt if you get hit by kicked laptop: */
1531 if (bad_guys[i].timer == 0)
1533 if (tux_invincible_time == 0)
1539 bad_guys[i].dying = FALLING;
1540 bad_guys[i].ym = -8;
1541 play_sound(sounds[SND_FALL]);
1548 if (tux_invincible_time == 0)
1554 bad_guys[i].dying = FALLING;
1555 bad_guys[i].ym = -8;
1556 play_sound(sounds[SND_FALL]);
1562 /* Handle mode timer: */
1564 if (bad_guys[i].mode == FLAT)
1566 bad_guys[i].timer--;
1568 if (bad_guys[i].timer <= 0)
1569 bad_guys[i].mode = NORMAL;
1571 else if (bad_guys[i].mode == KICK)
1573 if (bad_guys[i].timer > 0)
1574 bad_guys[i].timer--;
1578 /* Handle dying timer: */
1580 if (bad_guys[i].dying == SQUISHED)
1582 bad_guys[i].timer--;
1585 /* Remove it if time's up: */
1587 if (bad_guys[i].timer <= 0)
1588 bad_guys[i].alive = NO;
1592 /* Remove if it's far off the screen: */
1594 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1595 bad_guys[i].alive = NO;
1599 /* Once it's on screen, it's activated! */
1601 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1602 bad_guys[i].seen = YES;
1608 /* Handle skidding: */
1610 if (tux_skidding > 0)
1618 /* --- GAME DRAW! --- */
1626 if (tux_dying && (frame % 4) == 0)
1627 clearscreen(255, 255, 255);
1630 if (super_bkgd_time == 0)
1631 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1633 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1637 /* Draw background: */
1639 for (y = 0; y < 15; y++)
1641 for (x = 0; x < 21; x++)
1643 drawshape(x * 32 - (scroll_x % 32), y * 32,
1644 tiles[y][x + (scroll_x / 32)]);
1649 /* (Bouncy bricks): */
1651 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1653 if (bouncy_bricks[i].alive)
1655 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1656 bouncy_bricks[i].x <= scroll_x + 640)
1658 dest.x = bouncy_bricks[i].x - scroll_x;
1659 dest.y = bouncy_bricks[i].y;
1663 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1668 drawshape(bouncy_bricks[i].x - scroll_x,
1669 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1670 bouncy_bricks[i].shape);
1678 for (i = 0; i < NUM_BAD_GUYS; i++)
1680 if (bad_guys[i].alive &&
1681 bad_guys[i].x > scroll_x - 32 &&
1682 bad_guys[i].x < scroll_x + 640)
1684 if (bad_guys[i].kind == BAD_BSOD)
1686 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1688 if (bad_guys[i].dying == NO)
1692 if (bad_guys[i].dir == LEFT)
1694 drawimage(img_bsod_left[(frame / 5) % 4],
1695 bad_guys[i].x - scroll_x,
1701 drawimage(img_bsod_right[(frame / 5) % 4],
1702 bad_guys[i].x - scroll_x,
1707 else if (bad_guys[i].dying == FALLING)
1711 if (bad_guys[i].dir == LEFT)
1713 drawimage(img_bsod_falling_left,
1714 bad_guys[i].x - scroll_x,
1720 drawimage(img_bsod_falling_right,
1721 bad_guys[i].x - scroll_x,
1726 else if (bad_guys[i].dying == SQUISHED)
1728 /* Dying - Squished: */
1730 if (bad_guys[i].dir == LEFT)
1732 drawimage(img_bsod_squished_left,
1733 bad_guys[i].x - scroll_x,
1739 drawimage(img_bsod_squished_right,
1740 bad_guys[i].x - scroll_x,
1746 else if (bad_guys[i].kind == BAD_LAPTOP)
1748 /* --- LAPTOP MONSTER: --- */
1750 if (bad_guys[i].dying == NO)
1754 if (bad_guys[i].mode == NORMAL)
1758 if (bad_guys[i].dir == LEFT)
1760 drawimage(img_laptop_left[(frame / 5) % 3],
1761 bad_guys[i].x - scroll_x,
1767 drawimage(img_laptop_right[(frame / 5) % 3],
1768 bad_guys[i].x - scroll_x,
1777 if (bad_guys[i].dir == LEFT)
1779 drawimage(img_laptop_flat_left,
1780 bad_guys[i].x - scroll_x,
1786 drawimage(img_laptop_flat_right,
1787 bad_guys[i].x - scroll_x,
1793 else if (bad_guys[i].dying == FALLING)
1797 if (bad_guys[i].dir == LEFT)
1799 drawimage(img_laptop_falling_left,
1800 bad_guys[i].x - scroll_x,
1806 drawimage(img_laptop_falling_right,
1807 bad_guys[i].x - scroll_x,
1813 else if (bad_guys[i].kind == BAD_MONEY)
1815 if (bad_guys[i].ym > -16)
1817 if (bad_guys[i].dir == LEFT)
1819 drawimage(img_money_left[0],
1820 bad_guys[i].x - scroll_x,
1826 drawimage(img_money_right[0],
1827 bad_guys[i].x - scroll_x,
1834 if (bad_guys[i].dir == LEFT)
1836 drawimage(img_money_left[1],
1837 bad_guys[i].x - scroll_x,
1843 drawimage(img_money_right[1],
1844 bad_guys[i].x - scroll_x,
1850 else if (bad_guys[i].kind == -1)
1858 if (right == UP && left == UP)
1865 if ((fire == DOWN && (frame % 2) == 0) ||
1867 tux_frame_main = (tux_frame_main + 1) % 4;
1869 tux_frame = tux_frame_main;
1876 if (tux_safe == 0 || (frame % 2) == 0)
1878 if (tux_size == SMALL)
1880 if (tux_invincible_time)
1884 if (tux_dir == RIGHT)
1886 drawimage(cape_right[frame % 2],
1892 drawimage(cape_left[frame % 2],
1899 if (!tux_got_coffee)
1901 if (tux_dir == RIGHT)
1903 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1907 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1912 /* Tux got coffee! */
1914 if (tux_dir == RIGHT)
1916 drawimage(firetux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1920 drawimage(firetux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1926 if (tux_invincible_time)
1930 if (tux_dir == RIGHT)
1932 drawimage(bigcape_right[frame % 2],
1933 tux_x - 8 - 16, tux_y - 32,
1938 drawimage(bigcape_left[frame % 2],
1939 tux_x - 8, tux_y - 32,
1944 if (!tux_got_coffee)
1950 if (!jumping || tux_ym > 0)
1952 if (tux_dir == RIGHT)
1954 drawimage(bigtux_right[tux_frame],
1955 tux_x - 8, tux_y - 32,
1960 drawimage(bigtux_left[tux_frame],
1961 tux_x - 8, tux_y - 32,
1967 if (tux_dir == RIGHT)
1969 drawimage(bigtux_right_jump,
1970 tux_x - 8, tux_y - 32,
1975 drawimage(bigtux_left_jump,
1976 tux_x - 8, tux_y - 32,
1983 if (tux_dir == RIGHT)
1985 drawimage(skidtux_right,
1986 tux_x - 8, tux_y - 32,
1991 drawimage(skidtux_left,
1992 tux_x - 8, tux_y - 32,
1999 if (tux_dir == RIGHT)
2001 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2006 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2013 /* Tux has coffee! */
2019 if (!jumping || tux_ym > 0)
2021 if (tux_dir == RIGHT)
2023 drawimage(bigfiretux_right[tux_frame],
2024 tux_x - 8, tux_y - 32,
2029 drawimage(bigfiretux_left[tux_frame],
2030 tux_x - 8, tux_y - 32,
2036 if (tux_dir == RIGHT)
2038 drawimage(bigfiretux_right_jump,
2039 tux_x - 8, tux_y - 32,
2044 drawimage(bigfiretux_left_jump,
2045 tux_x - 8, tux_y - 32,
2052 if (tux_dir == RIGHT)
2054 drawimage(skidfiretux_right,
2055 tux_x - 8, tux_y - 32,
2060 drawimage(skidfiretux_left,
2061 tux_x - 8, tux_y - 32,
2068 if (tux_dir == RIGHT)
2070 drawimage(duckfiretux_right, tux_x - 8, tux_y - 16,
2075 drawimage(duckfiretux_left, tux_x - 8, tux_y - 16,
2086 for (i = 0; i < NUM_BULLETS; i++)
2088 if (bullets[i].alive &&
2089 bullets[i].x >= scroll_x - 4 &&
2090 bullets[i].x <= scroll_x + 640)
2092 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2098 /* (Floating scores): */
2100 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2102 if (floating_scores[i].alive)
2104 sprintf(str, "%d", floating_scores[i].value);
2106 floating_scores[i].x + 16 - strlen(str) * 8,
2107 floating_scores[i].y,
2108 letters_gold, NO_UPDATE);
2115 for (i = 0; i < NUM_UPGRADES; i++)
2117 if (upgrades[i].alive)
2119 if (upgrades[i].height < 32)
2123 dest.x = upgrades[i].x - scroll_x;
2124 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2126 dest.h = upgrades[i].height;
2131 src.h = upgrades[i].height;
2133 if (upgrades[i].kind == UPGRADE_MINTS)
2134 SDL_BlitSurface(img_mints, &src, screen, &dest);
2135 else if (upgrades[i].kind == UPGRADE_COFFEE)
2136 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2137 else if (upgrades[i].kind == UPGRADE_HERRING)
2138 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2142 if (upgrades[i].kind == UPGRADE_MINTS)
2144 drawimage(img_mints,
2145 upgrades[i].x - scroll_x, upgrades[i].y,
2148 else if (upgrades[i].kind == UPGRADE_COFFEE)
2150 drawimage(img_coffee,
2151 upgrades[i].x - scroll_x, upgrades[i].y,
2154 else if (upgrades[i].kind == UPGRADE_HERRING)
2156 drawimage(img_golden_herring,
2157 upgrades[i].x - scroll_x, upgrades[i].y,
2165 /* (Bouncy distros): */
2167 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2169 if (bouncy_distros[i].alive)
2171 drawimage(img_distro[0],
2172 bouncy_distros[i].x - scroll_x,
2173 bouncy_distros[i].y,
2179 /* (Broken bricks): */
2181 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2183 if (broken_bricks[i].alive)
2185 src.x = rand() % 16;
2186 src.y = rand() % 16;
2190 dest.x = broken_bricks[i].x - scroll_x;
2191 dest.y = broken_bricks[i].y;
2195 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2202 sprintf(str, "%d", score);
2203 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2204 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2206 sprintf(str, "%d", highscore);
2207 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2208 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2210 if (time_left >= TIME_WARNING || (frame % 10) < 5)
2212 sprintf(str, "%d", time_left);
2213 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2214 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2217 sprintf(str, "%d", distros);
2218 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2219 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2221 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE);
2223 for(i=0; i < lives; ++i)
2225 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2229 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2234 /* (Update it all!) */
2241 /* --- GAME LOOP! --- */
2246 Uint32 last_time, now_time;
2250 clearscreen(0, 0, 0);
2254 /* Init the game: */
2262 highscore = load_hs();
2265 /* --- MAIN GAME LOOP!!! --- */
2277 last_time = SDL_GetTicks();
2281 /* Handle events: */
2287 /* Handle actions: */
2289 if(!game_pause && !show_menu)
2291 if (game_action() == 0)
2293 /* == 0: no more lives */
2294 /* == -1: continues */
2301 /*Draw the current scene to the screen */
2304 /* Keep playing music: */
2307 if (!playing_music())
2309 switch (current_music)
2312 if (time_left <= TIME_WARNING)
2313 play_music(level_song_fast, 1);
2315 play_music(level_song, 1);
2318 play_music(herring_song, 1);
2320 case HURRYUP_MUSIC: // keep the compiler happy
2321 case NO_MUSIC: // keep the compiler happy for the moment :-)
2327 /* Time stops in pause mode */
2328 if(game_pause || show_menu )
2333 /* Pause til next frame: */
2335 now_time = SDL_GetTicks();
2336 if (now_time < last_time + FPS)
2337 SDL_Delay(last_time + FPS - now_time);
2342 if ((frame % 10) == 0 && time_left > 0)
2346 /* Stop the music; it will start again, faster! */
2347 if (time_left == TIME_WARNING)
2354 while (!done && !quit);
2356 if (playing_music())
2367 /* Initialize the game stuff: */
2379 /* Load data for this level: */
2381 void loadlevel(void)
2392 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2393 bouncy_distros[i].alive = NO;
2395 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2396 broken_bricks[i].alive = NO;
2398 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2399 bouncy_bricks[i].alive = NO;
2401 for (i = 0; i < NUM_BAD_GUYS; i++)
2402 bad_guys[i].alive = NO;
2404 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2405 floating_scores[i].alive = NO;
2407 for (i = 0; i < NUM_UPGRADES; i++)
2408 upgrades[i].alive = NO;
2410 for (i = 0; i < NUM_BULLETS; i++)
2411 bullets[i].alive = NO;
2414 /* Load data file: */
2416 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2417 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2418 fi = fopen(filename, "r");
2429 /* Load header info: */
2434 strcpy(levelname, str);
2435 levelname[strlen(levelname)-1] = '\0';
2439 strcpy(leveltheme, str);
2440 leveltheme[strlen(leveltheme)-1] = '\0';
2444 /* (Time to beat level) */
2446 time_left = atoi(str);
2448 /* (Song file for this level) */
2449 fgets(str, sizeof(song_title), fi);
2450 strcpy(song_title, str);
2451 song_title[strlen(song_title)-1] = '\0';
2455 /* (Level background color) */
2457 bkgd_red = atoi(str);
2459 bkgd_green= atoi(str);
2461 bkgd_blue = atoi(str);
2465 level_width = atoi(str);
2468 /* Allocate some space for the line-reading! */
2470 line = (char *) malloc(sizeof(char) * (level_width + 5));
2473 fprintf(stderr, "Couldn't allocate space to load level data!");
2478 /* Load the level lines: */
2480 for (y = 0; y < 15; y++)
2482 if(fgets(line, level_width + 5, fi) == NULL)
2484 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2487 line[strlen(line) - 1] = '\0';
2488 tiles[y] = strdup(line);
2494 /* Activate bad guys: */
2496 for (y = 0; y < 15; y++)
2498 for (x = 0; x < level_width; x++)
2500 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2502 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2517 tux_got_coffee = NO;
2518 tux_invincible_time = 0;
2522 tux_safe = TUX_SAFE_TIME;
2538 score_multiplier = 1;
2539 super_bkgd_time = 0;
2541 counting_distros = NO;
2546 /* set current song/music */
2547 current_music = LEVEL_MUSIC;
2551 clearscreen(0, 0, 0);
2553 sprintf(str, "LEVEL %d", level);
2554 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2556 sprintf(str, "%s", levelname);
2557 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2559 sprintf(str, "TUX x %d", lives);
2560 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2570 /* Load a level-specific graphic... */
2572 SDL_Surface * load_level_image(char * file, int use_alpha)
2576 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2578 return(load_image(fname, use_alpha));
2582 /* Load graphics: */
2584 void loadlevelgfx(void)
2586 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2587 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2589 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2590 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2591 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2592 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2594 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2595 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2596 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2597 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2599 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2600 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2601 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2602 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2608 void loadlevelsong(void)
2612 char * song_subtitle;
2614 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2615 strlen(song_title) + 8));
2616 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2617 level_song = load_song(song_path);
2621 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2622 strlen(song_title) + 8 + 5));
2623 song_subtitle = strdup(song_title);
2624 strcpy(strstr(song_subtitle, "."), "\0");
2625 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(song_title, "."));
2626 level_song_fast = load_song(song_path);
2627 free(song_subtitle);
2632 /* Free graphics data for this level: */
2634 void unloadlevelgfx(void)
2638 for (i = 0; i < 2; i++)
2640 SDL_FreeSurface(img_brick[i]);
2642 for (i = 0; i < 4; i++)
2644 SDL_FreeSurface(img_solid[i]);
2645 SDL_FreeSurface(img_bkgd[0][i]);
2646 SDL_FreeSurface(img_bkgd[1][i]);
2651 /* Free music data for this level: */
2653 void unloadlevelsong(void)
2655 free_music(level_song);
2659 /* Load graphics/sounds shared between all levels: */
2661 void loadshared(void)
2664 char * herring_song_path; /* for loading herring song*/
2668 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2671 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2674 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2677 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2680 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2683 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2686 firetux_right[0] = load_image(DATA_PREFIX "/images/shared/firetux-right-0.png",
2689 firetux_right[1] = load_image(DATA_PREFIX "/images/shared/firetux-right-1.png",
2692 firetux_right[2] = load_image(DATA_PREFIX "/images/shared/firetux-right-2.png",
2695 firetux_left[0] = load_image(DATA_PREFIX "/images/shared/firetux-left-0.png",
2698 firetux_left[1] = load_image(DATA_PREFIX "/images/shared/firetux-left-1.png",
2701 firetux_left[2] = load_image(DATA_PREFIX "/images/shared/firetux-left-2.png",
2704 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2707 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2710 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2713 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2716 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2719 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2722 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2726 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2728 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2731 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2734 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2738 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2741 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2745 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2749 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2753 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2756 bigfiretux_right[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
2759 bigfiretux_right[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
2762 bigfiretux_right[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
2765 bigfiretux_right_jump =
2766 load_image(DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
2768 bigfiretux_left[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
2771 bigfiretux_left[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
2774 bigfiretux_left[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
2777 bigfiretux_left_jump =
2778 load_image(DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
2781 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2785 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2789 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2793 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2797 ducktux_right = load_image(DATA_PREFIX
2798 "/images/shared/ducktux-right.png",
2801 ducktux_left = load_image(DATA_PREFIX
2802 "/images/shared/ducktux-left.png",
2805 skidtux_right = load_image(DATA_PREFIX
2806 "/images/shared/skidtux-right.png",
2809 skidtux_left = load_image(DATA_PREFIX
2810 "/images/shared/skidtux-left.png",
2813 duckfiretux_right = load_image(DATA_PREFIX
2814 "/images/shared/duckfiretux-right.png",
2817 duckfiretux_left = load_image(DATA_PREFIX
2818 "/images/shared/duckfiretux-left.png",
2821 skidfiretux_right = load_image(DATA_PREFIX
2822 "/images/shared/skidfiretux-right.png",
2825 skidfiretux_left = load_image(DATA_PREFIX
2826 "/images/shared/skidfiretux-left.png",
2832 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2834 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2841 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2843 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2846 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2849 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2855 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2856 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2862 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2864 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2870 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2873 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2876 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2879 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2883 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2886 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2889 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2892 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2900 img_bsod_left[0] = load_image(DATA_PREFIX
2901 "/images/shared/bsod-left-0.png",
2904 img_bsod_left[1] = load_image(DATA_PREFIX
2905 "/images/shared/bsod-left-1.png",
2908 img_bsod_left[2] = load_image(DATA_PREFIX
2909 "/images/shared/bsod-left-2.png",
2912 img_bsod_left[3] = load_image(DATA_PREFIX
2913 "/images/shared/bsod-left-3.png",
2916 img_bsod_right[0] = load_image(DATA_PREFIX
2917 "/images/shared/bsod-right-0.png",
2920 img_bsod_right[1] = load_image(DATA_PREFIX
2921 "/images/shared/bsod-right-1.png",
2924 img_bsod_right[2] = load_image(DATA_PREFIX
2925 "/images/shared/bsod-right-2.png",
2928 img_bsod_right[3] = load_image(DATA_PREFIX
2929 "/images/shared/bsod-right-3.png",
2932 img_bsod_squished_left = load_image(DATA_PREFIX
2933 "/images/shared/bsod-squished-left.png",
2936 img_bsod_squished_right = load_image(DATA_PREFIX
2937 "/images/shared/bsod-squished-right.png",
2940 img_bsod_falling_left = load_image(DATA_PREFIX
2941 "/images/shared/bsod-falling-left.png",
2944 img_bsod_falling_right = load_image(DATA_PREFIX
2945 "/images/shared/bsod-falling-right.png",
2951 img_laptop_left[0] = load_image(DATA_PREFIX
2952 "/images/shared/laptop-left-0.png",
2955 img_laptop_left[1] = load_image(DATA_PREFIX
2956 "/images/shared/laptop-left-1.png",
2959 img_laptop_left[2] = load_image(DATA_PREFIX
2960 "/images/shared/laptop-left-2.png",
2963 img_laptop_right[0] = load_image(DATA_PREFIX
2964 "/images/shared/laptop-right-0.png",
2967 img_laptop_right[1] = load_image(DATA_PREFIX
2968 "/images/shared/laptop-right-1.png",
2971 img_laptop_right[2] = load_image(DATA_PREFIX
2972 "/images/shared/laptop-right-2.png",
2975 img_laptop_flat_left = load_image(DATA_PREFIX
2976 "/images/shared/laptop-flat-left.png",
2979 img_laptop_flat_right = load_image(DATA_PREFIX
2980 "/images/shared/laptop-flat-right.png",
2983 img_laptop_falling_left =
2984 load_image(DATA_PREFIX
2985 "/images/shared/laptop-falling-left.png",
2988 img_laptop_falling_right =
2989 load_image(DATA_PREFIX
2990 "/images/shared/laptop-falling-right.png",
2996 img_money_left[0] = load_image(DATA_PREFIX
2997 "/images/shared/bag-left-0.png",
3000 img_money_left[1] = load_image(DATA_PREFIX
3001 "/images/shared/bag-left-1.png",
3004 img_money_right[0] = load_image(DATA_PREFIX
3005 "/images/shared/bag-right-0.png",
3008 img_money_right[1] = load_image(DATA_PREFIX
3009 "/images/shared/bag-right-1.png",
3016 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
3017 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
3022 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
3024 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
3031 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
3034 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
3037 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
3040 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
3046 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
3051 img_golden_herring =
3052 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
3056 /* Super background: */
3058 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
3062 /* Sound effects: */
3064 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
3065 // initialize sounds[i] with the correct pointer's value:
3066 // NULL or something else. And it will be dangerous to
3067 // play with not-initialized pointers.
3068 // This is also true with if (use_music)
3069 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
3071 for (i = 0; i < NUM_SOUNDS; i++)
3072 sounds[i] = load_sound(soundfilenames[i]);
3075 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
3076 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
3078 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
3080 herring_song = load_song(herring_song_path);
3082 free(herring_song_path);
3087 /* Free shared data: */
3089 void unloadshared(void)
3093 for (i = 0; i < 3; i++)
3095 SDL_FreeSurface(tux_right[i]);
3096 SDL_FreeSurface(tux_left[i]);
3097 SDL_FreeSurface(bigtux_right[i]);
3098 SDL_FreeSurface(bigtux_left[i]);
3101 SDL_FreeSurface(bigtux_right_jump);
3102 SDL_FreeSurface(bigtux_left_jump);
3104 for (i = 0; i < 2; i++)
3106 SDL_FreeSurface(cape_right[i]);
3107 SDL_FreeSurface(cape_left[i]);
3108 SDL_FreeSurface(bigcape_right[i]);
3109 SDL_FreeSurface(bigcape_left[i]);
3112 SDL_FreeSurface(ducktux_left);
3113 SDL_FreeSurface(ducktux_right);
3115 SDL_FreeSurface(skidtux_left);
3116 SDL_FreeSurface(skidtux_right);
3118 for (i = 0; i < 4; i++)
3120 SDL_FreeSurface(img_bsod_left[i]);
3121 SDL_FreeSurface(img_bsod_right[i]);
3124 SDL_FreeSurface(img_bsod_squished_left);
3125 SDL_FreeSurface(img_bsod_squished_right);
3127 SDL_FreeSurface(img_bsod_falling_left);
3128 SDL_FreeSurface(img_bsod_falling_right);
3130 for (i = 0; i < 3; i++)
3132 SDL_FreeSurface(img_laptop_left[i]);
3133 SDL_FreeSurface(img_laptop_right[i]);
3136 SDL_FreeSurface(img_laptop_flat_left);
3137 SDL_FreeSurface(img_laptop_flat_right);
3139 SDL_FreeSurface(img_laptop_falling_left);
3140 SDL_FreeSurface(img_laptop_falling_right);
3142 for (i = 0; i < 2; i++)
3144 SDL_FreeSurface(img_money_left[i]);
3145 SDL_FreeSurface(img_money_right[i]);
3148 SDL_FreeSurface(img_box_full);
3149 SDL_FreeSurface(img_box_empty);
3151 SDL_FreeSurface(img_water);
3152 for (i = 0; i < 3; i++)
3153 SDL_FreeSurface(img_waves[i]);
3155 SDL_FreeSurface(img_pole);
3156 SDL_FreeSurface(img_poletop);
3158 for (i = 0; i < 2; i++)
3159 SDL_FreeSurface(img_flag[i]);
3161 SDL_FreeSurface(img_mints);
3162 SDL_FreeSurface(img_coffee);
3164 for (i = 0; i < 4; i++)
3166 SDL_FreeSurface(img_distro[i]);
3167 SDL_FreeSurface(img_cloud[0][i]);
3168 SDL_FreeSurface(img_cloud[1][i]);
3171 SDL_FreeSurface(img_golden_herring);
3173 for (i = 0; i < NUM_SOUNDS; i++)
3174 free_chunk(sounds[i]);
3176 /* free the herring song */
3177 free_music( herring_song );
3181 /* Draw a tile on the screen: */
3183 void drawshape(int x, int y, unsigned char c)
3187 if (c == 'X' || c == 'x')
3188 drawimage(img_brick[0], x, y, NO_UPDATE);
3189 else if (c == 'Y' || c == 'y')
3190 drawimage(img_brick[1], x, y, NO_UPDATE);
3191 else if (c == 'A' || c =='B' || c == '!')
3192 drawimage(img_box_full, x, y, NO_UPDATE);
3194 drawimage(img_box_empty, x, y, NO_UPDATE);
3195 else if (c >= 'C' && c <= 'F')
3196 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3197 else if (c >= 'c' && c <= 'f')
3198 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3199 else if (c >= 'G' && c <= 'J')
3200 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3201 else if (c >= 'g' && c <= 'j')
3202 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3204 drawimage(img_solid[0], x, y, NO_UPDATE);
3206 drawimage(img_solid[1], x, y, NO_UPDATE);
3208 drawimage(img_solid[2], x, y, NO_UPDATE);
3210 drawimage(img_solid[3], x, y, NO_UPDATE);
3213 z = (frame / 2) % 6;
3216 drawimage(img_distro[z], x, y, NO_UPDATE);
3218 drawimage(img_distro[2], x, y, NO_UPDATE);
3220 drawimage(img_distro[1], x, y, NO_UPDATE);
3224 z = (frame / 3) % 3;
3226 drawimage(img_waves[z], x, y, NO_UPDATE);
3229 drawimage(img_poletop, x, y, NO_UPDATE);
3232 drawimage(img_pole, x, y, NO_UPDATE);
3234 /* Mark this as the end position of the level! */
3240 z = (frame / 3) % 2;
3242 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3245 drawimage(img_water, x, y, NO_UPDATE);
3249 /* What shape is at some position? */
3251 unsigned char shape(int x, int y, int sx)
3257 xx = ((x + sx) / 32);
3259 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3270 int issolid(int x, int y, int sx)
3276 if (isbrick(x, y, sx) ||
3277 isbrick(x + 31, y, sx) ||
3279 isice(x + 31, y, sx) ||
3280 (shape(x, y, sx) == '[' ||
3281 shape(x + 31, y, sx) == '[') ||
3282 (shape(x, y, sx) == '=' ||
3283 shape(x + 31, y, sx) == '=') ||
3284 (shape(x, y, sx) == ']' ||
3285 shape(x + 31, y, sx) == ']') ||
3286 (shape(x, y, sx) == 'A' ||
3287 shape(x + 31, y, sx) == 'A') ||
3288 (shape(x, y, sx) == 'B' ||
3289 shape(x + 31, y, sx) == 'B') ||
3290 (shape(x, y, sx) == '!' ||
3291 shape(x + 31, y, sx) == '!') ||
3292 (shape(x, y, sx) == 'a' ||
3293 shape(x + 31, y, sx) == 'a'))
3302 /* Is it a brick? */
3304 int isbrick(int x, int y, int sx)
3310 if (shape(x, y, sx) == 'X' ||
3311 shape(x, y, sx) == 'x' ||
3312 shape(x, y, sx) == 'Y' ||
3313 shape(x, y, sx) == 'y')
3324 int isice(int x, int y, int sx)
3330 if (shape(x, y, sx) == '#')
3339 /* Is it a full box? */
3341 int isfullbox(int x, int y, int sx)
3347 if (shape(x, y, sx) == 'A' ||
3348 shape(x, y, sx) == 'B' ||
3349 shape(x, y, sx) == '!')
3358 /* Edit a piece of the map! */
3360 void change(int x, int y, int sx, unsigned char c)
3365 xx = ((x + sx) / 32);
3367 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3372 /* Break a brick: */
3374 void trybreakbrick(int x, int y, int sx)
3376 if (isbrick(x, y, sx))
3378 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3380 /* Get a distro from it: */
3382 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3385 if (counting_distros == NO)
3387 counting_distros = YES;
3388 distro_counter = 50;
3391 if (distro_counter <= 0)
3392 change(x, y, sx, 'a');
3394 play_sound(sounds[SND_DISTRO]);
3395 score = score + SCORE_DISTRO;
3400 /* Get rid of it: */
3402 change(x, y, sx, '.');
3406 /* Replace it with broken bits: */
3408 add_broken_brick(((x + sx + 1) / 32) * 32,
3412 /* Get some score: */
3414 play_sound(sounds[SND_BRICK]);
3415 score = score + SCORE_BRICK;
3420 /* Bounce a brick: */
3422 void bumpbrick(int x, int y, int sx)
3424 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3427 play_sound(sounds[SND_BRICK]);
3433 void tryemptybox(int x, int y, int sx)
3435 if (isfullbox(x, y, sx))
3437 if (shape(x, y, sx) == 'A')
3439 /* Box with a distro! */
3441 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3442 (y / 32) * 32 - 32);
3444 play_sound(sounds[SND_DISTRO]);
3445 score = score + SCORE_DISTRO;
3448 else if (shape(x, y, sx) == 'B')
3450 /* Add an upgrade! */
3452 if (tux_size == SMALL)
3454 /* Tux is small, add mints! */
3456 add_upgrade(((x + sx + 1) / 32) * 32,
3462 /* Tux is big, add coffee: */
3464 add_upgrade(((x + sx + 1) / 32) * 32,
3469 play_sound(sounds[SND_UPGRADE]);
3471 else if (shape(x, y, sx) == '!')
3473 /* Add a golden herring */
3475 add_upgrade(((x + sx + 1) / 32) * 32,
3480 /* Empty the box: */
3482 change(x, y, sx, 'a');
3487 /* Try to grab a distro: */
3489 void trygrabdistro(int x, int y, int sx, int bounciness)
3491 if (shape(x, y, sx) == '$')
3493 change(x, y, sx, '.');
3494 play_sound(sounds[SND_DISTRO]);
3496 if (bounciness == BOUNCE)
3498 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3502 score = score + SCORE_DISTRO;
3508 /* Add a bouncy distro: */
3510 void add_bouncy_distro(int x, int y)
3516 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3518 if (!bouncy_distros[i].alive)
3524 bouncy_distros[found].alive = YES;
3525 bouncy_distros[found].x = x;
3526 bouncy_distros[found].y = y;
3527 bouncy_distros[found].ym = -6;
3532 /* Add broken brick pieces: */
3534 void add_broken_brick(int x, int y)
3536 add_broken_brick_piece(x, y, -4, -16);
3537 add_broken_brick_piece(x, y + 16, -6, -12);
3539 add_broken_brick_piece(x + 16, y, 4, -16);
3540 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3544 /* Add a broken brick piece: */
3546 void add_broken_brick_piece(int x, int y, int xm, int ym)
3552 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3554 if (!broken_bricks[i].alive)
3560 broken_bricks[found].alive = YES;
3561 broken_bricks[found].x = x;
3562 broken_bricks[found].y = y;
3563 broken_bricks[found].xm = xm;
3564 broken_bricks[found].ym = ym;
3569 /* Add a bouncy brick piece: */
3571 void add_bouncy_brick(int x, int y)
3577 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3579 if (!bouncy_bricks[i].alive)
3585 bouncy_bricks[found].alive = YES;
3586 bouncy_bricks[found].x = x;
3587 bouncy_bricks[found].y = y;
3588 bouncy_bricks[found].offset = 0;
3589 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3590 bouncy_bricks[found].shape = shape(x, y, 0);
3595 /* Add a bad guy: */
3597 void add_bad_guy(int x, int y, int kind)
3603 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3605 if (!bad_guys[i].alive)
3611 bad_guys[found].alive = YES;
3612 bad_guys[found].mode = NORMAL;
3613 bad_guys[found].dying = NO;
3614 bad_guys[found].timer = 0;
3615 bad_guys[found].kind = kind;
3616 bad_guys[found].x = x;
3617 bad_guys[found].y = y;
3618 bad_guys[found].xm = 0;
3619 bad_guys[found].ym = 0;
3620 bad_guys[found].dir = LEFT;
3621 bad_guys[found].seen = NO;
3628 void add_score(int x, int y, int s)
3633 /* Add the score: */
3638 /* Add a floating score thing to the game: */
3642 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3644 if (!floating_scores[i].alive)
3651 floating_scores[found].alive = YES;
3652 floating_scores[found].x = x;
3653 floating_scores[found].y = y - 16;
3654 floating_scores[found].timer = 8;
3655 floating_scores[found].value = s;
3660 /* Try to bump a bad guy from below: */
3662 void trybumpbadguy(int x, int y, int sx)
3669 for (i = 0; i < NUM_BAD_GUYS; i++)
3671 if (bad_guys[i].alive &&
3672 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3673 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3675 if (bad_guys[i].kind == BAD_BSOD ||
3676 bad_guys[i].kind == BAD_LAPTOP)
3678 bad_guys[i].dying = FALLING;
3679 bad_guys[i].ym = -8;
3680 play_sound(sounds[SND_FALL]);
3688 for (i = 0; i < NUM_UPGRADES; i++)
3690 if (upgrades[i].alive && upgrades[i].height == 32 &&
3691 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3692 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3694 upgrades[i].xm = -upgrades[i].xm;
3695 upgrades[i].ym = -8;
3696 play_sound(sounds[SND_BUMP_UPGRADE]);
3702 /* Add an upgrade: */
3704 void add_upgrade(int x, int y, int kind)
3710 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3712 if (!upgrades[i].alive)
3718 upgrades[found].alive = YES;
3719 upgrades[found].kind = kind;
3720 upgrades[found].x = x;
3721 upgrades[found].y = y;
3722 upgrades[found].xm = 4;
3723 upgrades[found].ym = -4;
3724 upgrades[found].height = 0;
3731 void killtux(int mode)
3735 play_sound(sounds[SND_HURT]);
3737 if (tux_dir == RIGHT)
3739 else if (tux_dir == LEFT)
3742 if (mode == SHRINK && tux_size == BIG)
3745 tux_got_coffee = NO;
3749 tux_safe = TUX_SAFE_TIME;
3760 void add_bullet(int x, int y, int dir, int xm)
3766 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3768 if (!bullets[i].alive)
3774 bullets[found].alive = YES;
3778 bullets[found].x = x + 32;
3779 bullets[found].xm = BULLET_XM + xm;
3783 bullets[found].x = x;
3784 bullets[found].xm = -BULLET_XM + xm;
3787 bullets[found].y = y;
3788 bullets[found].ym = BULLET_STARTING_YM;
3790 play_sound(sounds[SND_SHOOT]);
3795 void drawendscreen(void)
3799 clearscreen(0, 0, 0);
3801 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3803 sprintf(str, "SCORE: %d", score);
3804 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3806 sprintf(str, "DISTROS: %d", distros);
3807 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3813 void drawresultscreen(void)
3817 clearscreen(0, 0, 0);
3819 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3821 sprintf(str, "SCORE: %d", score);
3822 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3824 sprintf(str, "DISTROS: %d", distros);
3825 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3828 /*SDL_Delay(2000);*/