7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - December 9, 2003
22 #include <sys/types.h>
32 #include "high_scores.h"
58 char * soundfilenames[NUM_SOUNDS] = {
59 DATA_PREFIX "/sounds/jump.wav",
60 DATA_PREFIX "/sounds/bigjump.wav",
61 DATA_PREFIX "/sounds/skid.wav",
62 DATA_PREFIX "/sounds/distro.wav",
63 DATA_PREFIX "/sounds/herring.wav",
64 DATA_PREFIX "/sounds/brick.wav",
65 DATA_PREFIX "/sounds/hurt.wav",
66 DATA_PREFIX "/sounds/squish.wav",
67 DATA_PREFIX "/sounds/fall.wav",
68 DATA_PREFIX "/sounds/ricochet.wav",
69 DATA_PREFIX "/sounds/bump-upgrade.wav",
70 DATA_PREFIX "/sounds/upgrade.wav",
71 DATA_PREFIX "/sounds/excellent.wav",
72 DATA_PREFIX "/sounds/coffee.wav",
73 DATA_PREFIX "/sounds/shoot.wav",
74 DATA_PREFIX "/sounds/lifeup.wav"
78 /* Local variables: */
80 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
81 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
82 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
83 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
84 super_bkgd_time, time_left, tux_invincible_time, endpos,
85 counting_distros, distro_counter;
86 int bkgd_red, bkgd_green, bkgd_blue, level_width;
87 int left, right, up, down, fire, old_fire;
88 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
89 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
90 SDL_Surface * img_bkgd[2][4];
91 SDL_Surface * img_golden_herring;
92 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
93 * img_laptop_left[3], * img_laptop_right[3],
94 * img_money_left[2], * img_money_right[2];
95 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
96 * img_bsod_falling_left, * img_bsod_falling_right,
97 * img_laptop_flat_left, * img_laptop_flat_right,
98 * img_laptop_falling_left, * img_laptop_falling_right;
99 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
100 * img_super_bkgd, * img_bullet, * img_red_glow;
101 SDL_Surface * img_cloud[2][4];
102 SDL_Surface * tux_right[3], * tux_left[3],
103 * bigtux_right[3], * bigtux_left[3],
104 * bigtux_right_jump, * bigtux_left_jump,
105 * cape_right[2], * cape_left[2],
106 * bigcape_right[2], * bigcape_left[2],
107 * ducktux_right, * ducktux_left,
108 * skidtux_right, * skidtux_left;
112 unsigned char * tiles[15];
113 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
114 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
115 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
116 bad_guy_type bad_guys[NUM_BAD_GUYS];
117 floating_score_type floating_scores[NUM_FLOATING_SCORES];
118 upgrade_type upgrades[NUM_UPGRADES];
119 bullet_type bullets[NUM_BULLETS];
125 /* Local function prototypes: */
128 void loadlevel(void);
129 void loadlevelgfx(void);
130 void loadlevelsong(void);
131 void unloadlevelgfx(void);
132 void unloadlevelsong(void);
133 void loadshared(void);
134 void unloadshared(void);
135 void drawshape(int x, int y, unsigned char c);
136 unsigned char shape(int x, int y, int sx);
137 int issolid(int x, int y, int sx);
138 int isbrick(int x, int y, int sx);
139 int isice(int x, int y, int sx);
140 int isfullbox(int x, int y, int sx);
141 void change(int x, int y, int sx, unsigned char c);
142 void trybreakbrick(int x, int y, int sx);
143 void bumpbrick(int x, int y, int sx);
144 void tryemptybox(int x, int y, int sx);
145 void trygrabdistro(int x, int y, int sx, int bounciness);
146 void add_bouncy_distro(int x, int y);
147 void add_broken_brick(int x, int y);
148 void add_broken_brick_piece(int x, int y, int xm, int ym);
149 void add_bouncy_brick(int x, int y);
150 void add_bad_guy(int x, int y, int kind);
151 void add_score(int x, int y, int s);
152 void trybumpbadguy(int x, int y, int sx);
153 void add_upgrade(int x, int y, int kind);
154 void killtux(int mode);
155 void add_bullet(int x, int y, int dir, int xm);
156 void drawendscreen(void);
157 void drawresultscreen(void);
159 /* --- GAME EVENT! --- */
161 void game_event(void)
164 while (SDL_PollEvent(&event))
167 if (event.type == SDL_QUIT)
169 /* Quit event - quit: */
173 else if (event.type == SDL_KEYDOWN)
177 key = event.key.keysym.sym;
179 /* Check for menu-events, if the menu is shown */
183 if (key == SDLK_ESCAPE)
185 /* Escape: Open/Close the menu: */
194 else if (key == SDLK_RIGHT)
198 else if (key == SDLK_LEFT)
202 else if (key == SDLK_UP)
206 else if (key == SDLK_DOWN)
210 else if (key == SDLK_LCTRL)
215 else if (event.type == SDL_KEYUP)
219 key = event.key.keysym.sym;
221 if (key == SDLK_RIGHT)
225 else if (key == SDLK_LEFT)
229 else if (key == SDLK_UP)
233 else if (key == SDLK_DOWN)
237 else if (key == SDLK_LCTRL)
241 else if (key == SDLK_p)
251 else if (key == SDLK_TAB)
253 tux_size = !tux_size;
255 else if (key == SDLK_END)
259 else if (key == SDLK_SPACE)
265 else if (event.type == SDL_JOYAXISMOTION)
267 if (event.jaxis.axis == JOY_X)
269 if (event.jaxis.value < -256)
274 if (event.jaxis.value > 256)
279 else if (event.jaxis.axis == JOY_Y)
281 if (event.jaxis.value > 256)
286 /* Handle joystick for the menu */
290 menuaction = MN_DOWN;
296 else if (event.type == SDL_JOYBUTTONDOWN)
298 if (event.jbutton.button == JOY_A)
300 else if (event.jbutton.button == JOY_B)
303 else if (event.type == SDL_JOYBUTTONUP)
305 if (event.jbutton.button == JOY_A)
307 else if (event.jbutton.button == JOY_B)
320 /* --- GAME ACTION! --- */
322 int game_action(void)
326 /* --- HANDLE TUX! --- */
328 /* Handle key and joystick state: */
330 if (!(tux_dying || next_level))
332 if (right == DOWN && left == UP)
336 if (tux_xm < -SKID_XM && !tux_skidding &&
339 tux_skidding = SKID_TIME;
341 play_sound(sounds[SND_SKID]);
347 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
355 if (tux_dir == RIGHT)
357 /* Facing the direction we're jumping? Go full-speed: */
361 tux_xm = tux_xm + WALK_SPEED;
363 if (tux_xm > MAX_WALK_XM)
364 tux_xm = MAX_WALK_XM;
366 else if (fire == DOWN)
368 tux_xm = tux_xm + RUN_SPEED;
370 if (tux_xm > MAX_RUN_XM)
376 /* Not facing the direction we're jumping?
379 tux_xm = tux_xm + WALK_SPEED / 2;
381 if (tux_xm > MAX_WALK_XM / 2)
382 tux_xm = MAX_WALK_XM / 2;
386 else if (left == DOWN && right == UP)
390 if (tux_xm > SKID_XM && !tux_skidding &&
393 tux_skidding = SKID_TIME;
394 play_sound(sounds[SND_SKID]);
399 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
409 /* Facing the direction we're jumping? Go full-speed: */
413 tux_xm = tux_xm - WALK_SPEED;
415 if (tux_xm < -MAX_WALK_XM)
416 tux_xm = -MAX_WALK_XM;
418 else if (fire == DOWN)
420 tux_xm = tux_xm - RUN_SPEED;
422 if (tux_xm < -MAX_RUN_XM)
423 tux_xm = -MAX_RUN_XM;
428 /* Not facing the direction we're jumping?
431 tux_xm = tux_xm - WALK_SPEED / 2;
433 if (tux_xm < -MAX_WALK_XM / 2)
434 tux_xm = -MAX_WALK_XM / 2;
442 if (tux_x >= endpos && endpos != 0)
452 if (jump_counter == 0)
456 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
459 /* If they're not on the ground, or are currently moving
460 vertically, don't jump! */
462 jump_counter = MAX_JUMP_COUNT;
466 /* Make sure we're not standing back up into a solid! */
468 if (tux_size == SMALL || tux_duck == NO ||
469 !issolid(tux_x, tux_y, scroll_x))
473 if (tux_size == SMALL)
474 play_sound(sounds[SND_JUMP]);
476 play_sound(sounds[SND_BIGJUMP]);
482 /* Keep jumping for a while: */
484 if (jump_counter < MAX_JUMP_COUNT)
486 tux_ym = tux_ym - JUMP_SPEED;
496 if (fire == DOWN && old_fire == UP && tux_got_coffee)
498 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
511 if (tux_size == BIG && tux_duck == YES)
513 /* Make sure we're not standing back up into a solid! */
515 if (!issolid(tux_x, tux_y - 32, scroll_x))
521 } /* (tux_dying || next_level) */
524 /* Tux either died, or reached the end of a level! */
533 /* End of a level! */
541 tux_ym = tux_ym + GRAVITY;
549 /* No more lives!? */
555 if (score > highscore)
562 } /* if (lives < 0) */
565 /* Either way, (re-)load the (next) level... */
576 tux_x = tux_x + tux_xm;
577 tux_y = tux_y + tux_ym;
580 /* Keep tux in bounds: */
584 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
586 /* Scroll the screen in past center: */
588 scroll_x = scroll_x + (tux_x - 320);
591 if (scroll_x > ((level_width * 32) - 640))
592 scroll_x = ((level_width * 32) - 640);
594 else if (tux_x > 608)
596 /* ... unless there's no more to scroll! */
606 if (issolid(tux_x, tux_y + 31, scroll_x) &&
607 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
609 while (issolid(tux_x, tux_y + 31, scroll_x))
620 if (issolid(tux_x, tux_y, scroll_x) &&
621 !issolid(tux_x - tux_xm, tux_y, scroll_x))
623 while (issolid(tux_x, tux_y, scroll_x))
634 if (issolid(tux_x, tux_y + 31, scroll_x))
636 /* Set down properly: */
638 while (issolid(tux_x, tux_y + 31, scroll_x))
647 /* Reset score multiplier (for mutli-hits): */
650 score_multiplier = 1;
660 /* Bump into things: */
662 if (issolid(tux_x, tux_y, scroll_x) ||
663 (tux_size == BIG && !tux_duck &&
664 (issolid(tux_x, tux_y - 32, scroll_x))))
666 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
667 (tux_size == SMALL || tux_duck ||
668 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
670 tux_x = tux_x - tux_xm;
673 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
674 (tux_size == SMALL || tux_duck ||
675 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
683 /* Break bricks and empty boxes: */
687 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
688 isfullbox(tux_x, tux_y - 32, scroll_x))
690 trygrabdistro(tux_x, tux_y - 64, scroll_x,
692 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
694 if (isfullbox(tux_x, tux_y - 32,
697 bumpbrick(tux_x, tux_y - 32,
701 trybreakbrick(tux_x, tux_y - 32, scroll_x);
702 tryemptybox(tux_x, tux_y - 32, scroll_x);
705 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
706 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
708 trygrabdistro(tux_x + 31,
712 trybumpbadguy(tux_x + 31,
716 if (isfullbox(tux_x + 31, tux_y - 32,
719 bumpbrick(tux_x + 31, tux_y - 32,
723 trybreakbrick(tux_x + 31,
726 tryemptybox(tux_x + 31,
733 if (isbrick(tux_x, tux_y, scroll_x) ||
734 isfullbox(tux_x, tux_y, scroll_x))
736 trygrabdistro(tux_x, tux_y - 32, scroll_x,
738 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
739 if (isfullbox(tux_x, tux_y, scroll_x))
740 bumpbrick(tux_x, tux_y, scroll_x);
741 trybreakbrick(tux_x, tux_y, scroll_x);
742 tryemptybox(tux_x, tux_y, scroll_x);
745 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
746 isfullbox(tux_x + 31, tux_y, scroll_x))
748 trygrabdistro(tux_x + 31,
752 trybumpbadguy(tux_x + 31,
755 if (isfullbox(tux_x + 31, tux_y, scroll_x))
756 bumpbrick(tux_x + 31, tux_y, scroll_x);
757 trybreakbrick(tux_x + 31, tux_y, scroll_x);
758 tryemptybox(tux_x + 31, tux_y, scroll_x);
764 /* It's a brick and we're small, make the brick
765 bounce, and grab any distros above it: */
767 if (isbrick(tux_x, tux_y, scroll_x) ||
768 isfullbox(tux_x, tux_y, scroll_x))
770 trygrabdistro(tux_x, tux_y - 32, scroll_x,
772 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
773 bumpbrick(tux_x, tux_y, scroll_x);
774 tryemptybox(tux_x, tux_y, scroll_x);
777 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
778 isfullbox(tux_x + 31, tux_y, scroll_x))
780 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
782 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
783 bumpbrick(tux_x + 31, tux_y, scroll_x);
784 tryemptybox(tux_x + 31, tux_y, scroll_x);
788 /* Get a distro from a brick? */
790 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
791 shape(tux_x, tux_y, scroll_x) == 'y')
793 add_bouncy_distro(((tux_x + scroll_x + 1)
797 if (counting_distros == NO)
799 counting_distros = YES;
800 distro_counter = 100;
803 if (distro_counter <= 0)
804 change(tux_x, tux_y, scroll_x, 'a');
806 play_sound(sounds[SND_DISTRO]);
807 score = score + SCORE_DISTRO;
810 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
811 shape(tux_x + 31, tux_y, scroll_x) == 'y')
813 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
817 if (counting_distros == NO)
819 counting_distros = YES;
820 distro_counter = 100;
823 if (distro_counter <= 0)
824 change(tux_x + 31, tux_y, scroll_x, 'a');
826 play_sound(sounds[SND_DISTRO]);
827 score = score + SCORE_DISTRO;
835 tux_y = (tux_y / 32) * 32 + 30;
841 tux_y = (tux_y / 32) * 32 - 32;
846 jump_counter = MAX_JUMP_COUNT;
856 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
857 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
859 if (tux_size == BIG && !tux_duck)
861 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
862 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
867 /* Enough distros for a One-up? */
869 if (distros >= DISTROS_LIFEUP)
871 distros = distros - DISTROS_LIFEUP;
872 if(lives < MAX_LIVES)
874 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
878 /* Keep in-bounds, vertically: */
882 else if (tux_y > 480)
888 /* Slow down horizontally: */
892 if (right == UP && left == UP)
894 if (isice(tux_x, tux_y + 32, scroll_x) ||
895 !issolid(tux_x, tux_y + 32, scroll_x))
897 /* Slowly on ice or in air: */
906 /* Quickly, otherwise: */
913 /* Drop vertically: */
915 if (!issolid(tux_x, tux_y + 32, scroll_x))
917 tux_ym = tux_ym + GRAVITY;
929 /* ---- DONE HANDLING TUX! --- */
932 /* Handle bouncy distros: */
934 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
936 if (bouncy_distros[i].alive)
938 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
940 bouncy_distros[i].ym++;
942 if (bouncy_distros[i].ym >= 0)
943 bouncy_distros[i].alive = NO;
948 /* Handle broken bricks: */
950 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
952 if (broken_bricks[i].alive)
954 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
955 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
957 broken_bricks[i].ym++;
959 if (broken_bricks[i].ym >= 0)
960 broken_bricks[i].alive = NO;
965 /* Handle distro counting: */
967 if (counting_distros == YES)
971 if (distro_counter <= 0)
972 counting_distros = -1;
976 /* Handle bouncy bricks: */
978 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
980 if (bouncy_bricks[i].alive)
982 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
983 bouncy_bricks[i].offset_m);
987 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
988 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
993 if (bouncy_bricks[i].offset == 0)
994 bouncy_bricks[i].alive = NO;
999 /* Handle floating scores: */
1001 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1003 if (floating_scores[i].alive)
1005 floating_scores[i].y = floating_scores[i].y - 2;
1006 floating_scores[i].timer--;
1008 if (floating_scores[i].timer <= 0)
1009 floating_scores[i].alive = NO;
1014 /* Handle bullets: */
1016 for (i = 0; i < NUM_BULLETS; i++)
1018 if (bullets[i].alive)
1020 bullets[i].x = bullets[i].x + bullets[i].xm;
1021 bullets[i].y = bullets[i].y + bullets[i].ym;
1023 if (issolid(bullets[i].x, bullets[i].y, 0))
1025 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1026 bullets[i].alive = NO;
1029 if (bullets[i].ym >= 0)
1031 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1033 bullets[i].ym = -bullets[i].ym;
1037 bullets[i].ym = bullets[i].ym + GRAVITY;
1039 if (bullets[i].x < scroll_x ||
1040 bullets[i].x > scroll_x + 640)
1042 bullets[i].alive = NO;
1047 if (bullets[i].alive)
1049 for (j = 0; j < NUM_BAD_GUYS; j++)
1051 if (bad_guys[j].alive && !bad_guys[j].dying)
1053 if (bullets[i].x >= bad_guys[j].x - 4 &&
1054 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1055 bullets[i].y >= bad_guys[j].y - 4 &&
1056 bullets[i].y <= bad_guys[j].y + 32 + 4)
1058 /* Kill the bad guy! */
1060 bullets[i].alive = 0;
1061 bad_guys[j].dying = FALLING;
1062 bad_guys[j].ym = -8;
1065 /* Gain some points: */
1067 if (bad_guys[j].kind == BAD_BSOD)
1069 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1070 50 * score_multiplier);
1072 else if (bad_guys[j].kind == BAD_LAPTOP)
1074 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1075 25 * score_multiplier);
1079 /* Play death sound: */
1080 play_sound(sounds[SND_FALL]);
1088 /* Handle background timer: */
1090 if (super_bkgd_time)
1094 /* Handle invincibility timer: */
1097 if (tux_invincible_time > 50)
1099 tux_invincible_time--;
1102 if (!playing_music())
1103 play_music( herring_song, 1 );
1107 if (current_music == HERRING_MUSIC)
1109 /* stop the herring_song, now play the level_song ! */
1110 current_music = LEVEL_MUSIC;
1113 if (!playing_music())
1114 play_music( level_song, 1 );
1115 if (tux_invincible_time > 0)
1116 tux_invincible_time--;
1120 /* Handle upgrades: */
1122 for (i = 0; i < NUM_UPGRADES; i++)
1124 if (upgrades[i].alive)
1126 if (upgrades[i].height < 32)
1130 upgrades[i].height++;
1136 if (upgrades[i].kind == UPGRADE_MINTS ||
1137 upgrades[i].kind == UPGRADE_HERRING)
1139 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1140 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1142 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1143 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1145 if (upgrades[i].ym > 0)
1147 if (upgrades[i].kind == UPGRADE_MINTS)
1151 else if (upgrades[i].kind == UPGRADE_HERRING)
1153 upgrades[i].ym = -24;
1156 upgrades[i].y = (upgrades[i].y / 32) * 32;
1160 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1162 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1164 upgrades[i].xm = -upgrades[i].xm;
1169 /* Off the screen? Kill it! */
1171 if (upgrades[i].x < scroll_x)
1172 upgrades[i].alive = NO;
1175 /* Did the player grab it? */
1177 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1178 tux_x + scroll_x <= upgrades[i].x + 32 &&
1179 tux_y >= upgrades[i].y - 32 &&
1180 tux_y <= upgrades[i].y + 32)
1182 /* Remove the upgrade: */
1184 upgrades[i].alive = NO;
1187 /* Affect the player: */
1189 if (upgrades[i].kind == UPGRADE_MINTS)
1191 play_sound(sounds[SND_EXCELLENT]);
1193 super_bkgd_time = 8;
1195 else if (upgrades[i].kind == UPGRADE_COFFEE)
1197 play_sound(sounds[SND_COFFEE]);
1198 tux_got_coffee = YES;
1199 super_bkgd_time = 4;
1201 else if (upgrades[i].kind == UPGRADE_HERRING)
1203 play_sound(sounds[SND_HERRING]);
1204 tux_invincible_time = TUX_INVINCIBLE_TIME;
1205 super_bkgd_time = 4;
1206 /* play the herring song ^^ */
1207 current_music = HERRING_MUSIC;
1208 if (playing_music())
1210 play_music( herring_song, 1 );
1218 /* Handle bad guys: */
1220 for (i = 0; i < NUM_BAD_GUYS; i++)
1222 if (bad_guys[i].alive)
1224 if (bad_guys[i].seen)
1226 if (bad_guys[i].kind == BAD_BSOD)
1228 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1230 /* Move left/right: */
1232 if (bad_guys[i].dying == NO ||
1233 bad_guys[i].dying == FALLING)
1235 if (bad_guys[i].dir == RIGHT)
1236 bad_guys[i].x = bad_guys[i].x + 4;
1237 else if (bad_guys[i].dir == LEFT)
1238 bad_guys[i].x = bad_guys[i].x - 4;
1242 /* Move vertically: */
1244 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1247 /* Bump into things horizontally: */
1249 if (!bad_guys[i].dying)
1251 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1252 bad_guys[i].dir = !bad_guys[i].dir;
1256 /* Bump into other bad guys: */
1258 for (j = 0; j < NUM_BAD_GUYS; j++)
1260 if (j != i && bad_guys[j].alive &&
1261 !bad_guys[j].dying && !bad_guys[i].dying &&
1262 bad_guys[i].x >= bad_guys[j].x - 32 &&
1263 bad_guys[i].x <= bad_guys[j].x + 32 &&
1264 bad_guys[i].y >= bad_guys[j].y - 32 &&
1265 bad_guys[i].y <= bad_guys[j].y + 32)
1267 bad_guys[i].dir = !bad_guys[i].dir;
1272 /* Fall if we get off the ground: */
1274 if (bad_guys[i].dying != FALLING)
1276 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1277 bad_guys[i].ym < MAX_YM)
1279 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1285 if (bad_guys[i].ym > 0)
1287 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1293 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1295 if (bad_guys[i].y > 480)
1296 bad_guys[i].alive = NO;
1298 else if (bad_guys[i].kind == BAD_LAPTOP)
1300 /* --- LAPTOP MONSTER: --- */
1302 /* Move left/right: */
1304 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1306 if (bad_guys[i].dying == NO ||
1307 bad_guys[i].dying == FALLING)
1309 if (bad_guys[i].dir == RIGHT)
1310 bad_guys[i].x = bad_guys[i].x + 4;
1311 else if (bad_guys[i].dir == LEFT)
1312 bad_guys[i].x = bad_guys[i].x - 4;
1315 else if (bad_guys[i].mode == KICK)
1317 if (bad_guys[i].dir == RIGHT)
1318 bad_guys[i].x = bad_guys[i].x + 16;
1319 else if (bad_guys[i].dir == LEFT)
1320 bad_guys[i].x = bad_guys[i].x - 16;
1324 /* Move vertically: */
1326 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1329 /* Bump into things horizontally: */
1331 if (!bad_guys[i].dying)
1333 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1335 bad_guys[i].dir = !bad_guys[i].dir;
1337 if (bad_guys[i].mode == KICK)
1338 play_sound(sounds[SND_RICOCHET]);
1343 /* Bump into other bad guys: */
1345 for (j = 0; j < NUM_BAD_GUYS; j++)
1347 if (j != i && bad_guys[j].alive &&
1348 !bad_guys[j].dying && !bad_guys[i].dying &&
1349 bad_guys[i].x >= bad_guys[j].x - 32 &&
1350 bad_guys[i].x <= bad_guys[j].x + 32 &&
1351 bad_guys[i].y >= bad_guys[j].y - 32 &&
1352 bad_guys[i].y <= bad_guys[j].y + 32)
1354 if (bad_guys[i].mode != KICK)
1355 bad_guys[i].dir = !bad_guys[i].dir;
1358 /* We're in kick mode, kill the other guy: */
1360 bad_guys[j].dying = FALLING;
1361 bad_guys[j].ym = -8;
1362 play_sound(sounds[SND_FALL]);
1364 add_score(bad_guys[i].x - scroll_x,
1365 bad_guys[i].y, 100);
1371 /* Fall if we get off the ground: */
1373 if (bad_guys[i].dying != FALLING)
1375 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1376 bad_guys[i].ym < MAX_YM)
1378 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1384 if (bad_guys[i].ym > 0)
1386 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1392 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1394 if (bad_guys[i].y > 480)
1395 bad_guys[i].alive = NO;
1397 else if (bad_guys[i].kind == BAD_MONEY)
1399 /* --- MONEY BAGS: --- */
1402 /* Move vertically: */
1404 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1407 /* Fall if we get off the ground: */
1409 if (bad_guys[i].dying != FALLING)
1411 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1413 if (bad_guys[i].ym < MAX_YM)
1415 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1422 if (bad_guys[i].ym > 0)
1424 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1425 bad_guys[i].ym = -MAX_YM;
1430 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1432 if (bad_guys[i].y > 480)
1433 bad_guys[i].alive = NO;
1435 else if (bad_guys[i].kind == -1)
1439 /* Kill it if the player jumped on it: */
1441 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1442 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1443 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1444 tux_y >= bad_guys[i].y - 32 &&
1445 tux_y <= bad_guys[i].y - 8
1449 if (bad_guys[i].kind == BAD_BSOD)
1451 bad_guys[i].dying = SQUISHED;
1452 bad_guys[i].timer = 16;
1453 tux_ym = -KILL_BOUNCE_YM;
1455 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1456 50 * score_multiplier);
1458 play_sound(sounds[SND_SQUISH]);
1460 else if (bad_guys[i].kind == BAD_LAPTOP)
1462 if (bad_guys[i].mode != FLAT)
1466 bad_guys[i].mode = FLAT;
1468 bad_guys[i].timer = 64;
1476 bad_guys[i].mode = KICK;
1478 if (tux_x + scroll_x <= bad_guys[i].x)
1479 bad_guys[i].dir = RIGHT;
1481 bad_guys[i].dir = LEFT;
1483 bad_guys[i].timer = 8;
1486 tux_ym = -KILL_BOUNCE_YM;
1488 add_score(bad_guys[i].x - scroll_x,
1490 25 * score_multiplier);
1492 /* play_sound(sounds[SND_SQUISH]); */
1494 else if (bad_guys[i].kind == -1)
1501 /* Hurt the player if he just touched it: */
1503 if (!bad_guys[i].dying && !tux_dying &&
1505 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1506 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1507 tux_y >= bad_guys[i].y - 32 &&
1508 tux_y <= bad_guys[i].y + 32)
1510 if (bad_guys[i].mode == FLAT)
1514 bad_guys[i].mode = KICK;
1516 if (tux_x + scroll_x <= bad_guys[i].x)
1518 bad_guys[i].dir = RIGHT;
1519 bad_guys[i].x = bad_guys[i].x + 16;
1523 bad_guys[i].dir = LEFT;
1524 bad_guys[i].x = bad_guys[i].x - 16;
1527 bad_guys[i].timer = 8;
1529 else if (bad_guys[i].mode == KICK)
1531 if (tux_y < bad_guys[i].y - 16 &&
1532 bad_guys[i].timer == 0)
1534 /* Step on (stop being kicked) */
1536 bad_guys[i].mode = FLAT;
1537 bad_guys[i].timer = 64;
1541 /* Hurt if you get hit by kicked laptop: */
1543 if (bad_guys[i].timer == 0)
1545 if (tux_invincible_time == 0)
1551 bad_guys[i].dying = FALLING;
1552 bad_guys[i].ym = -8;
1553 play_sound(sounds[SND_FALL]);
1560 if (tux_invincible_time == 0)
1566 bad_guys[i].dying = FALLING;
1567 bad_guys[i].ym = -8;
1568 play_sound(sounds[SND_FALL]);
1574 /* Handle mode timer: */
1576 if (bad_guys[i].mode == FLAT)
1578 bad_guys[i].timer--;
1580 if (bad_guys[i].timer <= 0)
1581 bad_guys[i].mode = NORMAL;
1583 else if (bad_guys[i].mode == KICK)
1585 if (bad_guys[i].timer > 0)
1586 bad_guys[i].timer--;
1590 /* Handle dying timer: */
1592 if (bad_guys[i].dying == SQUISHED)
1594 bad_guys[i].timer--;
1597 /* Remove it if time's up: */
1599 if (bad_guys[i].timer <= 0)
1600 bad_guys[i].alive = NO;
1604 /* Remove if it's far off the screen: */
1606 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1607 bad_guys[i].alive = NO;
1611 /* Once it's on screen, it's activated! */
1613 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1614 bad_guys[i].seen = YES;
1620 /* Handle skidding: */
1622 if (tux_skidding > 0)
1630 /* --- GAME DRAW! --- */
1638 if (tux_dying && (frame % 4) == 0)
1639 clearscreen(255, 255, 255);
1642 if (super_bkgd_time == 0)
1643 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1645 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1649 /* Draw background: */
1651 for (y = 0; y < 15; y++)
1653 for (x = 0; x < 21; x++)
1655 drawshape(x * 32 - (scroll_x % 32), y * 32,
1656 tiles[y][x + (scroll_x / 32)]);
1661 /* (Bouncy bricks): */
1663 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1665 if (bouncy_bricks[i].alive)
1667 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1668 bouncy_bricks[i].x <= scroll_x + 640)
1670 dest.x = bouncy_bricks[i].x - scroll_x;
1671 dest.y = bouncy_bricks[i].y;
1675 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1680 drawshape(bouncy_bricks[i].x - scroll_x,
1681 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1682 bouncy_bricks[i].shape);
1690 for (i = 0; i < NUM_BAD_GUYS; i++)
1692 if (bad_guys[i].alive &&
1693 bad_guys[i].x > scroll_x - 32 &&
1694 bad_guys[i].x < scroll_x + 640)
1696 if (bad_guys[i].kind == BAD_BSOD)
1698 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1700 if (bad_guys[i].dying == NO)
1704 if (bad_guys[i].dir == LEFT)
1706 drawimage(img_bsod_left[(frame / 5) % 4],
1707 bad_guys[i].x - scroll_x,
1713 drawimage(img_bsod_right[(frame / 5) % 4],
1714 bad_guys[i].x - scroll_x,
1719 else if (bad_guys[i].dying == FALLING)
1723 if (bad_guys[i].dir == LEFT)
1725 drawimage(img_bsod_falling_left,
1726 bad_guys[i].x - scroll_x,
1732 drawimage(img_bsod_falling_right,
1733 bad_guys[i].x - scroll_x,
1738 else if (bad_guys[i].dying == SQUISHED)
1740 /* Dying - Squished: */
1742 if (bad_guys[i].dir == LEFT)
1744 drawimage(img_bsod_squished_left,
1745 bad_guys[i].x - scroll_x,
1751 drawimage(img_bsod_squished_right,
1752 bad_guys[i].x - scroll_x,
1758 else if (bad_guys[i].kind == BAD_LAPTOP)
1760 /* --- LAPTOP MONSTER: --- */
1762 if (bad_guys[i].dying == NO)
1766 if (bad_guys[i].mode == NORMAL)
1770 if (bad_guys[i].dir == LEFT)
1772 drawimage(img_laptop_left[(frame / 5) % 3],
1773 bad_guys[i].x - scroll_x,
1779 drawimage(img_laptop_right[(frame / 5) % 3],
1780 bad_guys[i].x - scroll_x,
1789 if (bad_guys[i].dir == LEFT)
1791 drawimage(img_laptop_flat_left,
1792 bad_guys[i].x - scroll_x,
1798 drawimage(img_laptop_flat_right,
1799 bad_guys[i].x - scroll_x,
1805 else if (bad_guys[i].dying == FALLING)
1809 if (bad_guys[i].dir == LEFT)
1811 drawimage(img_laptop_falling_left,
1812 bad_guys[i].x - scroll_x,
1818 drawimage(img_laptop_falling_right,
1819 bad_guys[i].x - scroll_x,
1825 else if (bad_guys[i].kind == BAD_MONEY)
1827 if (bad_guys[i].ym > -16)
1829 if (bad_guys[i].dir == LEFT)
1831 drawimage(img_money_left[0],
1832 bad_guys[i].x - scroll_x,
1838 drawimage(img_money_right[0],
1839 bad_guys[i].x - scroll_x,
1846 if (bad_guys[i].dir == LEFT)
1848 drawimage(img_money_left[1],
1849 bad_guys[i].x - scroll_x,
1855 drawimage(img_money_right[1],
1856 bad_guys[i].x - scroll_x,
1862 else if (bad_guys[i].kind == -1)
1870 if (right == UP && left == UP)
1877 if ((fire == DOWN && (frame % 2) == 0) ||
1879 tux_frame_main = (tux_frame_main + 1) % 4;
1881 tux_frame = tux_frame_main;
1888 if (tux_got_coffee && (frame % 2) == 1)
1892 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1896 if (tux_safe == 0 || (frame % 2) == 0)
1898 if (tux_size == SMALL)
1900 if (tux_invincible_time)
1904 if (tux_dir == RIGHT)
1906 drawimage(cape_right[frame % 2],
1912 drawimage(cape_left[frame % 2],
1919 if (tux_dir == RIGHT)
1921 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1925 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1930 if (tux_invincible_time)
1934 if (tux_dir == RIGHT)
1936 drawimage(bigcape_right[frame % 2],
1937 tux_x - 8 - 16, tux_y - 32,
1942 drawimage(bigcape_left[frame % 2],
1943 tux_x - 8, tux_y - 32,
1952 if (!jumping || tux_ym > 0)
1954 if (tux_dir == RIGHT)
1956 drawimage(bigtux_right[tux_frame],
1957 tux_x - 8, tux_y - 32,
1962 drawimage(bigtux_left[tux_frame],
1963 tux_x - 8, tux_y - 32,
1969 if (tux_dir == RIGHT)
1971 drawimage(bigtux_right_jump,
1972 tux_x - 8, tux_y - 32,
1977 drawimage(bigtux_left_jump,
1978 tux_x - 8, tux_y - 32,
1985 if (tux_dir == RIGHT)
1987 drawimage(skidtux_right,
1988 tux_x - 8, tux_y - 32,
1993 drawimage(skidtux_left,
1994 tux_x - 8, tux_y - 32,
2001 if (tux_dir == RIGHT)
2003 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2008 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2018 for (i = 0; i < NUM_BULLETS; i++)
2020 if (bullets[i].alive &&
2021 bullets[i].x >= scroll_x - 4 &&
2022 bullets[i].x <= scroll_x + 640)
2024 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2030 /* (Floating scores): */
2032 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2034 if (floating_scores[i].alive)
2036 sprintf(str, "%d", floating_scores[i].value);
2038 floating_scores[i].x + 16 - strlen(str) * 8,
2039 floating_scores[i].y,
2040 letters_gold, NO_UPDATE);
2047 for (i = 0; i < NUM_UPGRADES; i++)
2049 if (upgrades[i].alive)
2051 if (upgrades[i].height < 32)
2055 dest.x = upgrades[i].x - scroll_x;
2056 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2058 dest.h = upgrades[i].height;
2063 src.h = upgrades[i].height;
2065 if (upgrades[i].kind == UPGRADE_MINTS)
2066 SDL_BlitSurface(img_mints, &src, screen, &dest);
2067 else if (upgrades[i].kind == UPGRADE_COFFEE)
2068 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2069 else if (upgrades[i].kind == UPGRADE_HERRING)
2070 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2074 if (upgrades[i].kind == UPGRADE_MINTS)
2076 drawimage(img_mints,
2077 upgrades[i].x - scroll_x, upgrades[i].y,
2080 else if (upgrades[i].kind == UPGRADE_COFFEE)
2082 drawimage(img_coffee,
2083 upgrades[i].x - scroll_x, upgrades[i].y,
2086 else if (upgrades[i].kind == UPGRADE_HERRING)
2088 drawimage(img_golden_herring,
2089 upgrades[i].x - scroll_x, upgrades[i].y,
2097 /* (Bouncy distros): */
2099 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2101 if (bouncy_distros[i].alive)
2103 drawimage(img_distro[0],
2104 bouncy_distros[i].x - scroll_x,
2105 bouncy_distros[i].y,
2111 /* (Broken bricks): */
2113 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2115 if (broken_bricks[i].alive)
2117 src.x = rand() % 16;
2118 src.y = rand() % 16;
2122 dest.x = broken_bricks[i].x - scroll_x;
2123 dest.y = broken_bricks[i].y;
2127 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2134 sprintf(str, "%d", score);
2135 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2136 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2138 sprintf(str, "%d", highscore);
2139 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2140 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2142 if (time_left >= 50 || (frame % 10) < 5)
2144 sprintf(str, "%d", time_left);
2145 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2146 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2149 sprintf(str, "%d", distros);
2150 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2151 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2154 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2159 /* (Update it all!) */
2166 /* --- GAME LOOP! --- */
2171 Uint32 last_time, now_time;
2175 clearscreen(0, 0, 0);
2179 /* Init the game: */
2187 highscore = load_hs();
2190 /* --- MAIN GAME LOOP!!! --- */
2202 last_time = SDL_GetTicks();
2206 /* Handle events: */
2212 /* Handle actions: */
2214 if(!game_pause && !show_menu)
2216 if (game_action() == 0)
2218 /* == 0: no more lives */
2219 /* == -1: continues */
2226 /*Draw the current scene to the screen */
2229 /* Keep playing music: */
2232 if (!playing_music())
2234 switch (current_music)
2237 play_music(level_song, 1);
2240 play_music(herring_song, 1);
2242 case HURRYUP_MUSIC: // keep the compiler happy
2243 case NO_MUSIC: // keep the compiler happy for the moment :-)
2249 /* Time stops in pause mode */
2250 if(game_pause || show_menu )
2255 /* Pause til next frame: */
2257 now_time = SDL_GetTicks();
2258 if (now_time < last_time + FPS)
2259 SDL_Delay(last_time + FPS - now_time);
2264 if ((frame % 10) == 0 && time_left > 0)
2272 while (!done && !quit);
2274 if (playing_music())
2285 /* Initialize the game stuff: */
2297 /* Load data for this level: */
2299 void loadlevel(void)
2310 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2311 bouncy_distros[i].alive = NO;
2313 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2314 broken_bricks[i].alive = NO;
2316 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2317 bouncy_bricks[i].alive = NO;
2319 for (i = 0; i < NUM_BAD_GUYS; i++)
2320 bad_guys[i].alive = NO;
2322 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2323 floating_scores[i].alive = NO;
2325 for (i = 0; i < NUM_UPGRADES; i++)
2326 upgrades[i].alive = NO;
2328 for (i = 0; i < NUM_BULLETS; i++)
2329 bullets[i].alive = NO;
2332 /* Load data file: */
2334 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2335 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2336 fi = fopen(filename, "r");
2347 /* Load header info: */
2352 strcpy(levelname, str);
2353 levelname[strlen(levelname)-1] = '\0';
2357 strcpy(leveltheme, str);
2358 leveltheme[strlen(leveltheme)-1] = '\0';
2362 /* (Time to beat level) */
2364 time_left = atoi(str);
2366 /* (Song file for this level) */
2368 strcpy(song_title, str);
2369 song_title[strlen(song_title)-1] = '\0';
2373 /* (Level background color) */
2375 bkgd_red = atoi(str);
2377 bkgd_green= atoi(str);
2379 bkgd_blue = atoi(str);
2383 level_width = atoi(str);
2386 /* Allocate some space for the line-reading! */
2388 line = (char *) malloc(sizeof(char) * (level_width + 5));
2391 fprintf(stderr, "Couldn't allocate space to load level data!");
2396 /* Load the level lines: */
2398 for (y = 0; y < 15; y++)
2400 if(fgets(line, level_width + 5, fi) == NULL)
2402 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2405 line[strlen(line) - 1] = '\0';
2406 tiles[y] = strdup(line);
2412 /* Activate bad guys: */
2414 for (y = 0; y < 15; y++)
2416 for (x = 0; x < level_width; x++)
2418 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2420 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2435 tux_got_coffee = NO;
2436 tux_invincible_time = 0;
2440 tux_safe = TUX_SAFE_TIME;
2456 score_multiplier = 1;
2457 super_bkgd_time = 0;
2459 counting_distros = NO;
2464 /* set current song/music */
2465 current_music = LEVEL_MUSIC;
2469 clearscreen(0, 0, 0);
2471 sprintf(str, "LEVEL %d", level);
2472 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2474 sprintf(str, "%s", levelname);
2475 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2477 sprintf(str, "TUX x %d", lives);
2478 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2488 /* Load a level-specific graphic... */
2490 SDL_Surface * load_level_image(char * file, int use_alpha)
2494 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2496 return(load_image(fname, use_alpha));
2500 /* Load graphics: */
2502 void loadlevelgfx(void)
2504 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2505 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2507 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2508 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2509 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2510 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2512 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2513 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2514 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2515 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2517 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2518 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2519 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2520 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2526 void loadlevelsong(void)
2531 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2532 strlen(song_title) + 8));
2534 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2536 level_song = load_song(song_path);
2542 /* Free graphics data for this level: */
2544 void unloadlevelgfx(void)
2548 for (i = 0; i < 2; i++)
2550 SDL_FreeSurface(img_brick[i]);
2552 for (i = 0; i < 4; i++)
2554 SDL_FreeSurface(img_solid[i]);
2555 SDL_FreeSurface(img_bkgd[0][i]);
2556 SDL_FreeSurface(img_bkgd[1][i]);
2561 /* Free music data for this level: */
2563 void unloadlevelsong(void)
2565 free_music(level_song);
2569 /* Load graphics/sounds shared between all levels: */
2571 void loadshared(void)
2574 char * herring_song_path; /* for loading herring song*/
2578 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2581 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2584 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2587 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2590 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2593 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2596 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2599 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2602 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2605 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2608 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2611 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2614 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2618 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2620 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2623 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2626 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2630 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2633 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2637 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2641 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2645 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2648 ducktux_right = load_image(DATA_PREFIX
2649 "/images/shared/ducktux-right.png",
2652 ducktux_left = load_image(DATA_PREFIX
2653 "/images/shared/ducktux-left.png",
2656 skidtux_right = load_image(DATA_PREFIX
2657 "/images/shared/skidtux-right.png",
2660 skidtux_left = load_image(DATA_PREFIX
2661 "/images/shared/skidtux-left.png",
2667 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2669 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2676 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2678 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2681 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2684 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2690 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2691 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2697 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2699 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2705 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2708 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2711 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2714 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2718 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2721 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2724 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2727 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2735 img_bsod_left[0] = load_image(DATA_PREFIX
2736 "/images/shared/bsod-left-0.png",
2739 img_bsod_left[1] = load_image(DATA_PREFIX
2740 "/images/shared/bsod-left-1.png",
2743 img_bsod_left[2] = load_image(DATA_PREFIX
2744 "/images/shared/bsod-left-2.png",
2747 img_bsod_left[3] = load_image(DATA_PREFIX
2748 "/images/shared/bsod-left-3.png",
2751 img_bsod_right[0] = load_image(DATA_PREFIX
2752 "/images/shared/bsod-right-0.png",
2755 img_bsod_right[1] = load_image(DATA_PREFIX
2756 "/images/shared/bsod-right-1.png",
2759 img_bsod_right[2] = load_image(DATA_PREFIX
2760 "/images/shared/bsod-right-2.png",
2763 img_bsod_right[3] = load_image(DATA_PREFIX
2764 "/images/shared/bsod-right-3.png",
2767 img_bsod_squished_left = load_image(DATA_PREFIX
2768 "/images/shared/bsod-squished-left.png",
2771 img_bsod_squished_right = load_image(DATA_PREFIX
2772 "/images/shared/bsod-squished-right.png",
2775 img_bsod_falling_left = load_image(DATA_PREFIX
2776 "/images/shared/bsod-falling-left.png",
2779 img_bsod_falling_right = load_image(DATA_PREFIX
2780 "/images/shared/bsod-falling-right.png",
2786 img_laptop_left[0] = load_image(DATA_PREFIX
2787 "/images/shared/laptop-left-0.png",
2790 img_laptop_left[1] = load_image(DATA_PREFIX
2791 "/images/shared/laptop-left-1.png",
2794 img_laptop_left[2] = load_image(DATA_PREFIX
2795 "/images/shared/laptop-left-2.png",
2798 img_laptop_right[0] = load_image(DATA_PREFIX
2799 "/images/shared/laptop-right-0.png",
2802 img_laptop_right[1] = load_image(DATA_PREFIX
2803 "/images/shared/laptop-right-1.png",
2806 img_laptop_right[2] = load_image(DATA_PREFIX
2807 "/images/shared/laptop-right-2.png",
2810 img_laptop_flat_left = load_image(DATA_PREFIX
2811 "/images/shared/laptop-flat-left.png",
2814 img_laptop_flat_right = load_image(DATA_PREFIX
2815 "/images/shared/laptop-flat-right.png",
2818 img_laptop_falling_left =
2819 load_image(DATA_PREFIX
2820 "/images/shared/laptop-falling-left.png",
2823 img_laptop_falling_right =
2824 load_image(DATA_PREFIX
2825 "/images/shared/laptop-falling-right.png",
2831 img_money_left[0] = load_image(DATA_PREFIX
2832 "/images/shared/bag-left-0.png",
2835 img_money_left[1] = load_image(DATA_PREFIX
2836 "/images/shared/bag-left-1.png",
2839 img_money_right[0] = load_image(DATA_PREFIX
2840 "/images/shared/bag-right-0.png",
2843 img_money_right[1] = load_image(DATA_PREFIX
2844 "/images/shared/bag-right-1.png",
2851 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2852 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2857 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2859 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2865 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2868 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2871 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2874 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2880 img_golden_herring =
2881 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2885 /* Super background: */
2887 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2891 /* Sound effects: */
2893 /* if (use_sound) // this can help speeding up a little, but
2894 we shouldn't take care about "use_sound" here, it's load_sound's job
2895 / Send a mail to neoneurone@users.sf.net, if you have another opinion. :)
2897 for (i = 0; i < NUM_SOUNDS; i++)
2898 sounds[i] = load_sound(soundfilenames[i]);
2901 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2902 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
2904 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
2906 herring_song = load_song(herring_song_path);
2908 free(herring_song_path);
2913 /* Free shared data: */
2915 void unloadshared(void)
2919 for (i = 0; i < 3; i++)
2921 SDL_FreeSurface(tux_right[i]);
2922 SDL_FreeSurface(tux_left[i]);
2923 SDL_FreeSurface(bigtux_right[i]);
2924 SDL_FreeSurface(bigtux_left[i]);
2927 SDL_FreeSurface(bigtux_right_jump);
2928 SDL_FreeSurface(bigtux_left_jump);
2930 for (i = 0; i < 2; i++)
2932 SDL_FreeSurface(cape_right[i]);
2933 SDL_FreeSurface(cape_left[i]);
2934 SDL_FreeSurface(bigcape_right[i]);
2935 SDL_FreeSurface(bigcape_left[i]);
2938 SDL_FreeSurface(ducktux_left);
2939 SDL_FreeSurface(ducktux_right);
2941 SDL_FreeSurface(skidtux_left);
2942 SDL_FreeSurface(skidtux_right);
2944 for (i = 0; i < 4; i++)
2946 SDL_FreeSurface(img_bsod_left[i]);
2947 SDL_FreeSurface(img_bsod_right[i]);
2950 SDL_FreeSurface(img_bsod_squished_left);
2951 SDL_FreeSurface(img_bsod_squished_right);
2953 SDL_FreeSurface(img_bsod_falling_left);
2954 SDL_FreeSurface(img_bsod_falling_right);
2956 for (i = 0; i < 3; i++)
2958 SDL_FreeSurface(img_laptop_left[i]);
2959 SDL_FreeSurface(img_laptop_right[i]);
2962 SDL_FreeSurface(img_laptop_flat_left);
2963 SDL_FreeSurface(img_laptop_flat_right);
2965 SDL_FreeSurface(img_laptop_falling_left);
2966 SDL_FreeSurface(img_laptop_falling_right);
2968 for (i = 0; i < 2; i++)
2970 SDL_FreeSurface(img_money_left[i]);
2971 SDL_FreeSurface(img_money_right[i]);
2974 SDL_FreeSurface(img_box_full);
2975 SDL_FreeSurface(img_box_empty);
2977 SDL_FreeSurface(img_water);
2978 for (i = 0; i < 3; i++)
2979 SDL_FreeSurface(img_waves[i]);
2981 SDL_FreeSurface(img_pole);
2982 SDL_FreeSurface(img_poletop);
2984 for (i = 0; i < 2; i++)
2985 SDL_FreeSurface(img_flag[i]);
2987 SDL_FreeSurface(img_mints);
2988 SDL_FreeSurface(img_coffee);
2990 for (i = 0; i < 4; i++)
2992 SDL_FreeSurface(img_distro[i]);
2993 SDL_FreeSurface(img_cloud[0][i]);
2994 SDL_FreeSurface(img_cloud[1][i]);
2997 SDL_FreeSurface(img_golden_herring);
2999 for (i = 0; i < NUM_SOUNDS; i++)
3000 free_chunk(sounds[i]);
3002 /* free the herring song */
3003 free_music( herring_song );
3007 /* Draw a tile on the screen: */
3009 void drawshape(int x, int y, unsigned char c)
3013 if (c == 'X' || c == 'x')
3014 drawimage(img_brick[0], x, y, NO_UPDATE);
3015 else if (c == 'Y' || c == 'y')
3016 drawimage(img_brick[1], x, y, NO_UPDATE);
3017 else if (c == 'A' || c =='B' || c == '!')
3018 drawimage(img_box_full, x, y, NO_UPDATE);
3020 drawimage(img_box_empty, x, y, NO_UPDATE);
3021 else if (c >= 'C' && c <= 'F')
3022 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3023 else if (c >= 'c' && c <= 'f')
3024 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3025 else if (c >= 'G' && c <= 'J')
3026 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3027 else if (c >= 'g' && c <= 'j')
3028 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3030 drawimage(img_solid[0], x, y, NO_UPDATE);
3032 drawimage(img_solid[1], x, y, NO_UPDATE);
3034 drawimage(img_solid[2], x, y, NO_UPDATE);
3036 drawimage(img_solid[3], x, y, NO_UPDATE);
3039 z = (frame / 2) % 6;
3042 drawimage(img_distro[z], x, y, NO_UPDATE);
3044 drawimage(img_distro[2], x, y, NO_UPDATE);
3046 drawimage(img_distro[1], x, y, NO_UPDATE);
3050 z = (frame / 3) % 3;
3052 drawimage(img_waves[z], x, y, NO_UPDATE);
3055 drawimage(img_poletop, x, y, NO_UPDATE);
3058 drawimage(img_pole, x, y, NO_UPDATE);
3060 /* Mark this as the end position of the level! */
3066 z = (frame / 3) % 2;
3068 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3071 drawimage(img_water, x, y, NO_UPDATE);
3075 /* What shape is at some position? */
3077 unsigned char shape(int x, int y, int sx)
3083 xx = ((x + sx) / 32);
3085 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3096 int issolid(int x, int y, int sx)
3102 if (isbrick(x, y, sx) ||
3103 isbrick(x + 31, y, sx) ||
3105 isice(x + 31, y, sx) ||
3106 (shape(x, y, sx) == '[' ||
3107 shape(x + 31, y, sx) == '[') ||
3108 (shape(x, y, sx) == '=' ||
3109 shape(x + 31, y, sx) == '=') ||
3110 (shape(x, y, sx) == ']' ||
3111 shape(x + 31, y, sx) == ']') ||
3112 (shape(x, y, sx) == 'A' ||
3113 shape(x + 31, y, sx) == 'A') ||
3114 (shape(x, y, sx) == 'B' ||
3115 shape(x + 31, y, sx) == 'B') ||
3116 (shape(x, y, sx) == '!' ||
3117 shape(x + 31, y, sx) == '!') ||
3118 (shape(x, y, sx) == 'a' ||
3119 shape(x + 31, y, sx) == 'a'))
3128 /* Is it a brick? */
3130 int isbrick(int x, int y, int sx)
3136 if (shape(x, y, sx) == 'X' ||
3137 shape(x, y, sx) == 'x' ||
3138 shape(x, y, sx) == 'Y' ||
3139 shape(x, y, sx) == 'y')
3150 int isice(int x, int y, int sx)
3156 if (shape(x, y, sx) == '#')
3165 /* Is it a full box? */
3167 int isfullbox(int x, int y, int sx)
3173 if (shape(x, y, sx) == 'A' ||
3174 shape(x, y, sx) == 'B' ||
3175 shape(x, y, sx) == '!')
3184 /* Edit a piece of the map! */
3186 void change(int x, int y, int sx, unsigned char c)
3191 xx = ((x + sx) / 32);
3193 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3198 /* Break a brick: */
3200 void trybreakbrick(int x, int y, int sx)
3202 if (isbrick(x, y, sx))
3204 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3206 /* Get a distro from it: */
3208 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3211 if (counting_distros == NO)
3213 counting_distros = YES;
3214 distro_counter = 50;
3217 if (distro_counter <= 0)
3218 change(x, y, sx, 'a');
3220 play_sound(sounds[SND_DISTRO]);
3221 score = score + SCORE_DISTRO;
3226 /* Get rid of it: */
3228 change(x, y, sx, '.');
3232 /* Replace it with broken bits: */
3234 add_broken_brick(((x + sx + 1) / 32) * 32,
3238 /* Get some score: */
3240 play_sound(sounds[SND_BRICK]);
3241 score = score + SCORE_BRICK;
3246 /* Bounce a brick: */
3248 void bumpbrick(int x, int y, int sx)
3250 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3253 play_sound(sounds[SND_BRICK]);
3259 void tryemptybox(int x, int y, int sx)
3261 if (isfullbox(x, y, sx))
3263 if (shape(x, y, sx) == 'A')
3265 /* Box with a distro! */
3267 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3268 (y / 32) * 32 - 32);
3270 play_sound(sounds[SND_DISTRO]);
3271 score = score + SCORE_DISTRO;
3274 else if (shape(x, y, sx) == 'B')
3276 /* Add an upgrade! */
3278 if (tux_size == SMALL)
3280 /* Tux is small, add mints! */
3282 add_upgrade(((x + sx + 1) / 32) * 32,
3288 /* Tux is big, add coffee: */
3290 add_upgrade(((x + sx + 1) / 32) * 32,
3295 play_sound(sounds[SND_UPGRADE]);
3297 else if (shape(x, y, sx) == '!')
3299 /* Add a golden herring */
3301 add_upgrade(((x + sx + 1) / 32) * 32,
3306 /* Empty the box: */
3308 change(x, y, sx, 'a');
3313 /* Try to grab a distro: */
3315 void trygrabdistro(int x, int y, int sx, int bounciness)
3317 if (shape(x, y, sx) == '$')
3319 change(x, y, sx, '.');
3320 play_sound(sounds[SND_DISTRO]);
3322 if (bounciness == BOUNCE)
3324 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3328 score = score + SCORE_DISTRO;
3334 /* Add a bouncy distro: */
3336 void add_bouncy_distro(int x, int y)
3342 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3344 if (!bouncy_distros[i].alive)
3350 bouncy_distros[found].alive = YES;
3351 bouncy_distros[found].x = x;
3352 bouncy_distros[found].y = y;
3353 bouncy_distros[found].ym = -6;
3358 /* Add broken brick pieces: */
3360 void add_broken_brick(int x, int y)
3362 add_broken_brick_piece(x, y, -4, -16);
3363 add_broken_brick_piece(x, y + 16, -6, -12);
3365 add_broken_brick_piece(x + 16, y, 4, -16);
3366 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3370 /* Add a broken brick piece: */
3372 void add_broken_brick_piece(int x, int y, int xm, int ym)
3378 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3380 if (!broken_bricks[i].alive)
3386 broken_bricks[found].alive = YES;
3387 broken_bricks[found].x = x;
3388 broken_bricks[found].y = y;
3389 broken_bricks[found].xm = xm;
3390 broken_bricks[found].ym = ym;
3395 /* Add a bouncy brick piece: */
3397 void add_bouncy_brick(int x, int y)
3403 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3405 if (!bouncy_bricks[i].alive)
3411 bouncy_bricks[found].alive = YES;
3412 bouncy_bricks[found].x = x;
3413 bouncy_bricks[found].y = y;
3414 bouncy_bricks[found].offset = 0;
3415 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3416 bouncy_bricks[found].shape = shape(x, y, 0);
3421 /* Add a bad guy: */
3423 void add_bad_guy(int x, int y, int kind)
3429 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3431 if (!bad_guys[i].alive)
3437 bad_guys[found].alive = YES;
3438 bad_guys[found].mode = NORMAL;
3439 bad_guys[found].dying = NO;
3440 bad_guys[found].timer = 0;
3441 bad_guys[found].kind = kind;
3442 bad_guys[found].x = x;
3443 bad_guys[found].y = y;
3444 bad_guys[found].xm = 0;
3445 bad_guys[found].ym = 0;
3446 bad_guys[found].dir = LEFT;
3447 bad_guys[found].seen = NO;
3454 void add_score(int x, int y, int s)
3459 /* Add the score: */
3464 /* Add a floating score thing to the game: */
3468 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3470 if (!floating_scores[i].alive)
3477 floating_scores[found].alive = YES;
3478 floating_scores[found].x = x;
3479 floating_scores[found].y = y - 16;
3480 floating_scores[found].timer = 8;
3481 floating_scores[found].value = s;
3486 /* Try to bump a bad guy from below: */
3488 void trybumpbadguy(int x, int y, int sx)
3495 for (i = 0; i < NUM_BAD_GUYS; i++)
3497 if (bad_guys[i].alive &&
3498 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3499 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3501 if (bad_guys[i].kind == BAD_BSOD ||
3502 bad_guys[i].kind == BAD_LAPTOP)
3504 bad_guys[i].dying = FALLING;
3505 bad_guys[i].ym = -8;
3506 play_sound(sounds[SND_FALL]);
3514 for (i = 0; i < NUM_UPGRADES; i++)
3516 if (upgrades[i].alive && upgrades[i].height == 32 &&
3517 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3518 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3520 upgrades[i].xm = -upgrades[i].xm;
3521 upgrades[i].ym = -8;
3522 play_sound(sounds[SND_BUMP_UPGRADE]);
3528 /* Add an upgrade: */
3530 void add_upgrade(int x, int y, int kind)
3536 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3538 if (!upgrades[i].alive)
3544 upgrades[found].alive = YES;
3545 upgrades[found].kind = kind;
3546 upgrades[found].x = x;
3547 upgrades[found].y = y;
3548 upgrades[found].xm = 4;
3549 upgrades[found].ym = -4;
3550 upgrades[found].height = 0;
3557 void killtux(int mode)
3561 play_sound(sounds[SND_HURT]);
3563 if (tux_dir == RIGHT)
3565 else if (tux_dir == LEFT)
3568 if (mode == SHRINK && tux_size == BIG)
3571 tux_got_coffee = NO;
3575 tux_safe = TUX_SAFE_TIME;
3586 void add_bullet(int x, int y, int dir, int xm)
3592 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3594 if (!bullets[i].alive)
3600 bullets[found].alive = YES;
3604 bullets[found].x = x + 32;
3605 bullets[found].xm = BULLET_XM + xm;
3609 bullets[found].x = x;
3610 bullets[found].xm = -BULLET_XM + xm;
3613 bullets[found].y = y;
3614 bullets[found].ym = BULLET_STARTING_YM;
3616 play_sound(sounds[SND_SHOOT]);
3621 void drawendscreen(void)
3625 clearscreen(0, 0, 0);
3627 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3629 sprintf(str, "SCORE: %d", score);
3630 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3632 sprintf(str, "DISTROS: %d", distros);
3633 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3639 void drawresultscreen(void)
3643 clearscreen(0, 0, 0);
3645 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3647 sprintf(str, "SCORE: %d", score);
3648 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3650 sprintf(str, "DISTROS: %d", distros);
3651 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3654 /*SDL_Delay(2000);*/