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"
60 char * soundfilenames[NUM_SOUNDS] = {
61 DATA_PREFIX "/sounds/jump.wav",
62 DATA_PREFIX "/sounds/bigjump.wav",
63 DATA_PREFIX "/sounds/skid.wav",
64 DATA_PREFIX "/sounds/distro.wav",
65 DATA_PREFIX "/sounds/herring.wav",
66 DATA_PREFIX "/sounds/brick.wav",
67 DATA_PREFIX "/sounds/hurt.wav",
68 DATA_PREFIX "/sounds/squish.wav",
69 DATA_PREFIX "/sounds/fall.wav",
70 DATA_PREFIX "/sounds/ricochet.wav",
71 DATA_PREFIX "/sounds/bump-upgrade.wav",
72 DATA_PREFIX "/sounds/upgrade.wav",
73 DATA_PREFIX "/sounds/excellent.wav",
74 DATA_PREFIX "/sounds/coffee.wav",
75 DATA_PREFIX "/sounds/shoot.wav",
76 DATA_PREFIX "/sounds/lifeup.wav"
80 /* Local variables: */
82 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
83 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
84 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
85 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
86 super_bkgd_time, time_left, tux_invincible_time, endpos,
87 counting_distros, distro_counter;
88 int bkgd_red, bkgd_green, bkgd_blue, level_width;
89 int left, right, up, down, fire, old_fire;
90 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
91 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
92 SDL_Surface * img_bkgd[2][4];
93 SDL_Surface * img_golden_herring;
94 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
95 * img_laptop_left[3], * img_laptop_right[3],
96 * img_money_left[2], * img_money_right[2];
97 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
98 * img_bsod_falling_left, * img_bsod_falling_right,
99 * img_laptop_flat_left, * img_laptop_flat_right,
100 * img_laptop_falling_left, * img_laptop_falling_right;
101 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
102 * img_super_bkgd, * img_bullet, * img_red_glow;
103 SDL_Surface * img_cloud[2][4];
104 SDL_Surface * tux_right[3], * tux_left[3],
105 * bigtux_right[3], * bigtux_left[3],
106 * bigtux_right_jump, * bigtux_left_jump,
107 * cape_right[2], * cape_left[2],
108 * bigcape_right[2], * bigcape_left[2],
109 * ducktux_right, * ducktux_left,
110 * skidtux_right, * skidtux_left, * tux_life;
114 unsigned char * tiles[15];
115 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
116 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
117 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
118 bad_guy_type bad_guys[NUM_BAD_GUYS];
119 floating_score_type floating_scores[NUM_FLOATING_SCORES];
120 upgrade_type upgrades[NUM_UPGRADES];
121 bullet_type bullets[NUM_BULLETS];
127 /* Local function prototypes: */
130 void loadlevel(void);
131 void loadlevelgfx(void);
132 void loadlevelsong(void);
133 void unloadlevelgfx(void);
134 void unloadlevelsong(void);
135 void loadshared(void);
136 void unloadshared(void);
137 void drawshape(int x, int y, unsigned char c);
139 unsigned char shape(int x, int y, int sx);
140 int issolid(int x, int y, int sx);
141 int isbrick(int x, int y, int sx);
142 int isice(int x, int y, int sx);
143 int isfullbox(int x, int y, int sx);
144 void change(int x, int y, int sx, unsigned char c);
145 void trybreakbrick(int x, int y, int sx);
146 void bumpbrick(int x, int y, int sx);
147 void tryemptybox(int x, int y, int sx);
148 void trygrabdistro(int x, int y, int sx, int bounciness);
149 void add_bouncy_distro(int x, int y);
150 void add_broken_brick(int x, int y);
151 void add_broken_brick_piece(int x, int y, int xm, int ym);
152 void add_bouncy_brick(int x, int y);
153 void add_bad_guy(int x, int y, int kind);
154 void add_score(int x, int y, int s);
155 void trybumpbadguy(int x, int y, int sx);
156 void add_upgrade(int x, int y, int kind);
157 void killtux(int mode);
158 void add_bullet(int x, int y, int dir, int xm);
159 void drawendscreen(void);
160 void drawresultscreen(void);
162 /* --- GAME EVENT! --- */
164 void game_event(void)
167 while (SDL_PollEvent(&event))
170 if (event.type == SDL_QUIT)
172 /* Quit event - quit: */
176 else if (event.type == SDL_KEYDOWN)
180 key = event.key.keysym.sym;
182 /* Check for menu-events, if the menu is shown */
186 if (key == SDLK_ESCAPE)
188 /* Escape: Open/Close the menu: */
197 else if (key == SDLK_RIGHT)
201 else if (key == SDLK_LEFT)
205 else if (key == SDLK_UP)
209 else if (key == SDLK_DOWN)
213 else if (key == SDLK_LCTRL)
218 else if (event.type == SDL_KEYUP)
222 key = event.key.keysym.sym;
224 if (key == SDLK_RIGHT)
228 else if (key == SDLK_LEFT)
232 else if (key == SDLK_UP)
236 else if (key == SDLK_DOWN)
240 else if (key == SDLK_LCTRL)
244 else if (key == SDLK_p)
254 else if (key == SDLK_TAB && debug_mode == YES)
256 tux_size = !tux_size;
258 else if (key == SDLK_END && debug_mode == YES)
262 else if (key == SDLK_SPACE && debug_mode == YES)
268 else if (event.type == SDL_JOYAXISMOTION)
270 if (event.jaxis.axis == JOY_X)
272 if (event.jaxis.value < -256)
277 if (event.jaxis.value > 256)
282 else if (event.jaxis.axis == JOY_Y)
284 if (event.jaxis.value > 256)
289 /* Handle joystick for the menu */
293 menuaction = MN_DOWN;
299 else if (event.type == SDL_JOYBUTTONDOWN)
301 if (event.jbutton.button == JOY_A)
303 else if (event.jbutton.button == JOY_B)
306 else if (event.type == SDL_JOYBUTTONUP)
308 if (event.jbutton.button == JOY_A)
310 else if (event.jbutton.button == JOY_B)
323 /* --- GAME ACTION! --- */
325 int game_action(void)
329 /* --- HANDLE TUX! --- */
331 /* Handle key and joystick state: */
333 if (!(tux_dying || next_level))
335 if (right == DOWN && left == UP)
339 if (tux_xm < -SKID_XM && !tux_skidding &&
342 tux_skidding = SKID_TIME;
344 play_sound(sounds[SND_SKID]);
350 if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
358 if (tux_dir == RIGHT)
360 /* Facing the direction we're jumping? Go full-speed: */
364 tux_xm = tux_xm + WALK_SPEED;
366 if (tux_xm > MAX_WALK_XM)
367 tux_xm = MAX_WALK_XM;
369 else if (fire == DOWN)
371 tux_xm = tux_xm + RUN_SPEED;
373 if (tux_xm > MAX_RUN_XM)
379 /* Not facing the direction we're jumping?
382 tux_xm = tux_xm + WALK_SPEED / 2;
384 if (tux_xm > MAX_WALK_XM / 2)
385 tux_xm = MAX_WALK_XM / 2;
389 else if (left == DOWN && right == UP)
393 if (tux_xm > SKID_XM && !tux_skidding &&
396 tux_skidding = SKID_TIME;
397 play_sound(sounds[SND_SKID]);
402 if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
412 /* Facing the direction we're jumping? Go full-speed: */
416 tux_xm = tux_xm - WALK_SPEED;
418 if (tux_xm < -MAX_WALK_XM)
419 tux_xm = -MAX_WALK_XM;
421 else if (fire == DOWN)
423 tux_xm = tux_xm - RUN_SPEED;
425 if (tux_xm < -MAX_RUN_XM)
426 tux_xm = -MAX_RUN_XM;
431 /* Not facing the direction we're jumping?
434 tux_xm = tux_xm - WALK_SPEED / 2;
436 if (tux_xm < -MAX_WALK_XM / 2)
437 tux_xm = -MAX_WALK_XM / 2;
445 if (tux_x >= endpos && endpos != 0)
455 if (jump_counter == 0)
459 if (!issolid(tux_x, tux_y + 32, scroll_x) ||
462 /* If they're not on the ground, or are currently moving
463 vertically, don't jump! */
465 jump_counter = MAX_JUMP_COUNT;
469 /* Make sure we're not standing back up into a solid! */
471 if (tux_size == SMALL || tux_duck == NO ||
472 !issolid(tux_x, tux_y, scroll_x))
476 if (tux_size == SMALL)
477 play_sound(sounds[SND_JUMP]);
479 play_sound(sounds[SND_BIGJUMP]);
485 /* Keep jumping for a while: */
487 if (jump_counter < MAX_JUMP_COUNT)
489 tux_ym = tux_ym - JUMP_SPEED;
499 if (fire == DOWN && old_fire == UP && tux_got_coffee)
501 add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
514 if (tux_size == BIG && tux_duck == YES)
516 /* Make sure we're not standing back up into a solid! */
518 if (!issolid(tux_x, tux_y - 32, scroll_x))
524 } /* (tux_dying || next_level) */
527 /* Tux either died, or reached the end of a level! */
536 /* End of a level! */
544 tux_ym = tux_ym + GRAVITY;
552 /* No more lives!? */
558 if (score > highscore)
565 } /* if (lives < 0) */
568 /* Either way, (re-)load the (next) level... */
579 tux_x = tux_x + tux_xm;
580 tux_y = tux_y + tux_ym;
583 /* Keep tux in bounds: */
586 else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
588 scroll_x = scroll_x - ( 160 - tux_x);
595 else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
597 /* Scroll the screen in past center: */
599 scroll_x = scroll_x + (tux_x - 320);
602 if (scroll_x > ((level_width * 32) - 640))
603 scroll_x = ((level_width * 32) - 640);
605 else if (tux_x > 608)
607 /* ... unless there's no more to scroll! */
617 if (issolid(tux_x, tux_y + 31, scroll_x) &&
618 !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
620 while (issolid(tux_x, tux_y + 31, scroll_x))
631 if (issolid(tux_x, tux_y, scroll_x) &&
632 !issolid(tux_x - tux_xm, tux_y, scroll_x))
634 while (issolid(tux_x, tux_y, scroll_x))
645 if (issolid(tux_x, tux_y + 31, scroll_x))
647 /* Set down properly: */
649 while (issolid(tux_x, tux_y + 31, scroll_x))
658 /* Reset score multiplier (for mutli-hits): */
661 score_multiplier = 1;
671 /* Bump into things: */
673 if (issolid(tux_x, tux_y, scroll_x) ||
674 (tux_size == BIG && !tux_duck &&
675 (issolid(tux_x, tux_y - 32, scroll_x))))
677 if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
678 (tux_size == SMALL || tux_duck ||
679 !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
681 tux_x = tux_x - tux_xm;
684 else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
685 (tux_size == SMALL || tux_duck ||
686 !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
694 /* Break bricks and empty boxes: */
698 if (isbrick(tux_x, tux_y - 32, scroll_x) ||
699 isfullbox(tux_x, tux_y - 32, scroll_x))
701 trygrabdistro(tux_x, tux_y - 64, scroll_x,
703 trybumpbadguy(tux_x, tux_y - 96, scroll_x);
705 if (isfullbox(tux_x, tux_y - 32,
708 bumpbrick(tux_x, tux_y - 32,
712 trybreakbrick(tux_x, tux_y - 32, scroll_x);
713 tryemptybox(tux_x, tux_y - 32, scroll_x);
716 if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
717 isfullbox(tux_x + 31, tux_y - 32, scroll_x))
719 trygrabdistro(tux_x + 31,
723 trybumpbadguy(tux_x + 31,
727 if (isfullbox(tux_x + 31, tux_y - 32,
730 bumpbrick(tux_x + 31, tux_y - 32,
734 trybreakbrick(tux_x + 31,
737 tryemptybox(tux_x + 31,
744 if (isbrick(tux_x, tux_y, scroll_x) ||
745 isfullbox(tux_x, tux_y, scroll_x))
747 trygrabdistro(tux_x, tux_y - 32, scroll_x,
749 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
750 if (isfullbox(tux_x, tux_y, scroll_x))
751 bumpbrick(tux_x, tux_y, scroll_x);
752 trybreakbrick(tux_x, tux_y, scroll_x);
753 tryemptybox(tux_x, tux_y, scroll_x);
756 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
757 isfullbox(tux_x + 31, tux_y, scroll_x))
759 trygrabdistro(tux_x + 31,
763 trybumpbadguy(tux_x + 31,
766 if (isfullbox(tux_x + 31, tux_y, scroll_x))
767 bumpbrick(tux_x + 31, tux_y, scroll_x);
768 trybreakbrick(tux_x + 31, tux_y, scroll_x);
769 tryemptybox(tux_x + 31, tux_y, scroll_x);
775 /* It's a brick and we're small, make the brick
776 bounce, and grab any distros above it: */
778 if (isbrick(tux_x, tux_y, scroll_x) ||
779 isfullbox(tux_x, tux_y, scroll_x))
781 trygrabdistro(tux_x, tux_y - 32, scroll_x,
783 trybumpbadguy(tux_x, tux_y - 64, scroll_x);
784 bumpbrick(tux_x, tux_y, scroll_x);
785 tryemptybox(tux_x, tux_y, scroll_x);
788 if (isbrick(tux_x + 31, tux_y, scroll_x) ||
789 isfullbox(tux_x + 31, tux_y, scroll_x))
791 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
793 trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
794 bumpbrick(tux_x + 31, tux_y, scroll_x);
795 tryemptybox(tux_x + 31, tux_y, scroll_x);
799 /* Get a distro from a brick? */
801 if (shape(tux_x, tux_y, scroll_x) == 'x' ||
802 shape(tux_x, tux_y, scroll_x) == 'y')
804 add_bouncy_distro(((tux_x + scroll_x + 1)
808 if (counting_distros == NO)
810 counting_distros = YES;
811 distro_counter = 100;
814 if (distro_counter <= 0)
815 change(tux_x, tux_y, scroll_x, 'a');
817 play_sound(sounds[SND_DISTRO]);
818 score = score + SCORE_DISTRO;
821 else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
822 shape(tux_x + 31, tux_y, scroll_x) == 'y')
824 add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
828 if (counting_distros == NO)
830 counting_distros = YES;
831 distro_counter = 100;
834 if (distro_counter <= 0)
835 change(tux_x + 31, tux_y, scroll_x, 'a');
837 play_sound(sounds[SND_DISTRO]);
838 score = score + SCORE_DISTRO;
846 tux_y = (tux_y / 32) * 32 + 30;
852 tux_y = (tux_y / 32) * 32 - 32;
857 jump_counter = MAX_JUMP_COUNT;
867 trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
868 trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
870 if (tux_size == BIG && !tux_duck)
872 trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
873 trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
878 /* Enough distros for a One-up? */
880 if (distros >= DISTROS_LIFEUP)
882 distros = distros - DISTROS_LIFEUP;
883 if(lives < MAX_LIVES)
885 play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
889 /* Keep in-bounds, vertically: */
893 else if (tux_y > 480)
899 /* Slow down horizontally: */
903 if (right == UP && left == UP)
905 if (isice(tux_x, tux_y + 32, scroll_x) ||
906 !issolid(tux_x, tux_y + 32, scroll_x))
908 /* Slowly on ice or in air: */
917 /* Quickly, otherwise: */
924 /* Drop vertically: */
926 if (!issolid(tux_x, tux_y + 32, scroll_x))
928 tux_ym = tux_ym + GRAVITY;
940 /* ---- DONE HANDLING TUX! --- */
943 /* Handle bouncy distros: */
945 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
947 if (bouncy_distros[i].alive)
949 bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
951 bouncy_distros[i].ym++;
953 if (bouncy_distros[i].ym >= 0)
954 bouncy_distros[i].alive = NO;
959 /* Handle broken bricks: */
961 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
963 if (broken_bricks[i].alive)
965 broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
966 broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
968 broken_bricks[i].ym++;
970 if (broken_bricks[i].ym >= 0)
971 broken_bricks[i].alive = NO;
976 /* Handle distro counting: */
978 if (counting_distros == YES)
982 if (distro_counter <= 0)
983 counting_distros = -1;
987 /* Handle bouncy bricks: */
989 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
991 if (bouncy_bricks[i].alive)
993 bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
994 bouncy_bricks[i].offset_m);
998 if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
999 bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
1002 /* Stop bouncing? */
1004 if (bouncy_bricks[i].offset == 0)
1005 bouncy_bricks[i].alive = NO;
1010 /* Handle floating scores: */
1012 for (i = 0; i < NUM_FLOATING_SCORES; i++)
1014 if (floating_scores[i].alive)
1016 floating_scores[i].y = floating_scores[i].y - 2;
1017 floating_scores[i].timer--;
1019 if (floating_scores[i].timer <= 0)
1020 floating_scores[i].alive = NO;
1025 /* Handle bullets: */
1027 for (i = 0; i < NUM_BULLETS; i++)
1029 if (bullets[i].alive)
1031 bullets[i].x = bullets[i].x + bullets[i].xm;
1032 bullets[i].y = bullets[i].y + bullets[i].ym;
1034 if (issolid(bullets[i].x, bullets[i].y, 0))
1036 if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1037 bullets[i].alive = NO;
1040 if (bullets[i].ym >= 0)
1042 bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1044 bullets[i].ym = -bullets[i].ym;
1048 bullets[i].ym = bullets[i].ym + GRAVITY;
1050 if (bullets[i].x < scroll_x ||
1051 bullets[i].x > scroll_x + 640)
1053 bullets[i].alive = NO;
1058 if (bullets[i].alive)
1060 for (j = 0; j < NUM_BAD_GUYS; j++)
1062 if (bad_guys[j].alive && !bad_guys[j].dying)
1064 if (bullets[i].x >= bad_guys[j].x - 4 &&
1065 bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1066 bullets[i].y >= bad_guys[j].y - 4 &&
1067 bullets[i].y <= bad_guys[j].y + 32 + 4)
1069 /* Kill the bad guy! */
1071 bullets[i].alive = 0;
1072 bad_guys[j].dying = FALLING;
1073 bad_guys[j].ym = -8;
1076 /* Gain some points: */
1078 if (bad_guys[j].kind == BAD_BSOD)
1080 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1081 50 * score_multiplier);
1083 else if (bad_guys[j].kind == BAD_LAPTOP)
1085 add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1086 25 * score_multiplier);
1090 /* Play death sound: */
1091 play_sound(sounds[SND_FALL]);
1099 /* Handle background timer: */
1101 if (super_bkgd_time)
1105 /* Handle invincibility timer: */
1108 if (tux_invincible_time > 50)
1110 tux_invincible_time--;
1113 if (!playing_music())
1114 play_music( herring_song, 1 );
1118 if (current_music == HERRING_MUSIC)
1120 /* stop the herring_song, now play the level_song ! */
1121 current_music = LEVEL_MUSIC;
1124 if (!playing_music())
1125 play_music( level_song, 1 );
1126 if (tux_invincible_time > 0)
1127 tux_invincible_time--;
1131 /* Handle upgrades: */
1133 for (i = 0; i < NUM_UPGRADES; i++)
1135 if (upgrades[i].alive)
1137 if (upgrades[i].height < 32)
1141 upgrades[i].height++;
1147 if (upgrades[i].kind == UPGRADE_MINTS ||
1148 upgrades[i].kind == UPGRADE_HERRING)
1150 upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1151 upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1153 if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1154 issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1156 if (upgrades[i].ym > 0)
1158 if (upgrades[i].kind == UPGRADE_MINTS)
1162 else if (upgrades[i].kind == UPGRADE_HERRING)
1164 upgrades[i].ym = -24;
1167 upgrades[i].y = (upgrades[i].y / 32) * 32;
1171 upgrades[i].ym = upgrades[i].ym + GRAVITY;
1173 if (issolid(upgrades[i].x, upgrades[i].y, 0))
1175 upgrades[i].xm = -upgrades[i].xm;
1180 /* Off the screen? Kill it! */
1182 if (upgrades[i].x < scroll_x)
1183 upgrades[i].alive = NO;
1186 /* Did the player grab it? */
1188 if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1189 tux_x + scroll_x <= upgrades[i].x + 32 &&
1190 tux_y >= upgrades[i].y - 32 &&
1191 tux_y <= upgrades[i].y + 32)
1193 /* Remove the upgrade: */
1195 upgrades[i].alive = NO;
1198 /* Affect the player: */
1200 if (upgrades[i].kind == UPGRADE_MINTS)
1202 play_sound(sounds[SND_EXCELLENT]);
1204 super_bkgd_time = 8;
1206 else if (upgrades[i].kind == UPGRADE_COFFEE)
1208 play_sound(sounds[SND_COFFEE]);
1209 tux_got_coffee = YES;
1210 super_bkgd_time = 4;
1212 else if (upgrades[i].kind == UPGRADE_HERRING)
1214 play_sound(sounds[SND_HERRING]);
1215 tux_invincible_time = TUX_INVINCIBLE_TIME;
1216 super_bkgd_time = 4;
1217 /* play the herring song ^^ */
1218 current_music = HERRING_MUSIC;
1219 if (playing_music())
1221 play_music( herring_song, 1 );
1229 /* Handle bad guys: */
1231 for (i = 0; i < NUM_BAD_GUYS; i++)
1233 if (bad_guys[i].alive)
1235 if (bad_guys[i].seen)
1237 if (bad_guys[i].kind == BAD_BSOD)
1239 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1241 /* Move left/right: */
1243 if (bad_guys[i].dying == NO ||
1244 bad_guys[i].dying == FALLING)
1246 if (bad_guys[i].dir == RIGHT)
1247 bad_guys[i].x = bad_guys[i].x + 4;
1248 else if (bad_guys[i].dir == LEFT)
1249 bad_guys[i].x = bad_guys[i].x - 4;
1253 /* Move vertically: */
1255 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1258 /* Bump into things horizontally: */
1260 if (!bad_guys[i].dying)
1262 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1263 bad_guys[i].dir = !bad_guys[i].dir;
1267 /* Bump into other bad guys: */
1269 for (j = 0; j < NUM_BAD_GUYS; j++)
1271 if (j != i && bad_guys[j].alive &&
1272 !bad_guys[j].dying && !bad_guys[i].dying &&
1273 bad_guys[i].x >= bad_guys[j].x - 32 &&
1274 bad_guys[i].x <= bad_guys[j].x + 32 &&
1275 bad_guys[i].y >= bad_guys[j].y - 32 &&
1276 bad_guys[i].y <= bad_guys[j].y + 32)
1278 bad_guys[i].dir = !bad_guys[i].dir;
1283 /* Fall if we get off the ground: */
1285 if (bad_guys[i].dying != FALLING)
1287 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1288 bad_guys[i].ym < MAX_YM)
1290 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1296 if (bad_guys[i].ym > 0)
1298 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1304 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1306 if (bad_guys[i].y > 480)
1307 bad_guys[i].alive = NO;
1309 else if (bad_guys[i].kind == BAD_LAPTOP)
1311 /* --- LAPTOP MONSTER: --- */
1313 /* Move left/right: */
1315 if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1317 if (bad_guys[i].dying == NO ||
1318 bad_guys[i].dying == FALLING)
1320 if (bad_guys[i].dir == RIGHT)
1321 bad_guys[i].x = bad_guys[i].x + 4;
1322 else if (bad_guys[i].dir == LEFT)
1323 bad_guys[i].x = bad_guys[i].x - 4;
1326 else if (bad_guys[i].mode == KICK)
1328 if (bad_guys[i].dir == RIGHT)
1329 bad_guys[i].x = bad_guys[i].x + 16;
1330 else if (bad_guys[i].dir == LEFT)
1331 bad_guys[i].x = bad_guys[i].x - 16;
1335 /* Move vertically: */
1337 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1340 /* Bump into things horizontally: */
1342 if (!bad_guys[i].dying)
1344 if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1346 bad_guys[i].dir = !bad_guys[i].dir;
1348 if (bad_guys[i].mode == KICK)
1349 play_sound(sounds[SND_RICOCHET]);
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 if (bad_guys[i].mode != KICK)
1366 bad_guys[i].dir = !bad_guys[i].dir;
1369 /* We're in kick mode, kill the other guy: */
1371 bad_guys[j].dying = FALLING;
1372 bad_guys[j].ym = -8;
1373 play_sound(sounds[SND_FALL]);
1375 add_score(bad_guys[i].x - scroll_x,
1376 bad_guys[i].y, 100);
1382 /* Fall if we get off the ground: */
1384 if (bad_guys[i].dying != FALLING)
1386 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1387 bad_guys[i].ym < MAX_YM)
1389 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1395 if (bad_guys[i].ym > 0)
1397 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1403 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1405 if (bad_guys[i].y > 480)
1406 bad_guys[i].alive = NO;
1408 else if (bad_guys[i].kind == BAD_MONEY)
1410 /* --- MONEY BAGS: --- */
1413 /* Move vertically: */
1415 bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1418 /* Fall if we get off the ground: */
1420 if (bad_guys[i].dying != FALLING)
1422 if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1424 if (bad_guys[i].ym < MAX_YM)
1426 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1433 if (bad_guys[i].ym > 0)
1435 bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1436 bad_guys[i].ym = -MAX_YM;
1441 bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1443 if (bad_guys[i].y > 480)
1444 bad_guys[i].alive = NO;
1446 else if (bad_guys[i].kind == -1)
1450 /* Kill it if the player jumped on it: */
1452 if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1453 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1454 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1455 tux_y >= bad_guys[i].y - 32 &&
1456 tux_y <= bad_guys[i].y - 8
1460 if (bad_guys[i].kind == BAD_BSOD)
1462 bad_guys[i].dying = SQUISHED;
1463 bad_guys[i].timer = 16;
1464 tux_ym = -KILL_BOUNCE_YM;
1466 add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1467 50 * score_multiplier);
1469 play_sound(sounds[SND_SQUISH]);
1471 else if (bad_guys[i].kind == BAD_LAPTOP)
1473 if (bad_guys[i].mode != FLAT)
1477 bad_guys[i].mode = FLAT;
1479 bad_guys[i].timer = 64;
1487 bad_guys[i].mode = KICK;
1489 if (tux_x + scroll_x <= bad_guys[i].x)
1490 bad_guys[i].dir = RIGHT;
1492 bad_guys[i].dir = LEFT;
1494 bad_guys[i].timer = 8;
1497 tux_ym = -KILL_BOUNCE_YM;
1499 add_score(bad_guys[i].x - scroll_x,
1501 25 * score_multiplier);
1503 /* play_sound(sounds[SND_SQUISH]); */
1505 else if (bad_guys[i].kind == -1)
1512 /* Hurt the player if he just touched it: */
1514 if (!bad_guys[i].dying && !tux_dying &&
1516 tux_x + scroll_x >= bad_guys[i].x - 32 &&
1517 tux_x + scroll_x <= bad_guys[i].x + 32 &&
1518 tux_y >= bad_guys[i].y - 32 &&
1519 tux_y <= bad_guys[i].y + 32)
1521 if (bad_guys[i].mode == FLAT)
1525 bad_guys[i].mode = KICK;
1527 if (tux_x + scroll_x <= bad_guys[i].x)
1529 bad_guys[i].dir = RIGHT;
1530 bad_guys[i].x = bad_guys[i].x + 16;
1534 bad_guys[i].dir = LEFT;
1535 bad_guys[i].x = bad_guys[i].x - 16;
1538 bad_guys[i].timer = 8;
1540 else if (bad_guys[i].mode == KICK)
1542 if (tux_y < bad_guys[i].y - 16 &&
1543 bad_guys[i].timer == 0)
1545 /* Step on (stop being kicked) */
1547 bad_guys[i].mode = FLAT;
1548 bad_guys[i].timer = 64;
1552 /* Hurt if you get hit by kicked laptop: */
1554 if (bad_guys[i].timer == 0)
1556 if (tux_invincible_time == 0)
1562 bad_guys[i].dying = FALLING;
1563 bad_guys[i].ym = -8;
1564 play_sound(sounds[SND_FALL]);
1571 if (tux_invincible_time == 0)
1577 bad_guys[i].dying = FALLING;
1578 bad_guys[i].ym = -8;
1579 play_sound(sounds[SND_FALL]);
1585 /* Handle mode timer: */
1587 if (bad_guys[i].mode == FLAT)
1589 bad_guys[i].timer--;
1591 if (bad_guys[i].timer <= 0)
1592 bad_guys[i].mode = NORMAL;
1594 else if (bad_guys[i].mode == KICK)
1596 if (bad_guys[i].timer > 0)
1597 bad_guys[i].timer--;
1601 /* Handle dying timer: */
1603 if (bad_guys[i].dying == SQUISHED)
1605 bad_guys[i].timer--;
1608 /* Remove it if time's up: */
1610 if (bad_guys[i].timer <= 0)
1611 bad_guys[i].alive = NO;
1615 /* Remove if it's far off the screen: */
1617 if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1618 bad_guys[i].alive = NO;
1622 /* Once it's on screen, it's activated! */
1624 if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1625 bad_guys[i].seen = YES;
1631 /* Handle skidding: */
1633 if (tux_skidding > 0)
1641 /* --- GAME DRAW! --- */
1649 if (tux_dying && (frame % 4) == 0)
1650 clearscreen(255, 255, 255);
1653 if (super_bkgd_time == 0)
1654 clearscreen(bkgd_red, bkgd_green, bkgd_blue);
1656 drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1660 /* Draw background: */
1662 for (y = 0; y < 15; y++)
1664 for (x = 0; x < 21; x++)
1666 drawshape(x * 32 - (scroll_x % 32), y * 32,
1667 tiles[y][x + (scroll_x / 32)]);
1672 /* (Bouncy bricks): */
1674 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1676 if (bouncy_bricks[i].alive)
1678 if (bouncy_bricks[i].x >= scroll_x - 32 &&
1679 bouncy_bricks[i].x <= scroll_x + 640)
1681 dest.x = bouncy_bricks[i].x - scroll_x;
1682 dest.y = bouncy_bricks[i].y;
1686 SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1691 drawshape(bouncy_bricks[i].x - scroll_x,
1692 bouncy_bricks[i].y + bouncy_bricks[i].offset,
1693 bouncy_bricks[i].shape);
1701 for (i = 0; i < NUM_BAD_GUYS; i++)
1703 if (bad_guys[i].alive &&
1704 bad_guys[i].x > scroll_x - 32 &&
1705 bad_guys[i].x < scroll_x + 640)
1707 if (bad_guys[i].kind == BAD_BSOD)
1709 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1711 if (bad_guys[i].dying == NO)
1715 if (bad_guys[i].dir == LEFT)
1717 drawimage(img_bsod_left[(frame / 5) % 4],
1718 bad_guys[i].x - scroll_x,
1724 drawimage(img_bsod_right[(frame / 5) % 4],
1725 bad_guys[i].x - scroll_x,
1730 else if (bad_guys[i].dying == FALLING)
1734 if (bad_guys[i].dir == LEFT)
1736 drawimage(img_bsod_falling_left,
1737 bad_guys[i].x - scroll_x,
1743 drawimage(img_bsod_falling_right,
1744 bad_guys[i].x - scroll_x,
1749 else if (bad_guys[i].dying == SQUISHED)
1751 /* Dying - Squished: */
1753 if (bad_guys[i].dir == LEFT)
1755 drawimage(img_bsod_squished_left,
1756 bad_guys[i].x - scroll_x,
1762 drawimage(img_bsod_squished_right,
1763 bad_guys[i].x - scroll_x,
1769 else if (bad_guys[i].kind == BAD_LAPTOP)
1771 /* --- LAPTOP MONSTER: --- */
1773 if (bad_guys[i].dying == NO)
1777 if (bad_guys[i].mode == NORMAL)
1781 if (bad_guys[i].dir == LEFT)
1783 drawimage(img_laptop_left[(frame / 5) % 3],
1784 bad_guys[i].x - scroll_x,
1790 drawimage(img_laptop_right[(frame / 5) % 3],
1791 bad_guys[i].x - scroll_x,
1800 if (bad_guys[i].dir == LEFT)
1802 drawimage(img_laptop_flat_left,
1803 bad_guys[i].x - scroll_x,
1809 drawimage(img_laptop_flat_right,
1810 bad_guys[i].x - scroll_x,
1816 else if (bad_guys[i].dying == FALLING)
1820 if (bad_guys[i].dir == LEFT)
1822 drawimage(img_laptop_falling_left,
1823 bad_guys[i].x - scroll_x,
1829 drawimage(img_laptop_falling_right,
1830 bad_guys[i].x - scroll_x,
1836 else if (bad_guys[i].kind == BAD_MONEY)
1838 if (bad_guys[i].ym > -16)
1840 if (bad_guys[i].dir == LEFT)
1842 drawimage(img_money_left[0],
1843 bad_guys[i].x - scroll_x,
1849 drawimage(img_money_right[0],
1850 bad_guys[i].x - scroll_x,
1857 if (bad_guys[i].dir == LEFT)
1859 drawimage(img_money_left[1],
1860 bad_guys[i].x - scroll_x,
1866 drawimage(img_money_right[1],
1867 bad_guys[i].x - scroll_x,
1873 else if (bad_guys[i].kind == -1)
1881 if (right == UP && left == UP)
1888 if ((fire == DOWN && (frame % 2) == 0) ||
1890 tux_frame_main = (tux_frame_main + 1) % 4;
1892 tux_frame = tux_frame_main;
1899 if (tux_got_coffee && (frame % 2) == 1)
1903 drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
1907 if (tux_safe == 0 || (frame % 2) == 0)
1909 if (tux_size == SMALL)
1911 if (tux_invincible_time)
1915 if (tux_dir == RIGHT)
1917 drawimage(cape_right[frame % 2],
1923 drawimage(cape_left[frame % 2],
1930 if (tux_dir == RIGHT)
1932 drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
1936 drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
1941 if (tux_invincible_time)
1945 if (tux_dir == RIGHT)
1947 drawimage(bigcape_right[frame % 2],
1948 tux_x - 8 - 16, tux_y - 32,
1953 drawimage(bigcape_left[frame % 2],
1954 tux_x - 8, tux_y - 32,
1963 if (!jumping || tux_ym > 0)
1965 if (tux_dir == RIGHT)
1967 drawimage(bigtux_right[tux_frame],
1968 tux_x - 8, tux_y - 32,
1973 drawimage(bigtux_left[tux_frame],
1974 tux_x - 8, tux_y - 32,
1980 if (tux_dir == RIGHT)
1982 drawimage(bigtux_right_jump,
1983 tux_x - 8, tux_y - 32,
1988 drawimage(bigtux_left_jump,
1989 tux_x - 8, tux_y - 32,
1996 if (tux_dir == RIGHT)
1998 drawimage(skidtux_right,
1999 tux_x - 8, tux_y - 32,
2004 drawimage(skidtux_left,
2005 tux_x - 8, tux_y - 32,
2012 if (tux_dir == RIGHT)
2014 drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2019 drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2029 for (i = 0; i < NUM_BULLETS; i++)
2031 if (bullets[i].alive &&
2032 bullets[i].x >= scroll_x - 4 &&
2033 bullets[i].x <= scroll_x + 640)
2035 drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2041 /* (Floating scores): */
2043 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2045 if (floating_scores[i].alive)
2047 sprintf(str, "%d", floating_scores[i].value);
2049 floating_scores[i].x + 16 - strlen(str) * 8,
2050 floating_scores[i].y,
2051 letters_gold, NO_UPDATE);
2058 for (i = 0; i < NUM_UPGRADES; i++)
2060 if (upgrades[i].alive)
2062 if (upgrades[i].height < 32)
2066 dest.x = upgrades[i].x - scroll_x;
2067 dest.y = upgrades[i].y + 32 - upgrades[i].height;
2069 dest.h = upgrades[i].height;
2074 src.h = upgrades[i].height;
2076 if (upgrades[i].kind == UPGRADE_MINTS)
2077 SDL_BlitSurface(img_mints, &src, screen, &dest);
2078 else if (upgrades[i].kind == UPGRADE_COFFEE)
2079 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2080 else if (upgrades[i].kind == UPGRADE_HERRING)
2081 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2085 if (upgrades[i].kind == UPGRADE_MINTS)
2087 drawimage(img_mints,
2088 upgrades[i].x - scroll_x, upgrades[i].y,
2091 else if (upgrades[i].kind == UPGRADE_COFFEE)
2093 drawimage(img_coffee,
2094 upgrades[i].x - scroll_x, upgrades[i].y,
2097 else if (upgrades[i].kind == UPGRADE_HERRING)
2099 drawimage(img_golden_herring,
2100 upgrades[i].x - scroll_x, upgrades[i].y,
2108 /* (Bouncy distros): */
2110 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2112 if (bouncy_distros[i].alive)
2114 drawimage(img_distro[0],
2115 bouncy_distros[i].x - scroll_x,
2116 bouncy_distros[i].y,
2122 /* (Broken bricks): */
2124 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2126 if (broken_bricks[i].alive)
2128 src.x = rand() % 16;
2129 src.y = rand() % 16;
2133 dest.x = broken_bricks[i].x - scroll_x;
2134 dest.y = broken_bricks[i].y;
2138 SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2145 sprintf(str, "%d", score);
2146 drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
2147 drawtext(str, 96, 0, letters_gold, NO_UPDATE);
2149 sprintf(str, "%d", highscore);
2150 drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
2151 drawtext(str, 96, 20, letters_gold, NO_UPDATE);
2153 if (time_left >= 50 || (frame % 10) < 5)
2155 sprintf(str, "%d", time_left);
2156 drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
2157 drawtext(str, 304, 0, letters_gold, NO_UPDATE);
2160 sprintf(str, "%d", distros);
2161 drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
2162 drawtext(str, 608, 0, letters_gold, NO_UPDATE);
2164 drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE);
2166 for(i=0; i < lives; ++i)
2168 drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2172 drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
2177 /* (Update it all!) */
2184 /* --- GAME LOOP! --- */
2189 Uint32 last_time, now_time;
2193 clearscreen(0, 0, 0);
2197 /* Init the game: */
2205 highscore = load_hs();
2208 /* --- MAIN GAME LOOP!!! --- */
2220 last_time = SDL_GetTicks();
2224 /* Handle events: */
2230 /* Handle actions: */
2232 if(!game_pause && !show_menu)
2234 if (game_action() == 0)
2236 /* == 0: no more lives */
2237 /* == -1: continues */
2244 /*Draw the current scene to the screen */
2247 /* Keep playing music: */
2250 if (!playing_music())
2252 switch (current_music)
2255 play_music(level_song, 1);
2258 play_music(herring_song, 1);
2260 case HURRYUP_MUSIC: // keep the compiler happy
2261 case NO_MUSIC: // keep the compiler happy for the moment :-)
2267 /* Time stops in pause mode */
2268 if(game_pause || show_menu )
2273 /* Pause til next frame: */
2275 now_time = SDL_GetTicks();
2276 if (now_time < last_time + FPS)
2277 SDL_Delay(last_time + FPS - now_time);
2282 if ((frame % 10) == 0 && time_left > 0)
2290 while (!done && !quit);
2292 if (playing_music())
2303 /* Initialize the game stuff: */
2315 /* Load data for this level: */
2317 void loadlevel(void)
2328 for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2329 bouncy_distros[i].alive = NO;
2331 for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2332 broken_bricks[i].alive = NO;
2334 for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
2335 bouncy_bricks[i].alive = NO;
2337 for (i = 0; i < NUM_BAD_GUYS; i++)
2338 bad_guys[i].alive = NO;
2340 for (i = 0; i < NUM_FLOATING_SCORES; i++)
2341 floating_scores[i].alive = NO;
2343 for (i = 0; i < NUM_UPGRADES; i++)
2344 upgrades[i].alive = NO;
2346 for (i = 0; i < NUM_BULLETS; i++)
2347 bullets[i].alive = NO;
2350 /* Load data file: */
2352 filename = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + 20));
2353 sprintf(filename, "%s/levels/level%d.dat", DATA_PREFIX, level);
2354 fi = fopen(filename, "r");
2365 /* Load header info: */
2370 strcpy(levelname, str);
2371 levelname[strlen(levelname)-1] = '\0';
2375 strcpy(leveltheme, str);
2376 leveltheme[strlen(leveltheme)-1] = '\0';
2380 /* (Time to beat level) */
2382 time_left = atoi(str);
2384 /* (Song file for this level) */
2386 strcpy(song_title, str);
2387 song_title[strlen(song_title)-1] = '\0';
2391 /* (Level background color) */
2393 bkgd_red = atoi(str);
2395 bkgd_green= atoi(str);
2397 bkgd_blue = atoi(str);
2401 level_width = atoi(str);
2404 /* Allocate some space for the line-reading! */
2406 line = (char *) malloc(sizeof(char) * (level_width + 5));
2409 fprintf(stderr, "Couldn't allocate space to load level data!");
2414 /* Load the level lines: */
2416 for (y = 0; y < 15; y++)
2418 if(fgets(line, level_width + 5, fi) == NULL)
2420 fprintf(stderr, "Level %s isn't complete!\n",levelname);
2423 line[strlen(line) - 1] = '\0';
2424 tiles[y] = strdup(line);
2430 /* Activate bad guys: */
2432 for (y = 0; y < 15; y++)
2434 for (x = 0; x < level_width; x++)
2436 if (tiles[y][x] >= '0' && tiles[y][x] <= '9')
2438 add_bad_guy(x * 32, y * 32, tiles[y][x] - '0');
2453 tux_got_coffee = NO;
2454 tux_invincible_time = 0;
2458 tux_safe = TUX_SAFE_TIME;
2474 score_multiplier = 1;
2475 super_bkgd_time = 0;
2477 counting_distros = NO;
2482 /* set current song/music */
2483 current_music = LEVEL_MUSIC;
2487 clearscreen(0, 0, 0);
2489 sprintf(str, "LEVEL %d", level);
2490 drawcenteredtext(str, 200, letters_red, NO_UPDATE);
2492 sprintf(str, "%s", levelname);
2493 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
2495 sprintf(str, "TUX x %d", lives);
2496 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
2506 /* Load a level-specific graphic... */
2508 SDL_Surface * load_level_image(char * file, int use_alpha)
2512 snprintf(fname, 1024, "%s/images/%s/%s", DATA_PREFIX, leveltheme, file);
2514 return(load_image(fname, use_alpha));
2518 /* Load graphics: */
2520 void loadlevelgfx(void)
2522 img_brick[0] = load_level_image("brick0.png", IGNORE_ALPHA);
2523 img_brick[1] = load_level_image("brick1.png", IGNORE_ALPHA);
2525 img_solid[0] = load_level_image("solid0.png", USE_ALPHA);
2526 img_solid[1] = load_level_image("solid1.png", USE_ALPHA);
2527 img_solid[2] = load_level_image("solid2.png", USE_ALPHA);
2528 img_solid[3] = load_level_image("solid3.png", USE_ALPHA);
2530 img_bkgd[0][0] = load_level_image("bkgd-00.png", USE_ALPHA);
2531 img_bkgd[0][1] = load_level_image("bkgd-01.png", USE_ALPHA);
2532 img_bkgd[0][2] = load_level_image("bkgd-02.png", USE_ALPHA);
2533 img_bkgd[0][3] = load_level_image("bkgd-03.png", USE_ALPHA);
2535 img_bkgd[1][0] = load_level_image("bkgd-10.png", USE_ALPHA);
2536 img_bkgd[1][1] = load_level_image("bkgd-11.png", USE_ALPHA);
2537 img_bkgd[1][2] = load_level_image("bkgd-12.png", USE_ALPHA);
2538 img_bkgd[1][3] = load_level_image("bkgd-13.png", USE_ALPHA);
2544 void loadlevelsong(void)
2549 song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2550 strlen(song_title) + 8));
2552 sprintf(song_path, "%s/music/%s", DATA_PREFIX, song_title);
2554 level_song = load_song(song_path);
2560 /* Free graphics data for this level: */
2562 void unloadlevelgfx(void)
2566 for (i = 0; i < 2; i++)
2568 SDL_FreeSurface(img_brick[i]);
2570 for (i = 0; i < 4; i++)
2572 SDL_FreeSurface(img_solid[i]);
2573 SDL_FreeSurface(img_bkgd[0][i]);
2574 SDL_FreeSurface(img_bkgd[1][i]);
2579 /* Free music data for this level: */
2581 void unloadlevelsong(void)
2583 free_music(level_song);
2587 /* Load graphics/sounds shared between all levels: */
2589 void loadshared(void)
2592 char * herring_song_path; /* for loading herring song*/
2596 tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2599 tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2602 tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2605 tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2608 tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2611 tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2614 cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2617 cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2620 cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2623 cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2626 bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2629 bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2632 bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2636 load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2638 bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2641 bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2644 bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2648 load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2651 load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2655 load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2659 load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2663 load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2666 ducktux_right = load_image(DATA_PREFIX
2667 "/images/shared/ducktux-right.png",
2670 ducktux_left = load_image(DATA_PREFIX
2671 "/images/shared/ducktux-left.png",
2674 skidtux_right = load_image(DATA_PREFIX
2675 "/images/shared/skidtux-right.png",
2678 skidtux_left = load_image(DATA_PREFIX
2679 "/images/shared/skidtux-left.png",
2685 img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2687 img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2694 img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2696 img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2699 img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2702 img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2708 img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2709 img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2715 img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2717 img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2723 img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2726 img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2729 img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2732 img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2736 img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2739 img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2742 img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2745 img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2753 img_bsod_left[0] = load_image(DATA_PREFIX
2754 "/images/shared/bsod-left-0.png",
2757 img_bsod_left[1] = load_image(DATA_PREFIX
2758 "/images/shared/bsod-left-1.png",
2761 img_bsod_left[2] = load_image(DATA_PREFIX
2762 "/images/shared/bsod-left-2.png",
2765 img_bsod_left[3] = load_image(DATA_PREFIX
2766 "/images/shared/bsod-left-3.png",
2769 img_bsod_right[0] = load_image(DATA_PREFIX
2770 "/images/shared/bsod-right-0.png",
2773 img_bsod_right[1] = load_image(DATA_PREFIX
2774 "/images/shared/bsod-right-1.png",
2777 img_bsod_right[2] = load_image(DATA_PREFIX
2778 "/images/shared/bsod-right-2.png",
2781 img_bsod_right[3] = load_image(DATA_PREFIX
2782 "/images/shared/bsod-right-3.png",
2785 img_bsod_squished_left = load_image(DATA_PREFIX
2786 "/images/shared/bsod-squished-left.png",
2789 img_bsod_squished_right = load_image(DATA_PREFIX
2790 "/images/shared/bsod-squished-right.png",
2793 img_bsod_falling_left = load_image(DATA_PREFIX
2794 "/images/shared/bsod-falling-left.png",
2797 img_bsod_falling_right = load_image(DATA_PREFIX
2798 "/images/shared/bsod-falling-right.png",
2804 img_laptop_left[0] = load_image(DATA_PREFIX
2805 "/images/shared/laptop-left-0.png",
2808 img_laptop_left[1] = load_image(DATA_PREFIX
2809 "/images/shared/laptop-left-1.png",
2812 img_laptop_left[2] = load_image(DATA_PREFIX
2813 "/images/shared/laptop-left-2.png",
2816 img_laptop_right[0] = load_image(DATA_PREFIX
2817 "/images/shared/laptop-right-0.png",
2820 img_laptop_right[1] = load_image(DATA_PREFIX
2821 "/images/shared/laptop-right-1.png",
2824 img_laptop_right[2] = load_image(DATA_PREFIX
2825 "/images/shared/laptop-right-2.png",
2828 img_laptop_flat_left = load_image(DATA_PREFIX
2829 "/images/shared/laptop-flat-left.png",
2832 img_laptop_flat_right = load_image(DATA_PREFIX
2833 "/images/shared/laptop-flat-right.png",
2836 img_laptop_falling_left =
2837 load_image(DATA_PREFIX
2838 "/images/shared/laptop-falling-left.png",
2841 img_laptop_falling_right =
2842 load_image(DATA_PREFIX
2843 "/images/shared/laptop-falling-right.png",
2849 img_money_left[0] = load_image(DATA_PREFIX
2850 "/images/shared/bag-left-0.png",
2853 img_money_left[1] = load_image(DATA_PREFIX
2854 "/images/shared/bag-left-1.png",
2857 img_money_right[0] = load_image(DATA_PREFIX
2858 "/images/shared/bag-right-0.png",
2861 img_money_right[1] = load_image(DATA_PREFIX
2862 "/images/shared/bag-right-1.png",
2869 img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2870 img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2875 img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2877 img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2883 img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2886 img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2889 img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2892 img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2897 tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
2902 img_golden_herring =
2903 load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2907 /* Super background: */
2909 img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2913 /* Sound effects: */
2915 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
2916 // initialize sounds[i] with the correct pointer's value:
2917 // NULL or something else. And it will be dangerous to
2918 // play with not-initialized pointers.
2919 // This is also true with if (use_music)
2920 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
2922 for (i = 0; i < NUM_SOUNDS; i++)
2923 sounds[i] = load_sound(soundfilenames[i]);
2926 herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2927 strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
2929 sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
2931 herring_song = load_song(herring_song_path);
2933 free(herring_song_path);
2938 /* Free shared data: */
2940 void unloadshared(void)
2944 for (i = 0; i < 3; i++)
2946 SDL_FreeSurface(tux_right[i]);
2947 SDL_FreeSurface(tux_left[i]);
2948 SDL_FreeSurface(bigtux_right[i]);
2949 SDL_FreeSurface(bigtux_left[i]);
2952 SDL_FreeSurface(bigtux_right_jump);
2953 SDL_FreeSurface(bigtux_left_jump);
2955 for (i = 0; i < 2; i++)
2957 SDL_FreeSurface(cape_right[i]);
2958 SDL_FreeSurface(cape_left[i]);
2959 SDL_FreeSurface(bigcape_right[i]);
2960 SDL_FreeSurface(bigcape_left[i]);
2963 SDL_FreeSurface(ducktux_left);
2964 SDL_FreeSurface(ducktux_right);
2966 SDL_FreeSurface(skidtux_left);
2967 SDL_FreeSurface(skidtux_right);
2969 for (i = 0; i < 4; i++)
2971 SDL_FreeSurface(img_bsod_left[i]);
2972 SDL_FreeSurface(img_bsod_right[i]);
2975 SDL_FreeSurface(img_bsod_squished_left);
2976 SDL_FreeSurface(img_bsod_squished_right);
2978 SDL_FreeSurface(img_bsod_falling_left);
2979 SDL_FreeSurface(img_bsod_falling_right);
2981 for (i = 0; i < 3; i++)
2983 SDL_FreeSurface(img_laptop_left[i]);
2984 SDL_FreeSurface(img_laptop_right[i]);
2987 SDL_FreeSurface(img_laptop_flat_left);
2988 SDL_FreeSurface(img_laptop_flat_right);
2990 SDL_FreeSurface(img_laptop_falling_left);
2991 SDL_FreeSurface(img_laptop_falling_right);
2993 for (i = 0; i < 2; i++)
2995 SDL_FreeSurface(img_money_left[i]);
2996 SDL_FreeSurface(img_money_right[i]);
2999 SDL_FreeSurface(img_box_full);
3000 SDL_FreeSurface(img_box_empty);
3002 SDL_FreeSurface(img_water);
3003 for (i = 0; i < 3; i++)
3004 SDL_FreeSurface(img_waves[i]);
3006 SDL_FreeSurface(img_pole);
3007 SDL_FreeSurface(img_poletop);
3009 for (i = 0; i < 2; i++)
3010 SDL_FreeSurface(img_flag[i]);
3012 SDL_FreeSurface(img_mints);
3013 SDL_FreeSurface(img_coffee);
3015 for (i = 0; i < 4; i++)
3017 SDL_FreeSurface(img_distro[i]);
3018 SDL_FreeSurface(img_cloud[0][i]);
3019 SDL_FreeSurface(img_cloud[1][i]);
3022 SDL_FreeSurface(img_golden_herring);
3024 for (i = 0; i < NUM_SOUNDS; i++)
3025 free_chunk(sounds[i]);
3027 /* free the herring song */
3028 free_music( herring_song );
3032 /* Draw a tile on the screen: */
3034 void drawshape(int x, int y, unsigned char c)
3038 if (c == 'X' || c == 'x')
3039 drawimage(img_brick[0], x, y, NO_UPDATE);
3040 else if (c == 'Y' || c == 'y')
3041 drawimage(img_brick[1], x, y, NO_UPDATE);
3042 else if (c == 'A' || c =='B' || c == '!')
3043 drawimage(img_box_full, x, y, NO_UPDATE);
3045 drawimage(img_box_empty, x, y, NO_UPDATE);
3046 else if (c >= 'C' && c <= 'F')
3047 drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3048 else if (c >= 'c' && c <= 'f')
3049 drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3050 else if (c >= 'G' && c <= 'J')
3051 drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3052 else if (c >= 'g' && c <= 'j')
3053 drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3055 drawimage(img_solid[0], x, y, NO_UPDATE);
3057 drawimage(img_solid[1], x, y, NO_UPDATE);
3059 drawimage(img_solid[2], x, y, NO_UPDATE);
3061 drawimage(img_solid[3], x, y, NO_UPDATE);
3064 z = (frame / 2) % 6;
3067 drawimage(img_distro[z], x, y, NO_UPDATE);
3069 drawimage(img_distro[2], x, y, NO_UPDATE);
3071 drawimage(img_distro[1], x, y, NO_UPDATE);
3075 z = (frame / 3) % 3;
3077 drawimage(img_waves[z], x, y, NO_UPDATE);
3080 drawimage(img_poletop, x, y, NO_UPDATE);
3083 drawimage(img_pole, x, y, NO_UPDATE);
3085 /* Mark this as the end position of the level! */
3091 z = (frame / 3) % 2;
3093 drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3096 drawimage(img_water, x, y, NO_UPDATE);
3100 /* What shape is at some position? */
3102 unsigned char shape(int x, int y, int sx)
3108 xx = ((x + sx) / 32);
3110 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3121 int issolid(int x, int y, int sx)
3127 if (isbrick(x, y, sx) ||
3128 isbrick(x + 31, y, sx) ||
3130 isice(x + 31, y, sx) ||
3131 (shape(x, y, sx) == '[' ||
3132 shape(x + 31, y, sx) == '[') ||
3133 (shape(x, y, sx) == '=' ||
3134 shape(x + 31, y, sx) == '=') ||
3135 (shape(x, y, sx) == ']' ||
3136 shape(x + 31, y, sx) == ']') ||
3137 (shape(x, y, sx) == 'A' ||
3138 shape(x + 31, y, sx) == 'A') ||
3139 (shape(x, y, sx) == 'B' ||
3140 shape(x + 31, y, sx) == 'B') ||
3141 (shape(x, y, sx) == '!' ||
3142 shape(x + 31, y, sx) == '!') ||
3143 (shape(x, y, sx) == 'a' ||
3144 shape(x + 31, y, sx) == 'a'))
3153 /* Is it a brick? */
3155 int isbrick(int x, int y, int sx)
3161 if (shape(x, y, sx) == 'X' ||
3162 shape(x, y, sx) == 'x' ||
3163 shape(x, y, sx) == 'Y' ||
3164 shape(x, y, sx) == 'y')
3175 int isice(int x, int y, int sx)
3181 if (shape(x, y, sx) == '#')
3190 /* Is it a full box? */
3192 int isfullbox(int x, int y, int sx)
3198 if (shape(x, y, sx) == 'A' ||
3199 shape(x, y, sx) == 'B' ||
3200 shape(x, y, sx) == '!')
3209 /* Edit a piece of the map! */
3211 void change(int x, int y, int sx, unsigned char c)
3216 xx = ((x + sx) / 32);
3218 if (yy >= 0 && yy <= 15 && xx >= 0 && xx <= level_width)
3223 /* Break a brick: */
3225 void trybreakbrick(int x, int y, int sx)
3227 if (isbrick(x, y, sx))
3229 if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3231 /* Get a distro from it: */
3233 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3236 if (counting_distros == NO)
3238 counting_distros = YES;
3239 distro_counter = 50;
3242 if (distro_counter <= 0)
3243 change(x, y, sx, 'a');
3245 play_sound(sounds[SND_DISTRO]);
3246 score = score + SCORE_DISTRO;
3251 /* Get rid of it: */
3253 change(x, y, sx, '.');
3257 /* Replace it with broken bits: */
3259 add_broken_brick(((x + sx + 1) / 32) * 32,
3263 /* Get some score: */
3265 play_sound(sounds[SND_BRICK]);
3266 score = score + SCORE_BRICK;
3271 /* Bounce a brick: */
3273 void bumpbrick(int x, int y, int sx)
3275 add_bouncy_brick(((x + sx + 1) / 32) * 32,
3278 play_sound(sounds[SND_BRICK]);
3284 void tryemptybox(int x, int y, int sx)
3286 if (isfullbox(x, y, sx))
3288 if (shape(x, y, sx) == 'A')
3290 /* Box with a distro! */
3292 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3293 (y / 32) * 32 - 32);
3295 play_sound(sounds[SND_DISTRO]);
3296 score = score + SCORE_DISTRO;
3299 else if (shape(x, y, sx) == 'B')
3301 /* Add an upgrade! */
3303 if (tux_size == SMALL)
3305 /* Tux is small, add mints! */
3307 add_upgrade(((x + sx + 1) / 32) * 32,
3313 /* Tux is big, add coffee: */
3315 add_upgrade(((x + sx + 1) / 32) * 32,
3320 play_sound(sounds[SND_UPGRADE]);
3322 else if (shape(x, y, sx) == '!')
3324 /* Add a golden herring */
3326 add_upgrade(((x + sx + 1) / 32) * 32,
3331 /* Empty the box: */
3333 change(x, y, sx, 'a');
3338 /* Try to grab a distro: */
3340 void trygrabdistro(int x, int y, int sx, int bounciness)
3342 if (shape(x, y, sx) == '$')
3344 change(x, y, sx, '.');
3345 play_sound(sounds[SND_DISTRO]);
3347 if (bounciness == BOUNCE)
3349 add_bouncy_distro(((x + sx + 1) / 32) * 32,
3353 score = score + SCORE_DISTRO;
3359 /* Add a bouncy distro: */
3361 void add_bouncy_distro(int x, int y)
3367 for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3369 if (!bouncy_distros[i].alive)
3375 bouncy_distros[found].alive = YES;
3376 bouncy_distros[found].x = x;
3377 bouncy_distros[found].y = y;
3378 bouncy_distros[found].ym = -6;
3383 /* Add broken brick pieces: */
3385 void add_broken_brick(int x, int y)
3387 add_broken_brick_piece(x, y, -4, -16);
3388 add_broken_brick_piece(x, y + 16, -6, -12);
3390 add_broken_brick_piece(x + 16, y, 4, -16);
3391 add_broken_brick_piece(x + 16, y + 16, 6, -12);
3395 /* Add a broken brick piece: */
3397 void add_broken_brick_piece(int x, int y, int xm, int ym)
3403 for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3405 if (!broken_bricks[i].alive)
3411 broken_bricks[found].alive = YES;
3412 broken_bricks[found].x = x;
3413 broken_bricks[found].y = y;
3414 broken_bricks[found].xm = xm;
3415 broken_bricks[found].ym = ym;
3420 /* Add a bouncy brick piece: */
3422 void add_bouncy_brick(int x, int y)
3428 for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3430 if (!bouncy_bricks[i].alive)
3436 bouncy_bricks[found].alive = YES;
3437 bouncy_bricks[found].x = x;
3438 bouncy_bricks[found].y = y;
3439 bouncy_bricks[found].offset = 0;
3440 bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3441 bouncy_bricks[found].shape = shape(x, y, 0);
3446 /* Add a bad guy: */
3448 void add_bad_guy(int x, int y, int kind)
3454 for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3456 if (!bad_guys[i].alive)
3462 bad_guys[found].alive = YES;
3463 bad_guys[found].mode = NORMAL;
3464 bad_guys[found].dying = NO;
3465 bad_guys[found].timer = 0;
3466 bad_guys[found].kind = kind;
3467 bad_guys[found].x = x;
3468 bad_guys[found].y = y;
3469 bad_guys[found].xm = 0;
3470 bad_guys[found].ym = 0;
3471 bad_guys[found].dir = LEFT;
3472 bad_guys[found].seen = NO;
3479 void add_score(int x, int y, int s)
3484 /* Add the score: */
3489 /* Add a floating score thing to the game: */
3493 for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3495 if (!floating_scores[i].alive)
3502 floating_scores[found].alive = YES;
3503 floating_scores[found].x = x;
3504 floating_scores[found].y = y - 16;
3505 floating_scores[found].timer = 8;
3506 floating_scores[found].value = s;
3511 /* Try to bump a bad guy from below: */
3513 void trybumpbadguy(int x, int y, int sx)
3520 for (i = 0; i < NUM_BAD_GUYS; i++)
3522 if (bad_guys[i].alive &&
3523 bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3524 bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3526 if (bad_guys[i].kind == BAD_BSOD ||
3527 bad_guys[i].kind == BAD_LAPTOP)
3529 bad_guys[i].dying = FALLING;
3530 bad_guys[i].ym = -8;
3531 play_sound(sounds[SND_FALL]);
3539 for (i = 0; i < NUM_UPGRADES; i++)
3541 if (upgrades[i].alive && upgrades[i].height == 32 &&
3542 upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3543 upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3545 upgrades[i].xm = -upgrades[i].xm;
3546 upgrades[i].ym = -8;
3547 play_sound(sounds[SND_BUMP_UPGRADE]);
3553 /* Add an upgrade: */
3555 void add_upgrade(int x, int y, int kind)
3561 for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3563 if (!upgrades[i].alive)
3569 upgrades[found].alive = YES;
3570 upgrades[found].kind = kind;
3571 upgrades[found].x = x;
3572 upgrades[found].y = y;
3573 upgrades[found].xm = 4;
3574 upgrades[found].ym = -4;
3575 upgrades[found].height = 0;
3582 void killtux(int mode)
3586 play_sound(sounds[SND_HURT]);
3588 if (tux_dir == RIGHT)
3590 else if (tux_dir == LEFT)
3593 if (mode == SHRINK && tux_size == BIG)
3596 tux_got_coffee = NO;
3600 tux_safe = TUX_SAFE_TIME;
3611 void add_bullet(int x, int y, int dir, int xm)
3617 for (i = 0; i < NUM_BULLETS && found == -1; i++)
3619 if (!bullets[i].alive)
3625 bullets[found].alive = YES;
3629 bullets[found].x = x + 32;
3630 bullets[found].xm = BULLET_XM + xm;
3634 bullets[found].x = x;
3635 bullets[found].xm = -BULLET_XM + xm;
3638 bullets[found].y = y;
3639 bullets[found].ym = BULLET_STARTING_YM;
3641 play_sound(sounds[SND_SHOOT]);
3646 void drawendscreen(void)
3650 clearscreen(0, 0, 0);
3652 drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE);
3654 sprintf(str, "SCORE: %d", score);
3655 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3657 sprintf(str, "DISTROS: %d", distros);
3658 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3664 void drawresultscreen(void)
3668 clearscreen(0, 0, 0);
3670 drawcenteredtext("Result:", 200, letters_red, NO_UPDATE);
3672 sprintf(str, "SCORE: %d", score);
3673 drawcenteredtext(str, 224, letters_gold, NO_UPDATE);
3675 sprintf(str, "DISTROS: %d", distros);
3676 drawcenteredtext(str, 256, letters_blue, NO_UPDATE);
3679 /*SDL_Delay(2000);*/