7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 29, 2003
23 #include <sys/types.h>
32 #include "high_scores.h"
39 /* extern variables */
41 extern char* soundfilenames[NUM_SOUNDS];
43 /* Local variables: */
45 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
46 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
47 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
48 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
49 super_bkgd_time, tux_invincible_time, endpos,
50 counting_distros, distro_counter;
51 int left, right, up, down, fire, old_fire;
52 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
53 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
54 SDL_Surface * img_bkgd[2][4];
55 SDL_Surface * img_golden_herring;
56 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
57 * img_laptop_left[3], * img_laptop_right[3],
58 * img_money_left[2], * img_money_right[2];
59 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
60 * img_bsod_falling_left, * img_bsod_falling_right,
61 * img_laptop_flat_left, * img_laptop_flat_right,
62 * img_laptop_falling_left, * img_laptop_falling_right;
63 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
64 * img_super_bkgd, * img_bullet, * img_red_glow;
65 SDL_Surface * img_cloud[2][4];
66 SDL_Surface * tux_life,
67 * tux_right[3], * tux_left[3],
68 * bigtux_right[3], * bigtux_left[3],
69 * bigtux_right_jump, * bigtux_left_jump,
70 * ducktux_right, * ducktux_left,
71 * skidtux_right, * skidtux_left,
72 * firetux_right[3], * firetux_left[3],
73 * bigfiretux_right[3], * bigfiretux_left[3],
74 * bigfiretux_right_jump, * bigfiretux_left_jump,
75 * duckfiretux_right, * duckfiretux_left,
76 * skidfiretux_right, * skidfiretux_left,
77 * cape_right[2], * cape_left[2],
78 * bigcape_right[2], * bigcape_left[2];
82 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
83 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
84 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
85 bad_guy_type bad_guys[NUM_BAD_GUYS];
86 floating_score_type floating_scores[NUM_FLOATING_SCORES];
87 upgrade_type upgrades[NUM_UPGRADES];
88 bullet_type bullets[NUM_BULLETS];
89 st_level current_level;
90 char level_subset[100];
94 /* Local function prototypes: */
96 void levelintro(void);
97 void set_default(void);
99 void loadlevelgfx(void);
100 void loadlevelsong(void);
101 void unloadlevelgfx(void);
102 void unloadlevelsong(void);
103 void loadshared(void);
104 void unloadshared(void);
105 void drawshape(int x, int y, unsigned char c);
106 unsigned char shape(int x, int y, int sx);
107 int issolid(int x, int y, int sx);
108 int isbrick(int x, int y, int sx);
109 int isice(int x, int y, int sx);
110 int isfullbox(int x, int y, int sx);
111 void change(int x, int y, int sx, unsigned char c);
112 void trybreakbrick(int x, int y, int sx);
113 void bumpbrick(int x, int y, int sx);
114 void tryemptybox(int x, int y, int sx);
115 void trygrabdistro(int x, int y, int sx, int bounciness);
116 void add_bouncy_distro(int x, int y);
117 void add_broken_brick(int x, int y);
118 void add_broken_brick_piece(int x, int y, int xm, int ym);
119 void add_bouncy_brick(int x, int y);
120 void add_bad_guy(int x, int y, int kind);
121 void add_score(int x, int y, int s);
122 void trybumpbadguy(int x, int y, int sx);
123 void add_upgrade(int x, int y, int kind);
124 void killtux(int mode);
125 void remove_powerups(void);
126 void add_bullet(int x, int y, int dir, int xm);
127 void drawendscreen(void);
128 void drawresultscreen(void);
130 void levelintro(void)
134 clearscreen(0, 0, 0);
136 sprintf(str, "LEVEL %d", level);
137 drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1);
139 sprintf(str, "%s", current_level.name);
140 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
142 sprintf(str, "TUX x %d", lives);
143 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
150 void set_defaults(void)
156 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
157 bouncy_distros[i].alive = NO;
159 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
160 broken_bricks[i].alive = NO;
162 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
163 bouncy_bricks[i].alive = NO;
165 for (i = 0; i < NUM_BAD_GUYS; i++)
166 bad_guys[i].alive = NO;
168 for (i = 0; i < NUM_FLOATING_SCORES; i++)
169 floating_scores[i].alive = NO;
171 for (i = 0; i < NUM_UPGRADES; i++)
172 upgrades[i].alive = NO;
174 for (i = 0; i < NUM_BULLETS; i++)
175 bullets[i].alive = NO;
185 tux_invincible_time = 0;
189 tux_safe = TUX_SAFE_TIME;
205 score_multiplier = 1;
208 counting_distros = NO;
213 /* set current song/music */
214 current_music = LEVEL_MUSIC;
217 void activate_bad_guys(void)
221 /* Activate bad guys: */
223 for (y = 0; y < 15; y++)
225 for (x = 0; x < current_level.width; x++)
227 if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
229 add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
230 current_level.tiles[y][x] = '.';
237 /* --- GAME EVENT! --- */
239 void game_event(void)
242 while (SDL_PollEvent(&event))
245 if (event.type == SDL_QUIT)
247 /* Quit event - quit: */
251 else if (event.type == SDL_KEYDOWN)
255 key = event.key.keysym.sym;
257 /* Check for menu-events, if the menu is shown */
261 if (key == SDLK_ESCAPE)
263 /* Escape: Open/Close the menu: */
272 else if (key == SDLK_RIGHT)
276 else if (key == SDLK_LEFT)
280 else if (key == SDLK_UP)
284 else if (key == SDLK_DOWN)
288 else if (key == SDLK_LCTRL)
293 else if (event.type == SDL_KEYUP)
297 key = event.key.keysym.sym;
299 if (key == SDLK_RIGHT)
303 else if (key == SDLK_LEFT)
307 else if (key == SDLK_UP)
311 else if (key == SDLK_DOWN)
315 else if (key == SDLK_LCTRL)
319 else if (key == SDLK_p)
329 else if (key == SDLK_TAB && debug_mode == YES)
331 tux_size = !tux_size;
333 else if (key == SDLK_END && debug_mode == YES)
337 else if (key == SDLK_SPACE && debug_mode == YES)
343 else if (event.type == SDL_JOYAXISMOTION)
345 if (event.jaxis.axis == JOY_X)
347 if (event.jaxis.value < -256)
352 if (event.jaxis.value > 256)
357 else if (event.jaxis.axis == JOY_Y)
359 if (event.jaxis.value > 256)
364 /* Handle joystick for the menu */
368 menuaction = MN_DOWN;
374 else if (event.type == SDL_JOYBUTTONDOWN)
376 if (event.jbutton.button == JOY_A)
378 else if (event.jbutton.button == JOY_B)
381 else if (event.type == SDL_JOYBUTTONUP)
383 if (event.jbutton.button == JOY_A)
385 else if (event.jbutton.button == JOY_B)
398 /* --- GAME ACTION! --- */
400 int game_action(void)
404 /* --- HANDLE TUX! --- */
406 /* Handle key and joystick state: */
408 if (!(tux_dying || next_level))
410 if (right == DOWN && left == UP)
414 if (tux_xm < -SKID_XM && !tux_skidding &&
417 tux_skidding = SKID_TIME;
419 play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
425 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
433 if (tux_dir == RIGHT)
435 /* Facing the direction we're jumping? Go full-speed: */
439 tux_xm = tux_xm + WALK_SPEED;
441 if (tux_xm > MAX_WALK_XM)
442 tux_xm = MAX_WALK_XM;
444 else if (fire == DOWN)
446 tux_xm = tux_xm + RUN_SPEED;
448 if (tux_xm > MAX_RUN_XM)
454 /* Not facing the direction we're jumping?
457 tux_xm = tux_xm + WALK_SPEED / 2;
459 if (tux_xm > MAX_WALK_XM / 2)
460 tux_xm = MAX_WALK_XM / 2;
464 else if (left == DOWN && right == UP)
468 if (tux_xm > SKID_XM && !tux_skidding &&
471 tux_skidding = SKID_TIME;
472 play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
477 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
487 /* Facing the direction we're jumping? Go full-speed: */
491 tux_xm = tux_xm - WALK_SPEED;
493 if (tux_xm < -MAX_WALK_XM)
494 tux_xm = -MAX_WALK_XM;
496 else if (fire == DOWN)
498 tux_xm = tux_xm - RUN_SPEED;
500 if (tux_xm < -MAX_RUN_XM)
501 tux_xm = -MAX_RUN_XM;
506 /* Not facing the direction we're jumping?
509 tux_xm = tux_xm - WALK_SPEED / 2;
511 if (tux_xm < -MAX_WALK_XM / 2)
512 tux_xm = -MAX_WALK_XM / 2;
520 if (tux_x >= endpos && endpos != 0)
530 if (jump_counter == 0)
534 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
537 /* If they're not on the ground, or are currently moving
538 vertically, don't jump! */
540 jump_counter = MAX_JUMP_COUNT;
544 /* Make sure we're not standing back up into a solid! */
546 if (tux_size == SMALL || tux_duck == NO ||
547 !issolid(tux_x, tux_y, scroll_x))
551 if (tux_size == SMALL)
552 play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
554 play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
560 /* Keep jumping for a while: */
562 if (jump_counter < MAX_JUMP_COUNT)
564 tux_ym = tux_ym - JUMP_SPEED;
574 if (fire == DOWN && old_fire == UP && tux_got_coffee)
576 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
589 if (tux_size == BIG && tux_duck == YES)
591 /* Make sure we're not standing back up into a solid! */
593 if (!issolid(tux_x, tux_y - 32, scroll_x))
599 } /* (tux_dying || next_level) */
602 /* Tux either died, or reached the end of a level! */
611 /* End of a level! */
619 tux_ym = tux_ym + GRAVITY;
628 /* No more lives!? */
634 if (score > highscore)
641 } /* if (lives < 0) */
644 /* Either way, (re-)load the (next) level... */
647 loadlevel(¤t_level,"default",level);
658 tux_x = tux_x + tux_xm;
659 tux_y = tux_y + tux_ym;
662 /* Keep tux in bounds: */
665 else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
667 scroll_x = scroll_x - ( 160 - tux_x);
674 else if (tux_x > 320 && scroll_x < ((current_level.width * 32) - 640))
676 /* Scroll the screen in past center: */
678 scroll_x = scroll_x + (tux_x - 320);
681 if (scroll_x > ((current_level.width * 32) - 640))
682 scroll_x = ((current_level.width * 32) - 640);
684 else if (tux_x > 608)
686 /* ... unless there's no more to scroll! */
696 if (issolid(tux_x, tux_y + 31, scroll_x) &&
697 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
699 while (issolid(tux_x, tux_y + 31, scroll_x))
710 if (issolid(tux_x, tux_y, scroll_x) &&
711 !issolid(tux_x - tux_xm, tux_y, scroll_x))
713 while (issolid(tux_x, tux_y, scroll_x))
724 if (issolid(tux_x, tux_y + 31, scroll_x))
726 /* Set down properly: */
728 while (issolid(tux_x, tux_y + 31, scroll_x))
737 /* Reset score multiplier (for mutli-hits): */
740 score_multiplier = 1;
750 /* Bump into things: */
752 if (issolid(tux_x, tux_y, scroll_x) ||
753 (tux_size == BIG && !tux_duck &&
754 (issolid(tux_x, tux_y - 32, scroll_x))))
756 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
757 (tux_size == SMALL || tux_duck ||
758 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
760 tux_x = tux_x - tux_xm;
763 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
764 (tux_size == SMALL || tux_duck ||
765 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
773 /* Break bricks and empty boxes: */
777 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
778 isfullbox(tux_x, tux_y - 32, scroll_x))
780 trygrabdistro(tux_x, tux_y - 64, scroll_x,
782 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
784 if (isfullbox(tux_x, tux_y - 32,
787 bumpbrick(tux_x, tux_y - 32,
791 trybreakbrick(tux_x, tux_y - 32, scroll_x);
792 tryemptybox(tux_x, tux_y - 32, scroll_x);
795 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
796 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
798 trygrabdistro(tux_x + 31,
802 trybumpbadguy(tux_x + 31,
806 if (isfullbox(tux_x + 31, tux_y - 32,
809 bumpbrick(tux_x + 31, tux_y - 32,
813 trybreakbrick(tux_x + 31,
816 tryemptybox(tux_x + 31,
823 if (isbrick(tux_x, tux_y, scroll_x) ||
824 isfullbox(tux_x, tux_y, scroll_x))
826 trygrabdistro(tux_x, tux_y - 32, scroll_x,
828 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
829 if (isfullbox(tux_x, tux_y, scroll_x))
830 bumpbrick(tux_x, tux_y, scroll_x);
831 trybreakbrick(tux_x, tux_y, scroll_x);
832 tryemptybox(tux_x, tux_y, scroll_x);
835 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
836 isfullbox(tux_x + 31, tux_y, scroll_x))
838 trygrabdistro(tux_x + 31,
842 trybumpbadguy(tux_x + 31,
845 if (isfullbox(tux_x + 31, tux_y, scroll_x))
846 bumpbrick(tux_x + 31, tux_y, scroll_x);
847 trybreakbrick(tux_x + 31, tux_y, scroll_x);
848 tryemptybox(tux_x + 31, tux_y, scroll_x);
854 /* It's a brick and we're small, make the brick
855 bounce, and grab any distros above it: */
857 if (isbrick(tux_x, tux_y, scroll_x) ||
858 isfullbox(tux_x, tux_y, scroll_x))
860 trygrabdistro(tux_x, tux_y - 32, scroll_x,
862 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
863 bumpbrick(tux_x, tux_y, scroll_x);
864 tryemptybox(tux_x, tux_y, scroll_x);
867 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
868 isfullbox(tux_x + 31, tux_y, scroll_x))
870 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
872 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
873 bumpbrick(tux_x + 31, tux_y, scroll_x);
874 tryemptybox(tux_x + 31, tux_y, scroll_x);
878 /* Get a distro from a brick? */
880 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
881 shape(tux_x, tux_y, scroll_x) == 'y')
883 add_bouncy_distro(((tux_x + scroll_x + 1)
887 if (counting_distros == NO)
889 counting_distros = YES;
890 distro_counter = 100;
893 if (distro_counter <= 0)
894 change(tux_x, tux_y, scroll_x, 'a');
896 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
897 score = score + SCORE_DISTRO;
900 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
901 shape(tux_x + 31, tux_y, scroll_x) == 'y')
903 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
907 if (counting_distros == NO)
909 counting_distros = YES;
910 distro_counter = 100;
913 if (distro_counter <= 0)
914 change(tux_x + 31, tux_y, scroll_x, 'a');
916 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
917 score = score + SCORE_DISTRO;
925 tux_y = (tux_y / 32) * 32 + 30;
931 tux_y = (tux_y / 32) * 32 - 32;
936 jump_counter = MAX_JUMP_COUNT;
946 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
947 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
949 if (tux_size == BIG && !tux_duck)
951 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
952 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
957 /* Enough distros for a One-up? */
959 if (distros >= DISTROS_LIFEUP)
961 distros = distros - DISTROS_LIFEUP;
962 if(lives < MAX_LIVES)
964 /*We want to hear the sound even, if MAX_LIVES is reached*/
965 play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
969 /* Keep in-bounds, vertically: */
973 else if (tux_y > 480)
979 /* Slow down horizontally: */
983 if (right == UP && left == UP)
985 if (isice(tux_x, tux_y + 32, scroll_x) ||
986 !issolid(tux_x, tux_y + 32, scroll_x))
988 /* Slowly on ice or in air: */
997 /* Quickly, otherwise: */
1004 /* Drop vertically: */
1006 if (!issolid(tux_x, tux_y + 32, scroll_x))
1008 tux_ym = tux_ym + GRAVITY;
1010 if (tux_ym > MAX_YM)
1020 /* ---- DONE HANDLING TUX! --- */
1023 /* Handle bouncy distros: */
1025 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
1027 if (bouncy_distros[i].alive)
1029 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
1031 bouncy_distros[i].ym++;
1033 if (bouncy_distros[i].ym >= 0)
1034 bouncy_distros[i].alive = NO;
1039 /* Handle broken bricks: */
1041 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
1043 if (broken_bricks[i].alive)
1045 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
1046 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
1048 broken_bricks[i].ym++;
1050 if (broken_bricks[i].ym >= 0)
1051 broken_bricks[i].alive = NO;
1056 /* Handle distro counting: */
1058 if (counting_distros == YES)
1062 if (distro_counter <= 0)
1063 counting_distros = -1;
1067 /* Handle bouncy bricks: */
1069 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1071 if (bouncy_bricks[i].alive)
1073 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
1074 bouncy_bricks[i].offset_m);
1078 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
1079 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
1082 /* Stop bouncing? */
1084 if (bouncy_bricks[i].offset == 0)
1085 bouncy_bricks[i].alive = NO;
1090 /* Handle floating scores: */
1092 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1094 if (floating_scores[i].alive)
1096 floating_scores[i].y = floating_scores[i].y - 2;
1097 floating_scores[i].timer--;
1099 if (floating_scores[i].timer <= 0)
1100 floating_scores[i].alive = NO;
1105 /* Handle bullets: */
1107 for (i = 0; i < NUM_BULLETS; i++)
1109 if (bullets[i].alive)
1111 bullets[i].x = bullets[i].x + bullets[i].xm;
1112 bullets[i].y = bullets[i].y + bullets[i].ym;
1114 if (issolid(bullets[i].x, bullets[i].y, 0))
1116 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1117 bullets[i].alive = NO;
1120 if (bullets[i].ym >= 0)
1122 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1124 bullets[i].ym = -bullets[i].ym;
1128 bullets[i].ym = bullets[i].ym + GRAVITY;
1130 if (bullets[i].x < scroll_x ||
1131 bullets[i].x > scroll_x + 640)
1133 bullets[i].alive = NO;
1138 if (bullets[i].alive)
1140 for (j = 0; j < NUM_BAD_GUYS; j++)
1142 if (bad_guys[j].alive && !bad_guys[j].dying)
1144 if (bullets[i].x >= bad_guys[j].x - 4 &&
1145 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1146 bullets[i].y >= bad_guys[j].y - 4 &&
1147 bullets[i].y <= bad_guys[j].y + 32 + 4)
1149 /* Kill the bad guy! */
1151 bullets[i].alive = 0;
1152 bad_guys[j].dying = FALLING;
1153 bad_guys[j].ym = -8;
1156 /* Gain some points: */
1158 if (bad_guys[j].kind == BAD_BSOD)
1160 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1161 50 * score_multiplier);
1163 else if (bad_guys[j].kind == BAD_LAPTOP)
1165 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1166 25 * score_multiplier);
1170 /* Play death sound: */
1171 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1179 /* Handle background timer: */
1181 if (super_bkgd_time)
1185 /* Handle invincibility timer: */
1188 if (tux_invincible_time > 50)
1190 tux_invincible_time--;
1193 if (!playing_music())
1194 play_music( herring_song, 1 );
1198 if (current_music == HERRING_MUSIC)
1200 /* stop the herring_song, now play the level_song ! */
1201 current_music = LEVEL_MUSIC;
1205 if (!playing_music())
1207 if (current_level.time_left <= TIME_WARNING)
1208 play_music( level_song_fast, 1 );
1210 play_music( level_song, 1 );
1213 if (tux_invincible_time > 0)
1214 tux_invincible_time--;
1218 /* Handle upgrades: */
1220 for (i = 0; i < NUM_UPGRADES; i++)
1222 if (upgrades[i].alive)
1224 if (upgrades[i].height < 32)
1228 upgrades[i].height++;
1234 if (upgrades[i].kind == UPGRADE_MINTS ||
1235 upgrades[i].kind == UPGRADE_HERRING)
1237 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1238 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1240 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1241 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1243 if (upgrades[i].ym > 0)
1245 if (upgrades[i].kind == UPGRADE_MINTS)
1249 else if (upgrades[i].kind == UPGRADE_HERRING)
1251 upgrades[i].ym = -24;
1254 upgrades[i].y = (upgrades[i].y / 32) * 32;
1258 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1260 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1262 upgrades[i].xm = -upgrades[i].xm;
1267 /* Off the screen? Kill it! */
1269 if (upgrades[i].x < scroll_x)
1270 upgrades[i].alive = NO;
1273 /* Did the player grab it? */
1275 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1276 tux_x + scroll_x <= upgrades[i].x + 32 &&
1277 tux_y >= upgrades[i].y - 32 &&
1278 tux_y <= upgrades[i].y + 32)
1280 /* Remove the upgrade: */
1282 upgrades[i].alive = NO;
1285 /* Affect the player: */
1287 if (upgrades[i].kind == UPGRADE_MINTS)
1289 play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
1291 super_bkgd_time = 8;
1293 else if (upgrades[i].kind == UPGRADE_COFFEE)
1295 play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
1296 tux_got_coffee = YES;
1297 super_bkgd_time = 4;
1299 else if (upgrades[i].kind == UPGRADE_HERRING)
1301 play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
1302 tux_invincible_time = TUX_INVINCIBLE_TIME;
1303 super_bkgd_time = 4;
1304 /* play the herring song ^^ */
1305 current_music = HERRING_MUSIC;
1306 if (playing_music())
1308 play_music( herring_song, 1 );
1316 /* Handle bad guys: */
1318 for (i = 0; i < NUM_BAD_GUYS; i++)
1320 if (bad_guys[i].alive)
1322 if (bad_guys[i].seen)
1324 if (bad_guys[i].kind == BAD_BSOD)
1326 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1328 /* Move left/right: */
1330 if (bad_guys[i].dying == NO ||
1331 bad_guys[i].dying == FALLING)
1333 if (bad_guys[i].dir == RIGHT)
1334 bad_guys[i].x = bad_guys[i].x + 4;
1335 else if (bad_guys[i].dir == LEFT)
1336 bad_guys[i].x = bad_guys[i].x - 4;
1340 /* Move vertically: */
1342 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1345 /* Bump into things horizontally: */
1347 if (!bad_guys[i].dying)
1349 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1350 bad_guys[i].dir = !bad_guys[i].dir;
1354 /* Bump into other bad guys: */
1356 for (j = 0; j < NUM_BAD_GUYS; j++)
1358 if (j != i && bad_guys[j].alive &&
1359 !bad_guys[j].dying && !bad_guys[i].dying &&
1360 bad_guys[i].x >= bad_guys[j].x - 32 &&
1361 bad_guys[i].x <= bad_guys[j].x + 32 &&
1362 bad_guys[i].y >= bad_guys[j].y - 32 &&
1363 bad_guys[i].y <= bad_guys[j].y + 32)
1365 bad_guys[i].dir = !bad_guys[i].dir;
1370 /* Fall if we get off the ground: */
1372 if (bad_guys[i].dying != FALLING)
1374 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1375 bad_guys[i].ym < MAX_YM)
1377 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1383 if (bad_guys[i].ym > 0)
1385 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1391 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1393 if (bad_guys[i].y > 480)
1394 bad_guys[i].alive = NO;
1396 else if (bad_guys[i].kind == BAD_LAPTOP)
1398 /* --- LAPTOP MONSTER: --- */
1400 /* Move left/right: */
1402 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1404 if (bad_guys[i].dying == NO ||
1405 bad_guys[i].dying == FALLING)
1407 if (bad_guys[i].dir == RIGHT)
1408 bad_guys[i].x = bad_guys[i].x + 4;
1409 else if (bad_guys[i].dir == LEFT)
1410 bad_guys[i].x = bad_guys[i].x - 4;
1413 else if (bad_guys[i].mode == KICK)
1415 if (bad_guys[i].dir == RIGHT)
1416 bad_guys[i].x = bad_guys[i].x + 16;
1417 else if (bad_guys[i].dir == LEFT)
1418 bad_guys[i].x = bad_guys[i].x - 16;
1422 /* Move vertically: */
1424 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1427 /* Bump into things horizontally: */
1429 if (!bad_guys[i].dying)
1431 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1433 bad_guys[i].dir = !bad_guys[i].dir;
1435 if (bad_guys[i].mode == KICK)
1437 /* handle stereo sound */
1438 if (tux_x + scroll_x > bad_guys[i].x)
1439 play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
1440 else if (tux_x + scroll_x < bad_guys[i].x)
1441 play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
1443 play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
1449 /* Bump into other bad guys: */
1451 for (j = 0; j < NUM_BAD_GUYS; j++)
1453 if (j != i && bad_guys[j].alive &&
1454 !bad_guys[j].dying && !bad_guys[i].dying &&
1455 bad_guys[i].x >= bad_guys[j].x - 32 &&
1456 bad_guys[i].x <= bad_guys[j].x + 32 &&
1457 bad_guys[i].y >= bad_guys[j].y - 32 &&
1458 bad_guys[i].y <= bad_guys[j].y + 32)
1460 if (bad_guys[i].mode != KICK)
1461 bad_guys[i].dir = !bad_guys[i].dir;
1464 /* We're in kick mode, kill the other guy: */
1466 bad_guys[j].dying = FALLING;
1467 bad_guys[j].ym = -8;
1468 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1470 add_score(bad_guys[i].x - scroll_x,
1471 bad_guys[i].y, 100);
1477 /* Fall if we get off the ground: */
1479 if (bad_guys[i].dying != FALLING)
1481 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1482 bad_guys[i].ym < MAX_YM)
1484 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1490 if (bad_guys[i].ym > 0)
1492 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1498 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1500 if (bad_guys[i].y > 480)
1501 bad_guys[i].alive = NO;
1503 else if (bad_guys[i].kind == BAD_MONEY)
1505 /* --- MONEY BAGS: --- */
1508 /* Move vertically: */
1510 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1513 /* Fall if we get off the ground: */
1515 if (bad_guys[i].dying != FALLING)
1517 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1519 if (bad_guys[i].ym < MAX_YM)
1521 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1528 if (bad_guys[i].ym > 0)
1530 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1531 bad_guys[i].ym = -MAX_YM;
1536 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1538 if (bad_guys[i].y > 480)
1539 bad_guys[i].alive = NO;
1541 else if (bad_guys[i].kind == -1)
1545 /* Kill it if the player jumped on it: */
1547 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1548 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1549 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1550 tux_y >= bad_guys[i].y - 32 &&
1551 tux_y <= bad_guys[i].y - 8
1555 if (bad_guys[i].kind == BAD_BSOD)
1557 bad_guys[i].dying = SQUISHED;
1558 bad_guys[i].timer = 16;
1559 tux_ym = -KILL_BOUNCE_YM;
1561 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1562 50 * score_multiplier);
1564 play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
1566 else if (bad_guys[i].kind == BAD_LAPTOP)
1568 if (bad_guys[i].mode != FLAT)
1572 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1573 bad_guys[i].mode = FLAT;
1575 bad_guys[i].timer = 64;
1583 bad_guys[i].mode = KICK;
1584 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1586 if (tux_x + scroll_x <= bad_guys[i].x)
1587 bad_guys[i].dir = RIGHT;
1589 bad_guys[i].dir = LEFT;
1591 bad_guys[i].timer = 8;
1594 tux_ym = -KILL_BOUNCE_YM;
1596 add_score(bad_guys[i].x - scroll_x,
1598 25 * score_multiplier);
1600 /* play_sound(sounds[SND_SQUISH]); */
1602 else if (bad_guys[i].kind == -1)
1609 /* Hurt the player if he just touched it: */
1611 if (!bad_guys[i].dying && !tux_dying &&
1613 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1614 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1615 tux_y >= bad_guys[i].y - 32 &&
1616 tux_y <= bad_guys[i].y + 32)
1618 if (bad_guys[i].mode == FLAT)
1622 bad_guys[i].mode = KICK;
1623 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1625 if (tux_x + scroll_x <= bad_guys[i].x)
1627 bad_guys[i].dir = RIGHT;
1628 bad_guys[i].x = bad_guys[i].x + 16;
1632 bad_guys[i].dir = LEFT;
1633 bad_guys[i].x = bad_guys[i].x - 16;
1636 bad_guys[i].timer = 8;
1638 else if (bad_guys[i].mode == KICK)
1640 if (tux_y < bad_guys[i].y - 16 &&
1641 bad_guys[i].timer == 0)
1643 /* Step on (stop being kicked) */
1645 bad_guys[i].mode = FLAT;
1646 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1647 bad_guys[i].timer = 64;
1651 /* Hurt if you get hit by kicked laptop: */
1653 if (bad_guys[i].timer == 0)
1655 if (tux_invincible_time == 0)
1661 bad_guys[i].dying = FALLING;
1662 bad_guys[i].ym = -8;
1663 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1670 if (tux_invincible_time == 0)
1676 bad_guys[i].dying = FALLING;
1677 bad_guys[i].ym = -8;
1678 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1684 /* Handle mode timer: */
1686 if (bad_guys[i].mode == FLAT)
1688 bad_guys[i].timer--;
1690 if (bad_guys[i].timer <= 0)
1691 bad_guys[i].mode = NORMAL;
1693 else if (bad_guys[i].mode == KICK)
1695 if (bad_guys[i].timer > 0)
1696 bad_guys[i].timer--;
1700 /* Handle dying timer: */
1702 if (bad_guys[i].dying == SQUISHED)
1704 bad_guys[i].timer--;
1707 /* Remove it if time's up: */
1709 if (bad_guys[i].timer <= 0)
1710 bad_guys[i].alive = NO;
1714 /* Remove if it's far off the screen: */
1716 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1717 bad_guys[i].alive = NO;
1721 /* Once it's on screen, it's activated! */
1723 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1724 bad_guys[i].seen = YES;
1730 /* Handle skidding: */
1732 if (tux_skidding > 0)
1740 /* --- GAME DRAW! --- */
1748 if (tux_dying && (frame % 4) == 0)
1749 clearscreen(255, 255, 255);
1752 if (super_bkgd_time == 0)
1753 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
1755 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1759 /* Draw background: */
1761 for (y = 0; y < 15; y++)
1763 for (x = 0; x < 21; x++)
1765 drawshape(x * 32 - (scroll_x % 32), y * 32,
1766 current_level.tiles[y][x + (scroll_x / 32)]);
1771 /* (Bouncy bricks): */
1773 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1775 if (bouncy_bricks[i].alive)
1777 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1778 bouncy_bricks[i].x <= scroll_x + 640)
1780 dest.x = bouncy_bricks[i].x - scroll_x;
1781 dest.y = bouncy_bricks[i].y;
1785 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1786 current_level.bkgd_red,
1787 current_level.bkgd_green,
1788 current_level.bkgd_blue));
1790 drawshape(bouncy_bricks[i].x - scroll_x,
1791 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1792 bouncy_bricks[i].shape);
1800 for (i = 0; i < NUM_BAD_GUYS; i++)
1802 if (bad_guys[i].alive &&
1803 bad_guys[i].x > scroll_x - 32 &&
1804 bad_guys[i].x < scroll_x + 640)
1806 if (bad_guys[i].kind == BAD_BSOD)
1808 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1810 if (bad_guys[i].dying == NO)
1814 if (bad_guys[i].dir == LEFT)
1816 drawimage(img_bsod_left[(frame / 5) % 4],
1817 bad_guys[i].x - scroll_x,
1823 drawimage(img_bsod_right[(frame / 5) % 4],
1824 bad_guys[i].x - scroll_x,
1829 else if (bad_guys[i].dying == FALLING)
1833 if (bad_guys[i].dir == LEFT)
1835 drawimage(img_bsod_falling_left,
1836 bad_guys[i].x - scroll_x,
1842 drawimage(img_bsod_falling_right,
1843 bad_guys[i].x - scroll_x,
1848 else if (bad_guys[i].dying == SQUISHED)
1850 /* Dying - Squished: */
1852 if (bad_guys[i].dir == LEFT)
1854 drawimage(img_bsod_squished_left,
1855 bad_guys[i].x - scroll_x,
1861 drawimage(img_bsod_squished_right,
1862 bad_guys[i].x - scroll_x,
1868 else if (bad_guys[i].kind == BAD_LAPTOP)
1870 /* --- LAPTOP MONSTER: --- */
1872 if (bad_guys[i].dying == NO)
1876 if (bad_guys[i].mode == NORMAL)
1880 if (bad_guys[i].dir == LEFT)
1882 drawimage(img_laptop_left[(frame / 5) % 3],
1883 bad_guys[i].x - scroll_x,
1889 drawimage(img_laptop_right[(frame / 5) % 3],
1890 bad_guys[i].x - scroll_x,
1899 if (bad_guys[i].dir == LEFT)
1901 drawimage(img_laptop_flat_left,
1902 bad_guys[i].x - scroll_x,
1908 drawimage(img_laptop_flat_right,
1909 bad_guys[i].x - scroll_x,
1915 else if (bad_guys[i].dying == FALLING)
1919 if (bad_guys[i].dir == LEFT)
1921 drawimage(img_laptop_falling_left,
1922 bad_guys[i].x - scroll_x,
1928 drawimage(img_laptop_falling_right,
1929 bad_guys[i].x - scroll_x,
1935 else if (bad_guys[i].kind == BAD_MONEY)
1937 if (bad_guys[i].ym > -16)
1939 if (bad_guys[i].dir == LEFT)
1941 drawimage(img_money_left[0],
1942 bad_guys[i].x - scroll_x,
1948 drawimage(img_money_right[0],
1949 bad_guys[i].x - scroll_x,
1956 if (bad_guys[i].dir == LEFT)
1958 drawimage(img_money_left[1],
1959 bad_guys[i].x - scroll_x,
1965 drawimage(img_money_right[1],
1966 bad_guys[i].x - scroll_x,
1972 else if (bad_guys[i].kind == -1)
1980 if (right == UP && left == UP)
1987 if ((fire == DOWN && (frame % 2) == 0) ||
1989 tux_frame_main = (tux_frame_main + 1) % 4;
1991 tux_frame = tux_frame_main;
1998 if (tux_safe == 0 || (frame % 2) == 0)
2000 if (tux_size == SMALL)
2002 if (tux_invincible_time)
2006 if (tux_dir == RIGHT)
2008 drawimage(cape_right[frame % 2],
2014 drawimage(cape_left[frame % 2],
2021 if (!tux_got_coffee)
2023 if (tux_dir == RIGHT)
2025 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
2029 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
2034 /* Tux got coffee! */
2036 if (tux_dir == RIGHT)
2038 drawimage(firetux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
2042 drawimage(firetux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
2048 if (tux_invincible_time)
2052 if (tux_dir == RIGHT)
2054 drawimage(bigcape_right[frame % 2],
2055 tux_x - 8 - 16, tux_y - 32,
2060 drawimage(bigcape_left[frame % 2],
2061 tux_x - 8, tux_y - 32,
2066 if (!tux_got_coffee)
2072 if (!jumping || tux_ym > 0)
2074 if (tux_dir == RIGHT)
2076 drawimage(bigtux_right[tux_frame],
2077 tux_x - 8, tux_y - 32,
2082 drawimage(bigtux_left[tux_frame],
2083 tux_x - 8, tux_y - 32,
2089 if (tux_dir == RIGHT)
2091 drawimage(bigtux_right_jump,
2092 tux_x - 8, tux_y - 32,
2097 drawimage(bigtux_left_jump,
2098 tux_x - 8, tux_y - 32,
2105 if (tux_dir == RIGHT)
2107 drawimage(skidtux_right,
2108 tux_x - 8, tux_y - 32,
2113 drawimage(skidtux_left,
2114 tux_x - 8, tux_y - 32,
2121 if (tux_dir == RIGHT)
2123 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2128 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2135 /* Tux has coffee! */
2141 if (!jumping || tux_ym > 0)
2143 if (tux_dir == RIGHT)
2145 drawimage(bigfiretux_right[tux_frame],
2146 tux_x - 8, tux_y - 32,
2151 drawimage(bigfiretux_left[tux_frame],
2152 tux_x - 8, tux_y - 32,
2158 if (tux_dir == RIGHT)
2160 drawimage(bigfiretux_right_jump,
2161 tux_x - 8, tux_y - 32,
2166 drawimage(bigfiretux_left_jump,
2167 tux_x - 8, tux_y - 32,
2174 if (tux_dir == RIGHT)
2176 drawimage(skidfiretux_right,
2177 tux_x - 8, tux_y - 32,
2182 drawimage(skidfiretux_left,
2183 tux_x - 8, tux_y - 32,
2190 if (tux_dir == RIGHT)
2192 drawimage(duckfiretux_right, tux_x - 8, tux_y - 16,
2197 drawimage(duckfiretux_left, tux_x - 8, tux_y - 16,
2208 for (i = 0; i < NUM_BULLETS; i++)
2210 if (bullets[i].alive &&
2211 bullets[i].x >= scroll_x - 4 &&
2212 bullets[i].x <= scroll_x + 640)
2214 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2220 /* (Floating scores): */
2222 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2224 if (floating_scores[i].alive)
2226 sprintf(str, "%d", floating_scores[i].value);
2228 floating_scores[i].x + 16 - strlen(str) * 8,
2229 floating_scores[i].y,
2230 letters_gold, NO_UPDATE, 1);
2237 for (i = 0; i < NUM_UPGRADES; i++)
2239 if (upgrades[i].alive)
2241 if (upgrades[i].height < 32)
2245 dest.x = upgrades[i].x - scroll_x;
2246 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2248 dest.h = upgrades[i].height;
2253 src.h = upgrades[i].height;
2255 if (upgrades[i].kind == UPGRADE_MINTS)
2256 SDL_BlitSurface(img_mints, &src, screen, &dest);
2257 else if (upgrades[i].kind == UPGRADE_COFFEE)
2258 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2259 else if (upgrades[i].kind == UPGRADE_HERRING)
2260 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2264 if (upgrades[i].kind == UPGRADE_MINTS)
2266 drawimage(img_mints,
2267 upgrades[i].x - scroll_x, upgrades[i].y,
2270 else if (upgrades[i].kind == UPGRADE_COFFEE)
2272 drawimage(img_coffee,
2273 upgrades[i].x - scroll_x, upgrades[i].y,
2276 else if (upgrades[i].kind == UPGRADE_HERRING)
2278 drawimage(img_golden_herring,
2279 upgrades[i].x - scroll_x, upgrades[i].y,
2287 /* (Bouncy distros): */
2289 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2291 if (bouncy_distros[i].alive)
2293 drawimage(img_distro[0],
2294 bouncy_distros[i].x - scroll_x,
2295 bouncy_distros[i].y,
2301 /* (Broken bricks): */
2303 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2305 if (broken_bricks[i].alive)
2307 src.x = rand() % 16;
2308 src.y = rand() % 16;
2312 dest.x = broken_bricks[i].x - scroll_x;
2313 dest.y = broken_bricks[i].y;
2317 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2324 sprintf(str, "%d", score);
2325 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE, 1);
2326 drawtext(str, 96, 0, letters_gold, NO_UPDATE, 1);
2328 sprintf(str, "%d", highscore);
2329 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE, 1);
2330 drawtext(str, 96, 20, letters_gold, NO_UPDATE, 1);
2332 if (current_level.time_left >= TIME_WARNING || (frame % 10) < 5)
2334 sprintf(str, "%d", current_level.time_left);
2335 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE, 1);
2336 drawtext(str, 304, 0, letters_gold, NO_UPDATE, 1);
2339 sprintf(str, "%d", distros);
2340 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE, 1);
2341 drawtext(str, 608, 0, letters_gold, NO_UPDATE, 1);
2343 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE, 1);
2345 for(i=0; i < lives; ++i)
2347 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2351 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE, 1);
2356 /* (Update it all!) */
2363 /* --- GAME LOOP! --- */
2368 Uint32 last_time, now_time;
2372 clearscreen(0, 0, 0);
2376 /* Init the game: */
2379 menumenu = MENU_GAME;
2384 tux_got_coffee = NO;
2387 loadlevel(¤t_level,"default",level);
2389 activate_bad_guys();
2391 highscore = load_hs();
2395 /* --- MAIN GAME LOOP!!! --- */
2407 last_time = SDL_GetTicks();
2411 /* Handle events: */
2417 /* Handle actions: */
2419 if(!game_pause && !show_menu)
2421 if (game_action() == 0)
2423 /* == 0: no more lives */
2424 /* == -1: continues */
2431 /*Draw the current scene to the screen */
2434 /* Keep playing music: */
2437 if (!playing_music())
2439 switch (current_music)
2442 if (current_level.time_left <= TIME_WARNING)
2443 play_music(level_song_fast, 1);
2445 play_music(level_song, 1);
2448 play_music(herring_song, 1);
2450 case HURRYUP_MUSIC: // keep the compiler happy
2451 case NO_MUSIC: // keep the compiler happy for the moment :-)
2457 /* Time stops in pause mode */
2458 if(game_pause || show_menu )
2463 /* Pause til next frame: */
2465 now_time = SDL_GetTicks();
2466 if (now_time < last_time + FPS)
2467 SDL_Delay(last_time + FPS - now_time);
2472 if ((frame % 10) == 0 && current_level.time_left > 0)
2474 current_level.time_left--;
2476 /* Stop the music; it will start again, faster! */
2477 if (current_level.time_left == TIME_WARNING)
2480 if (current_level.time_left <= 0)
2484 while (!done && !quit);
2486 if (playing_music())
2497 /* Initialize the game stuff: */
2507 /* Load graphics: */
2509 void loadlevelgfx(void)
2512 img_brick[0] = load_level_image(current_level.theme,"brick0.png", IGNORE_ALPHA);
2513 img_brick[1] = load_level_image(current_level.theme,"brick1.png", IGNORE_ALPHA);
2515 img_solid[0] = load_level_image(current_level.theme,"solid0.png", USE_ALPHA);
2516 img_solid[1] = load_level_image(current_level.theme,"solid1.png", USE_ALPHA);
2517 img_solid[2] = load_level_image(current_level.theme,"solid2.png", USE_ALPHA);
2518 img_solid[3] = load_level_image(current_level.theme,"solid3.png", USE_ALPHA);
2520 img_bkgd[0][0] = load_level_image(current_level.theme,"bkgd-00.png", USE_ALPHA);
2521 img_bkgd[0][1] = load_level_image(current_level.theme,"bkgd-01.png", USE_ALPHA);
2522 img_bkgd[0][2] = load_level_image(current_level.theme,"bkgd-02.png", USE_ALPHA);
2523 img_bkgd[0][3] = load_level_image(current_level.theme,"bkgd-03.png", USE_ALPHA);
2525 img_bkgd[1][0] = load_level_image(current_level.theme,"bkgd-10.png", USE_ALPHA);
2526 img_bkgd[1][1] = load_level_image(current_level.theme,"bkgd-11.png", USE_ALPHA);
2527 img_bkgd[1][2] = load_level_image(current_level.theme,"bkgd-12.png", USE_ALPHA);
2528 img_bkgd[1][3] = load_level_image(current_level.theme,"bkgd-13.png", USE_ALPHA);
2534 void loadlevelsong(void)
2538 char * song_subtitle;
2540 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2541 strlen(current_level.song_title) + 8));
2542 sprintf(song_path, "%s/music/%s", DATA_PREFIX, current_level.song_title);
2543 level_song = load_song(song_path);
2547 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2548 strlen(current_level.song_title) + 8 + 5));
2549 song_subtitle = strdup(current_level.song_title);
2550 strcpy(strstr(song_subtitle, "."), "\0");
2551 sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(current_level.song_title, "."));
2552 level_song_fast = load_song(song_path);
2553 free(song_subtitle);
2558 /* Free graphics data for this level: */
2560 void unloadlevelgfx(void)
2564 for (i = 0; i < 2; i++)
2566 SDL_FreeSurface(img_brick[i]);
2568 for (i = 0; i < 4; i++)
2570 SDL_FreeSurface(img_solid[i]);
2571 SDL_FreeSurface(img_bkgd[0][i]);
2572 SDL_FreeSurface(img_bkgd[1][i]);
2577 /* Free music data for this level: */
2579 void unloadlevelsong(void)
2581 free_music(level_song);
2585 /* Load graphics/sounds shared between all levels: */
2587 void loadshared(void)
2590 char * herring_song_path; /* for loading herring song*/
2594 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2597 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2600 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2603 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2606 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2609 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2612 firetux_right[0] = load_image(DATA_PREFIX "/images/shared/firetux-right-0.png",
2615 firetux_right[1] = load_image(DATA_PREFIX "/images/shared/firetux-right-1.png",
2618 firetux_right[2] = load_image(DATA_PREFIX "/images/shared/firetux-right-2.png",
2621 firetux_left[0] = load_image(DATA_PREFIX "/images/shared/firetux-left-0.png",
2624 firetux_left[1] = load_image(DATA_PREFIX "/images/shared/firetux-left-1.png",
2627 firetux_left[2] = load_image(DATA_PREFIX "/images/shared/firetux-left-2.png",
2630 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2633 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2636 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2639 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2642 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2645 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2648 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2652 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2654 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2657 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2660 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2664 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2667 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2671 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2675 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2679 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2682 bigfiretux_right[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
2685 bigfiretux_right[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
2688 bigfiretux_right[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
2691 bigfiretux_right_jump =
2692 load_image(DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
2694 bigfiretux_left[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
2697 bigfiretux_left[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
2700 bigfiretux_left[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
2703 bigfiretux_left_jump =
2704 load_image(DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
2707 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2711 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2715 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2719 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2723 ducktux_right = load_image(DATA_PREFIX
2724 "/images/shared/ducktux-right.png",
2727 ducktux_left = load_image(DATA_PREFIX
2728 "/images/shared/ducktux-left.png",
2731 skidtux_right = load_image(DATA_PREFIX
2732 "/images/shared/skidtux-right.png",
2735 skidtux_left = load_image(DATA_PREFIX
2736 "/images/shared/skidtux-left.png",
2739 duckfiretux_right = load_image(DATA_PREFIX
2740 "/images/shared/duckfiretux-right.png",
2743 duckfiretux_left = load_image(DATA_PREFIX
2744 "/images/shared/duckfiretux-left.png",
2747 skidfiretux_right = load_image(DATA_PREFIX
2748 "/images/shared/skidfiretux-right.png",
2751 skidfiretux_left = load_image(DATA_PREFIX
2752 "/images/shared/skidfiretux-left.png",
2758 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2760 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2767 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2769 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2772 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2775 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2781 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2782 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2788 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2790 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2796 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2799 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2802 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2805 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2809 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2812 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2815 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2818 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2826 img_bsod_left[0] = load_image(DATA_PREFIX
2827 "/images/shared/bsod-left-0.png",
2830 img_bsod_left[1] = load_image(DATA_PREFIX
2831 "/images/shared/bsod-left-1.png",
2834 img_bsod_left[2] = load_image(DATA_PREFIX
2835 "/images/shared/bsod-left-2.png",
2838 img_bsod_left[3] = load_image(DATA_PREFIX
2839 "/images/shared/bsod-left-3.png",
2842 img_bsod_right[0] = load_image(DATA_PREFIX
2843 "/images/shared/bsod-right-0.png",
2846 img_bsod_right[1] = load_image(DATA_PREFIX
2847 "/images/shared/bsod-right-1.png",
2850 img_bsod_right[2] = load_image(DATA_PREFIX
2851 "/images/shared/bsod-right-2.png",
2854 img_bsod_right[3] = load_image(DATA_PREFIX
2855 "/images/shared/bsod-right-3.png",
2858 img_bsod_squished_left = load_image(DATA_PREFIX
2859 "/images/shared/bsod-squished-left.png",
2862 img_bsod_squished_right = load_image(DATA_PREFIX
2863 "/images/shared/bsod-squished-right.png",
2866 img_bsod_falling_left = load_image(DATA_PREFIX
2867 "/images/shared/bsod-falling-left.png",
2870 img_bsod_falling_right = load_image(DATA_PREFIX
2871 "/images/shared/bsod-falling-right.png",
2877 img_laptop_left[0] = load_image(DATA_PREFIX
2878 "/images/shared/laptop-left-0.png",
2881 img_laptop_left[1] = load_image(DATA_PREFIX
2882 "/images/shared/laptop-left-1.png",
2885 img_laptop_left[2] = load_image(DATA_PREFIX
2886 "/images/shared/laptop-left-2.png",
2889 img_laptop_right[0] = load_image(DATA_PREFIX
2890 "/images/shared/laptop-right-0.png",
2893 img_laptop_right[1] = load_image(DATA_PREFIX
2894 "/images/shared/laptop-right-1.png",
2897 img_laptop_right[2] = load_image(DATA_PREFIX
2898 "/images/shared/laptop-right-2.png",
2901 img_laptop_flat_left = load_image(DATA_PREFIX
2902 "/images/shared/laptop-flat-left.png",
2905 img_laptop_flat_right = load_image(DATA_PREFIX
2906 "/images/shared/laptop-flat-right.png",
2909 img_laptop_falling_left =
2910 load_image(DATA_PREFIX
2911 "/images/shared/laptop-falling-left.png",
2914 img_laptop_falling_right =
2915 load_image(DATA_PREFIX
2916 "/images/shared/laptop-falling-right.png",
2922 img_money_left[0] = load_image(DATA_PREFIX
2923 "/images/shared/bag-left-0.png",
2926 img_money_left[1] = load_image(DATA_PREFIX
2927 "/images/shared/bag-left-1.png",
2930 img_money_right[0] = load_image(DATA_PREFIX
2931 "/images/shared/bag-right-0.png",
2934 img_money_right[1] = load_image(DATA_PREFIX
2935 "/images/shared/bag-right-1.png",
2942 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2943 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2948 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2950 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2957 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2960 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2963 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2966 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2972 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
2977 img_golden_herring =
2978 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2982 /* Super background: */
2984 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2988 /* Sound effects: */
2990 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
2991 // initialize sounds[i] with the correct pointer's value:
2992 // NULL or something else. And it will be dangerous to
2993 // play with not-initialized pointers.
2994 // This is also true with if (use_music)
2995 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
2997 for (i = 0; i < NUM_SOUNDS; i++)
2998 sounds[i] = load_sound(soundfilenames[i]);
3001 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
3002 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
3004 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
3006 herring_song = load_song(herring_song_path);
3008 free(herring_song_path);
3013 /* Free shared data: */
3015 void unloadshared(void)
3019 for (i = 0; i < 3; i++)
3021 SDL_FreeSurface(tux_right[i]);
3022 SDL_FreeSurface(tux_left[i]);
3023 SDL_FreeSurface(bigtux_right[i]);
3024 SDL_FreeSurface(bigtux_left[i]);
3027 SDL_FreeSurface(bigtux_right_jump);
3028 SDL_FreeSurface(bigtux_left_jump);
3030 for (i = 0; i < 2; i++)
3032 SDL_FreeSurface(cape_right[i]);
3033 SDL_FreeSurface(cape_left[i]);
3034 SDL_FreeSurface(bigcape_right[i]);
3035 SDL_FreeSurface(bigcape_left[i]);
3038 SDL_FreeSurface(ducktux_left);
3039 SDL_FreeSurface(ducktux_right);
3041 SDL_FreeSurface(skidtux_left);
3042 SDL_FreeSurface(skidtux_right);
3044 for (i = 0; i < 4; i++)
3046 SDL_FreeSurface(img_bsod_left[i]);
3047 SDL_FreeSurface(img_bsod_right[i]);
3050 SDL_FreeSurface(img_bsod_squished_left);
3051 SDL_FreeSurface(img_bsod_squished_right);
3053 SDL_FreeSurface(img_bsod_falling_left);
3054 SDL_FreeSurface(img_bsod_falling_right);
3056 for (i = 0; i < 3; i++)
3058 SDL_FreeSurface(img_laptop_left[i]);
3059 SDL_FreeSurface(img_laptop_right[i]);
3062 SDL_FreeSurface(img_laptop_flat_left);
3063 SDL_FreeSurface(img_laptop_flat_right);
3065 SDL_FreeSurface(img_laptop_falling_left);
3066 SDL_FreeSurface(img_laptop_falling_right);
3068 for (i = 0; i < 2; i++)
3070 SDL_FreeSurface(img_money_left[i]);
3071 SDL_FreeSurface(img_money_right[i]);
3074 SDL_FreeSurface(img_box_full);
3075 SDL_FreeSurface(img_box_empty);
3077 SDL_FreeSurface(img_water);
3078 for (i = 0; i < 3; i++)
3079 SDL_FreeSurface(img_waves[i]);
3081 SDL_FreeSurface(img_pole);
3082 SDL_FreeSurface(img_poletop);
3084 for (i = 0; i < 2; i++)
3085 SDL_FreeSurface(img_flag[i]);
3087 SDL_FreeSurface(img_mints);
3088 SDL_FreeSurface(img_coffee);
3090 for (i = 0; i < 4; i++)
3092 SDL_FreeSurface(img_distro[i]);
3093 SDL_FreeSurface(img_cloud[0][i]);
3094 SDL_FreeSurface(img_cloud[1][i]);
3097 SDL_FreeSurface(img_golden_herring);
3099 for (i = 0; i < NUM_SOUNDS; i++)
3100 free_chunk(sounds[i]);
3102 /* free the herring song */
3103 free_music( herring_song );
3107 /* Draw a tile on the screen: */
3109 void drawshape(int x, int y, unsigned char c)
3113 if (c == 'X' || c == 'x')
3114 drawimage(img_brick[0], x, y, NO_UPDATE);
3115 else if (c == 'Y' || c == 'y')
3116 drawimage(img_brick[1], x, y, NO_UPDATE);
3117 else if (c == 'A' || c =='B' || c == '!')
3118 drawimage(img_box_full, x, y, NO_UPDATE);
3120 drawimage(img_box_empty, x, y, NO_UPDATE);
3121 else if (c >= 'C' && c <= 'F')
3122 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3123 else if (c >= 'c' && c <= 'f')
3124 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3125 else if (c >= 'G' && c <= 'J')
3126 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3127 else if (c >= 'g' && c <= 'j')
3128 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3130 drawimage(img_solid[0], x, y, NO_UPDATE);
3132 drawimage(img_solid[1], x, y, NO_UPDATE);
3134 drawimage(img_solid[2], x, y, NO_UPDATE);
3136 drawimage(img_solid[3], x, y, NO_UPDATE);
3139 z = (frame / 2) % 6;
3142 drawimage(img_distro[z], x, y, NO_UPDATE);
3144 drawimage(img_distro[2], x, y, NO_UPDATE);
3146 drawimage(img_distro[1], x, y, NO_UPDATE);
3150 z = (frame / 3) % 3;
3152 drawimage(img_waves[z], x, y, NO_UPDATE);
3155 drawimage(img_poletop, x, y, NO_UPDATE);
3158 drawimage(img_pole, x, y, NO_UPDATE);
3160 /* Mark this as the end position of the level! */
3166 z = (frame / 3) % 2;
3168 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3171 drawimage(img_water, x, y, NO_UPDATE);
3175 /* What shape is at some position? */
3177 unsigned char shape(int x, int y, int sx)
3184 xx = ((x + sx) / 32);
3187 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
3188 c = current_level.tiles[yy][xx];
3198 int issolid(int x, int y, int sx)
3204 if (isbrick(x, y, sx) ||
3205 isbrick(x + 31, y, sx) ||
3207 isice(x + 31, y, sx) ||
3208 (shape(x, y, sx) == '[' ||
3209 shape(x + 31, y, sx) == '[') ||
3210 (shape(x, y, sx) == '=' ||
3211 shape(x + 31, y, sx) == '=') ||
3212 (shape(x, y, sx) == ']' ||
3213 shape(x + 31, y, sx) == ']') ||
3214 (shape(x, y, sx) == 'A' ||
3215 shape(x + 31, y, sx) == 'A') ||
3216 (shape(x, y, sx) == 'B' ||
3217 shape(x + 31, y, sx) == 'B') ||
3218 (shape(x, y, sx) == '!' ||
3219 shape(x + 31, y, sx) == '!') ||
3220 (shape(x, y, sx) == 'a' ||
3221 shape(x + 31, y, sx) == 'a'))
3230 /* Is it a brick? */
3232 int isbrick(int x, int y, int sx)
3238 if (shape(x, y, sx) == 'X' ||
3239 shape(x, y, sx) == 'x' ||
3240 shape(x, y, sx) == 'Y' ||
3241 shape(x, y, sx) == 'y')
3252 int isice(int x, int y, int sx)
3258 if (shape(x, y, sx) == '#')
3267 /* Is it a full box? */
3269 int isfullbox(int x, int y, int sx)
3275 if (shape(x, y, sx) == 'A' ||
3276 shape(x, y, sx) == 'B' ||
3277 shape(x, y, sx) == '!')
3286 /* Edit a piece of the map! */
3288 void change(int x, int y, int sx, unsigned char c)
3293 xx = ((x + sx) / 32);
3295 if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
3296 current_level.tiles[yy][xx] = c;
3300 /* Break a brick: */
3302 void trybreakbrick(int x, int y, int sx)
3304 if (isbrick(x, y, sx))
3306 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3308 /* Get a distro from it: */
3310 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3313 if (counting_distros == NO)
3315 counting_distros = YES;
3316 distro_counter = 50;
3319 if (distro_counter <= 0)
3320 change(x, y, sx, 'a');
3322 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3323 score = score + SCORE_DISTRO;
3328 /* Get rid of it: */
3330 change(x, y, sx, '.');
3334 /* Replace it with broken bits: */
3336 add_broken_brick(((x + sx + 1) / 32) * 32,
3340 /* Get some score: */
3342 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
3343 score = score + SCORE_BRICK;
3348 /* Bounce a brick: */
3350 void bumpbrick(int x, int y, int sx)
3352 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3355 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
3361 void tryemptybox(int x, int y, int sx)
3363 if (isfullbox(x, y, sx))
3365 if (shape(x, y, sx) == 'A')
3367 /* Box with a distro! */
3369 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3370 (y / 32) * 32 - 32);
3372 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3373 score = score + SCORE_DISTRO;
3376 else if (shape(x, y, sx) == 'B')
3378 /* Add an upgrade! */
3380 if (tux_size == SMALL)
3382 /* Tux is small, add mints! */
3384 add_upgrade(((x + sx + 1) / 32) * 32,
3390 /* Tux is big, add coffee: */
3392 add_upgrade(((x + sx + 1) / 32) * 32,
3397 play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
3399 else if (shape(x, y, sx) == '!')
3401 /* Add a golden herring */
3403 add_upgrade(((x + sx + 1) / 32) * 32,
3408 /* Empty the box: */
3410 change(x, y, sx, 'a');
3415 /* Try to grab a distro: */
3417 void trygrabdistro(int x, int y, int sx, int bounciness)
3419 if (shape(x, y, sx) == '$')
3421 change(x, y, sx, '.');
3422 play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3424 if (bounciness == BOUNCE)
3426 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3430 score = score + SCORE_DISTRO;
3436 /* Add a bouncy distro: */
3438 void add_bouncy_distro(int x, int y)
3444 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3446 if (!bouncy_distros[i].alive)
3452 bouncy_distros[found].alive = YES;
3453 bouncy_distros[found].x = x;
3454 bouncy_distros[found].y = y;
3455 bouncy_distros[found].ym = -6;
3460 /* Add broken brick pieces: */
3462 void add_broken_brick(int x, int y)
3464 add_broken_brick_piece(x, y, -4, -16);
3465 add_broken_brick_piece(x, y + 16, -6, -12);
3467 add_broken_brick_piece(x + 16, y, 4, -16);
3468 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3472 /* Add a broken brick piece: */
3474 void add_broken_brick_piece(int x, int y, int xm, int ym)
3480 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3482 if (!broken_bricks[i].alive)
3488 broken_bricks[found].alive = YES;
3489 broken_bricks[found].x = x;
3490 broken_bricks[found].y = y;
3491 broken_bricks[found].xm = xm;
3492 broken_bricks[found].ym = ym;
3497 /* Add a bouncy brick piece: */
3499 void add_bouncy_brick(int x, int y)
3505 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3507 if (!bouncy_bricks[i].alive)
3513 bouncy_bricks[found].alive = YES;
3514 bouncy_bricks[found].x = x;
3515 bouncy_bricks[found].y = y;
3516 bouncy_bricks[found].offset = 0;
3517 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3518 bouncy_bricks[found].shape = shape(x, y, 0);
3523 /* Add a bad guy: */
3525 void add_bad_guy(int x, int y, int kind)
3531 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3533 if (!bad_guys[i].alive)
3539 bad_guys[found].alive = YES;
3540 bad_guys[found].mode = NORMAL;
3541 bad_guys[found].dying = NO;
3542 bad_guys[found].timer = 0;
3543 bad_guys[found].kind = kind;
3544 bad_guys[found].x = x;
3545 bad_guys[found].y = y;
3546 bad_guys[found].xm = 0;
3547 bad_guys[found].ym = 0;
3548 bad_guys[found].dir = LEFT;
3549 bad_guys[found].seen = NO;
3556 void add_score(int x, int y, int s)
3561 /* Add the score: */
3566 /* Add a floating score thing to the game: */
3570 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3572 if (!floating_scores[i].alive)
3579 floating_scores[found].alive = YES;
3580 floating_scores[found].x = x;
3581 floating_scores[found].y = y - 16;
3582 floating_scores[found].timer = 8;
3583 floating_scores[found].value = s;
3588 /* Try to bump a bad guy from below: */
3590 void trybumpbadguy(int x, int y, int sx)
3597 for (i = 0; i < NUM_BAD_GUYS; i++)
3599 if (bad_guys[i].alive &&
3600 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3601 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3603 if (bad_guys[i].kind == BAD_BSOD ||
3604 bad_guys[i].kind == BAD_LAPTOP)
3606 bad_guys[i].dying = FALLING;
3607 bad_guys[i].ym = -8;
3608 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
3616 for (i = 0; i < NUM_UPGRADES; i++)
3618 if (upgrades[i].alive && upgrades[i].height == 32 &&
3619 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3620 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3622 upgrades[i].xm = -upgrades[i].xm;
3623 upgrades[i].ym = -8;
3624 play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
3630 /* Add an upgrade: */
3632 void add_upgrade(int x, int y, int kind)
3638 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3640 if (!upgrades[i].alive)
3646 upgrades[found].alive = YES;
3647 upgrades[found].kind = kind;
3648 upgrades[found].x = x;
3649 upgrades[found].y = y;
3650 upgrades[found].xm = 4;
3651 upgrades[found].ym = -4;
3652 upgrades[found].height = 0;
3656 /* Remove Tux's power ups */
3657 void remove_powerups(void)
3659 tux_got_coffee = NO;
3666 void killtux(int mode)
3670 play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
3672 if (tux_dir == RIGHT)
3674 else if (tux_dir == LEFT)
3677 if (mode == SHRINK && tux_size == BIG)
3680 tux_got_coffee = NO;
3684 tux_safe = TUX_SAFE_TIME;
3695 void add_bullet(int x, int y, int dir, int xm)
3701 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3703 if (!bullets[i].alive)
3709 bullets[found].alive = YES;
3713 bullets[found].x = x + 32;
3714 bullets[found].xm = BULLET_XM + xm;
3718 bullets[found].x = x;
3719 bullets[found].xm = -BULLET_XM + xm;
3722 bullets[found].y = y;
3723 bullets[found].ym = BULLET_STARTING_YM;
3725 play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER);
3730 void drawendscreen(void)
3734 clearscreen(0, 0, 0);
3736 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE, 1);
3738 sprintf(str, "SCORE: %d", score);
3739 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
3741 sprintf(str, "DISTROS: %d", distros);
3742 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
3748 void drawresultscreen(void)
3752 clearscreen(0, 0, 0);
3754 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE, 1);
3756 sprintf(str, "SCORE: %d", score);
3757 drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
3759 sprintf(str, "DISTROS: %d", distros);
3760 drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
3769 time_t current_time = time(NULL);
3770 struct tm* time_struct;
3773 time_struct = localtime(¤t_time);
3774 sprintf(savefile,"%s/%d-%d-%d-%d.save",st_save_dir,time_struct->tm_year+1900,time_struct->tm_mon,time_struct->tm_mday,time_struct->tm_hour);
3775 printf("%s",savefile);
3778 fi = fopen(savefile, "wb");
3782 fprintf(stderr, "Warning: I could not open the high score file ");
3787 fwrite(&level,4,1,fi);
3788 fwrite(&score,4,1,fi);
3789 fwrite(&distros,4,1,fi);
3790 fwrite(&tux_x,4,1,fi);
3791 fwrite(&tux_y,4,1,fi);
3792 fwrite(&scroll_x,4,1,fi);
3793 fwrite(¤t_level.time_left,4,1,fi);
3799 void loadgame(char* filename)
3803 time_t current_time = time(NULL);
3804 struct tm* time_struct;
3806 time_struct = localtime(¤t_time);
3807 sprintf(savefile,"%s/%d-%d-%d-%d.save",st_save_dir,time_struct->tm_year+1900,time_struct->tm_mon,time_struct->tm_mday,time_struct->tm_hour);
3808 printf("%s",savefile);
3811 fi = fopen(savefile, "rb");
3815 fprintf(stderr, "Warning: I could not open the high score file ");
3821 loadlevel(¤t_level,"default",level);
3822 activate_bad_guys();
3829 fread(&level,4,1,fi);
3830 fread(&score,4,1,fi);
3831 fread(&distros,4,1,fi);
3832 fread(&tux_x,4,1,fi);
3833 fread(&tux_y,4,1,fi);
3834 fread(&scroll_x,4,1,fi);
3835 fread(¤t_level.time_left,4,1,fi);