+ if(scroll_x < 0)
+ scroll_x = 0;
+
+ }
+ else if (tux_x > 320 && scroll_x < ((level_width * 32) - 640))
+ {
+ /* Scroll the screen in past center: */
+
+ scroll_x = scroll_x + (tux_x - 320);
+ tux_x = 320;
+
+ if (scroll_x > ((level_width * 32) - 640))
+ scroll_x = ((level_width * 32) - 640);
+ }
+ else if (tux_x > 608)
+ {
+ /* ... unless there's no more to scroll! */
+
+ tux_x = 608;
+ }
+
+
+ /* Land: */
+
+ if (!tux_dying)
+ {
+ if (issolid(tux_x, tux_y + 31, scroll_x) &&
+ !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
+ {
+ while (issolid(tux_x, tux_y + 31, scroll_x))
+ {
+ if (tux_xm < 0)
+ tux_x++;
+ else if (tux_xm > 0)
+ tux_x--;
+ }
+
+ tux_xm = 0;
+ }
+
+ if (issolid(tux_x, tux_y, scroll_x) &&
+ !issolid(tux_x - tux_xm, tux_y, scroll_x))
+ {
+ while (issolid(tux_x, tux_y, scroll_x))
+ {
+ if (tux_xm < 0)
+ tux_x++;
+ else if (tux_xm > 0)
+ tux_x--;
+ }
+
+ tux_xm = 0;
+ }
+
+ if (issolid(tux_x, tux_y + 31, scroll_x))
+ {
+ /* Set down properly: */
+
+ while (issolid(tux_x, tux_y + 31, scroll_x))
+ {
+ if (tux_ym < 0)
+ tux_y++;
+ else if (tux_ym > 0)
+ tux_y--;
+ }
+
+
+ /* Reset score multiplier (for mutli-hits): */
+
+ if (tux_ym > 0)
+ score_multiplier = 1;
+
+
+ /* Stop jumping! */
+
+ tux_ym = 0;
+ jumping = NO;
+ }
+
+
+ /* Bump into things: */
+
+ if (issolid(tux_x, tux_y, scroll_x) ||
+ (tux_size == BIG && !tux_duck &&
+ (issolid(tux_x, tux_y - 32, scroll_x))))
+ {
+ if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
+ (tux_size == SMALL || tux_duck ||
+ !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
+ {
+ tux_x = tux_x - tux_xm;
+ tux_xm = 0;
+ }
+ else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
+ (tux_size == SMALL || tux_duck ||
+ !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
+ {
+ if (tux_ym <= 0)
+ {
+ /* Jumping up? */
+
+ if (tux_size == BIG)
+ {
+ /* Break bricks and empty boxes: */
+
+ if (!tux_duck)
+ {
+ if (isbrick(tux_x, tux_y - 32, scroll_x) ||
+ isfullbox(tux_x, tux_y - 32, scroll_x))
+ {
+ trygrabdistro(tux_x, tux_y - 64, scroll_x,
+ BOUNCE);
+ trybumpbadguy(tux_x, tux_y - 96, scroll_x);
+
+ if (isfullbox(tux_x, tux_y - 32,
+ scroll_x))
+ {
+ bumpbrick(tux_x, tux_y - 32,
+ scroll_x);
+ }
+
+ trybreakbrick(tux_x, tux_y - 32, scroll_x);
+ tryemptybox(tux_x, tux_y - 32, scroll_x);
+ }
+
+ if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
+ isfullbox(tux_x + 31, tux_y - 32, scroll_x))
+ {
+ trygrabdistro(tux_x + 31,
+ tux_y - 64,
+ scroll_x,
+ BOUNCE);
+ trybumpbadguy(tux_x + 31,
+ tux_y - 96,
+ scroll_x);
+
+ if (isfullbox(tux_x + 31, tux_y - 32,
+ scroll_x))
+ {
+ bumpbrick(tux_x + 31, tux_y - 32,
+ scroll_x);
+ }
+
+ trybreakbrick(tux_x + 31,
+ tux_y - 32,
+ scroll_x);
+ tryemptybox(tux_x + 31,
+ tux_y - 32,
+ scroll_x);
+ }
+ }
+ else /* ducking */
+ {
+ if (isbrick(tux_x, tux_y, scroll_x) ||
+ isfullbox(tux_x, tux_y, scroll_x))
+ {
+ trygrabdistro(tux_x, tux_y - 32, scroll_x,
+ BOUNCE);
+ trybumpbadguy(tux_x, tux_y - 64, scroll_x);
+ if (isfullbox(tux_x, tux_y, scroll_x))
+ bumpbrick(tux_x, tux_y, scroll_x);
+ trybreakbrick(tux_x, tux_y, scroll_x);
+ tryemptybox(tux_x, tux_y, scroll_x);
+ }
+
+ if (isbrick(tux_x + 31, tux_y, scroll_x) ||
+ isfullbox(tux_x + 31, tux_y, scroll_x))
+ {
+ trygrabdistro(tux_x + 31,
+ tux_y - 32,
+ scroll_x,
+ BOUNCE);
+ trybumpbadguy(tux_x + 31,
+ tux_y - 64,
+ scroll_x);
+ if (isfullbox(tux_x + 31, tux_y, scroll_x))
+ bumpbrick(tux_x + 31, tux_y, scroll_x);
+ trybreakbrick(tux_x + 31, tux_y, scroll_x);
+ tryemptybox(tux_x + 31, tux_y, scroll_x);
+ }
+ }
+ }
+ else
+ {
+ /* It's a brick and we're small, make the brick
+ bounce, and grab any distros above it: */
+
+ if (isbrick(tux_x, tux_y, scroll_x) ||
+ isfullbox(tux_x, tux_y, scroll_x))
+ {
+ trygrabdistro(tux_x, tux_y - 32, scroll_x,
+ BOUNCE);
+ trybumpbadguy(tux_x, tux_y - 64, scroll_x);
+ bumpbrick(tux_x, tux_y, scroll_x);
+ tryemptybox(tux_x, tux_y, scroll_x);
+ }
+
+ if (isbrick(tux_x + 31, tux_y, scroll_x) ||
+ isfullbox(tux_x + 31, tux_y, scroll_x))
+ {
+ trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
+ BOUNCE);
+ trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
+ bumpbrick(tux_x + 31, tux_y, scroll_x);
+ tryemptybox(tux_x + 31, tux_y, scroll_x);
+ }
+
+
+ /* Get a distro from a brick? */
+
+ if (shape(tux_x, tux_y, scroll_x) == 'x' ||
+ shape(tux_x, tux_y, scroll_x) == 'y')
+ {
+ add_bouncy_distro(((tux_x + scroll_x + 1)
+ / 32) * 32,
+ (tux_y / 32) * 32);
+
+ if (counting_distros == NO)
+ {
+ counting_distros = YES;
+ distro_counter = 100;
+ }
+
+ if (distro_counter <= 0)
+ change(tux_x, tux_y, scroll_x, 'a');
+
+ play_sound(sounds[SND_DISTRO]);
+ score = score + SCORE_DISTRO;
+ distros++;
+ }
+ else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
+ shape(tux_x + 31, tux_y, scroll_x) == 'y')
+ {
+ add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
+ / 32) * 32,
+ (tux_y / 32) * 32);
+
+ if (counting_distros == NO)
+ {
+ counting_distros = YES;
+ distro_counter = 100;
+ }
+
+ if (distro_counter <= 0)
+ change(tux_x + 31, tux_y, scroll_x, 'a');
+
+ play_sound(sounds[SND_DISTRO]);
+ score = score + SCORE_DISTRO;
+ distros++;
+ }
+ }
+
+
+ /* Bump head: */
+
+ tux_y = (tux_y / 32) * 32 + 30;
+ }
+ else
+ {
+ /* Land on feet: */
+
+ tux_y = (tux_y / 32) * 32 - 32;
+ }
+
+ tux_ym = 0;
+ jumping = NO;
+ jump_counter = MAX_JUMP_COUNT;
+ }
+ }
+ }
+
+
+ /* Grab distros: */
+
+ if (!tux_dying)
+ {
+ trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
+ trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
+
+ if (tux_size == BIG && !tux_duck)
+ {
+ trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
+ trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
+ }
+ }
+
+
+ /* Enough distros for a One-up? */
+
+ if (distros >= DISTROS_LIFEUP)
+ {
+ distros = distros - DISTROS_LIFEUP;
+ if(lives < MAX_LIVES)
+ lives++;
+ play_sound(sounds[SND_LIFEUP]); /*We want to hear the sound even, if MAX_LIVES is reached*/
+ }
+
+
+ /* Keep in-bounds, vertically: */
+
+ if (tux_y < 0)
+ tux_y = 0;
+ else if (tux_y > 480)
+ {
+ killtux(KILL);
+ }
+
+
+ /* Slow down horizontally: */
+
+ if (!tux_dying)
+ {
+ if (right == UP && left == UP)
+ {
+ if (isice(tux_x, tux_y + 32, scroll_x) ||
+ !issolid(tux_x, tux_y + 32, scroll_x))
+ {
+ /* Slowly on ice or in air: */
+
+ if (tux_xm > 0)
+ tux_xm--;
+ else if (tux_xm < 0)
+ tux_xm++;
+ }
+ else
+ {
+ /* Quickly, otherwise: */
+
+ tux_xm = tux_xm / 2;
+ }
+ }
+
+
+ /* Drop vertically: */
+
+ if (!issolid(tux_x, tux_y + 32, scroll_x))
+ {
+ tux_ym = tux_ym + GRAVITY;
+
+ if (tux_ym > MAX_YM)
+ tux_ym = MAX_YM;
+ }
+ }
+
+
+ if (tux_safe > 0)
+ tux_safe--;
+
+
+ /* ---- DONE HANDLING TUX! --- */
+
+
+ /* Handle bouncy distros: */
+
+ for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
+ {
+ if (bouncy_distros[i].alive)
+ {
+ bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
+
+ bouncy_distros[i].ym++;
+
+ if (bouncy_distros[i].ym >= 0)
+ bouncy_distros[i].alive = NO;
+ }
+ }
+
+
+ /* Handle broken bricks: */
+
+ for (i = 0; i < NUM_BROKEN_BRICKS; i++)
+ {
+ if (broken_bricks[i].alive)
+ {
+ broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
+ broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
+
+ broken_bricks[i].ym++;
+
+ if (broken_bricks[i].ym >= 0)
+ broken_bricks[i].alive = NO;
+ }
+ }
+
+
+ /* Handle distro counting: */
+
+ if (counting_distros == YES)
+ {
+ distro_counter--;
+
+ if (distro_counter <= 0)
+ counting_distros = -1;
+ }
+
+
+ /* Handle bouncy bricks: */
+
+ for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
+ {
+ if (bouncy_bricks[i].alive)
+ {
+ bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
+ bouncy_bricks[i].offset_m);
+
+ /* Go back down? */
+
+ if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
+ bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
+
+
+ /* Stop bouncing? */
+
+ if (bouncy_bricks[i].offset == 0)
+ bouncy_bricks[i].alive = NO;
+ }
+ }
+
+
+ /* Handle floating scores: */
+
+ for (i = 0; i < NUM_FLOATING_SCORES; i++)
+ {
+ if (floating_scores[i].alive)
+ {
+ floating_scores[i].y = floating_scores[i].y - 2;
+ floating_scores[i].timer--;
+
+ if (floating_scores[i].timer <= 0)
+ floating_scores[i].alive = NO;
+ }
+ }
+
+
+ /* Handle bullets: */
+
+ for (i = 0; i < NUM_BULLETS; i++)
+ {
+ if (bullets[i].alive)
+ {
+ bullets[i].x = bullets[i].x + bullets[i].xm;
+ bullets[i].y = bullets[i].y + bullets[i].ym;
+
+ if (issolid(bullets[i].x, bullets[i].y, 0))
+ {
+ if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
+ bullets[i].alive = NO;
+ else
+ {
+ if (bullets[i].ym >= 0)
+ {
+ bullets[i].y = (bullets[i].y / 32) * 32 - 8;
+ }
+ bullets[i].ym = -bullets[i].ym;
+ }
+ }
+
+ bullets[i].ym = bullets[i].ym + GRAVITY;
+
+ if (bullets[i].x < scroll_x ||
+ bullets[i].x > scroll_x + 640)
+ {
+ bullets[i].alive = NO;
+ }
+ }
+
+
+ if (bullets[i].alive)
+ {
+ for (j = 0; j < NUM_BAD_GUYS; j++)
+ {
+ if (bad_guys[j].alive && !bad_guys[j].dying)
+ {
+ if (bullets[i].x >= bad_guys[j].x - 4 &&
+ bullets[i].x <= bad_guys[j].x + 32 + 4 &&
+ bullets[i].y >= bad_guys[j].y - 4 &&
+ bullets[i].y <= bad_guys[j].y + 32 + 4)
+ {
+ /* Kill the bad guy! */
+
+ bullets[i].alive = 0;
+ bad_guys[j].dying = FALLING;
+ bad_guys[j].ym = -8;
+
+
+ /* Gain some points: */
+
+ if (bad_guys[j].kind == BAD_BSOD)
+ {
+ add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
+ 50 * score_multiplier);
+ }
+ else if (bad_guys[j].kind == BAD_LAPTOP)
+ {
+ add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
+ 25 * score_multiplier);
+ }
+
+
+ /* Play death sound: */
+ play_sound(sounds[SND_FALL]);
+ }
+ }
+ }
+ }
+ }
+
+
+ /* Handle background timer: */
+
+ if (super_bkgd_time)
+ super_bkgd_time--;
+
+
+ /* Handle invincibility timer: */
+
+
+ if (tux_invincible_time > 50)
+ {
+ tux_invincible_time--;
+
+
+ if (!playing_music())
+ play_music( herring_song, 1 );
+ }
+ else
+ {
+ if (current_music == HERRING_MUSIC)
+ {
+ /* stop the herring_song, now play the level_song ! */
+ current_music = LEVEL_MUSIC;
+ halt_music();
+ }
+
+ if (!playing_music())
+ {
+ if (time_left <= TIME_WARNING)
+ play_music( level_song_fast, 1 );
+ else
+ play_music( level_song, 1 );
+ }
+
+ if (tux_invincible_time > 0)
+ tux_invincible_time--;
+ }
+
+
+ /* Handle upgrades: */
+
+ for (i = 0; i < NUM_UPGRADES; i++)
+ {
+ if (upgrades[i].alive)
+ {
+ if (upgrades[i].height < 32)
+ {
+ /* Rise up! */
+
+ upgrades[i].height++;
+ }
+ else
+ {
+ /* Move around? */
+
+ if (upgrades[i].kind == UPGRADE_MINTS ||
+ upgrades[i].kind == UPGRADE_HERRING)
+ {
+ upgrades[i].x = upgrades[i].x + upgrades[i].xm;
+ upgrades[i].y = upgrades[i].y + upgrades[i].ym;
+
+ if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
+ issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
+ {
+ if (upgrades[i].ym > 0)
+ {
+ if (upgrades[i].kind == UPGRADE_MINTS)
+ {
+ upgrades[i].ym = 0;
+ }
+ else if (upgrades[i].kind == UPGRADE_HERRING)
+ {
+ upgrades[i].ym = -24;
+ }
+
+ upgrades[i].y = (upgrades[i].y / 32) * 32;
+ }
+ }
+ else
+ upgrades[i].ym = upgrades[i].ym + GRAVITY;
+
+ if (issolid(upgrades[i].x, upgrades[i].y, 0))
+ {
+ upgrades[i].xm = -upgrades[i].xm;
+ }
+ }
+
+
+ /* Off the screen? Kill it! */
+
+ if (upgrades[i].x < scroll_x)
+ upgrades[i].alive = NO;
+
+
+ /* Did the player grab it? */
+
+ if (tux_x + scroll_x >= upgrades[i].x - 32 &&
+ tux_x + scroll_x <= upgrades[i].x + 32 &&
+ tux_y >= upgrades[i].y - 32 &&
+ tux_y <= upgrades[i].y + 32)
+ {
+ /* Remove the upgrade: */
+
+ upgrades[i].alive = NO;
+
+
+ /* Affect the player: */
+
+ if (upgrades[i].kind == UPGRADE_MINTS)
+ {
+ play_sound(sounds[SND_EXCELLENT]);
+ tux_size = BIG;
+ super_bkgd_time = 8;
+ }
+ else if (upgrades[i].kind == UPGRADE_COFFEE)
+ {
+ play_sound(sounds[SND_COFFEE]);
+ tux_got_coffee = YES;
+ super_bkgd_time = 4;
+ }
+ else if (upgrades[i].kind == UPGRADE_HERRING)
+ {
+ play_sound(sounds[SND_HERRING]);
+ tux_invincible_time = TUX_INVINCIBLE_TIME;
+ super_bkgd_time = 4;
+ /* play the herring song ^^ */
+ current_music = HERRING_MUSIC;
+ if (playing_music())
+ halt_music();
+ play_music( herring_song, 1 );
+ }
+ }
+ }
+ }
+ }
+
+
+ /* Handle bad guys: */
+
+ for (i = 0; i < NUM_BAD_GUYS; i++)
+ {
+ if (bad_guys[i].alive)
+ {
+ if (bad_guys[i].seen)
+ {
+ if (bad_guys[i].kind == BAD_BSOD)
+ {
+ /* --- BLUE SCREEN OF DEATH MONSTER: --- */
+
+ /* Move left/right: */
+
+ if (bad_guys[i].dying == NO ||
+ bad_guys[i].dying == FALLING)
+ {
+ if (bad_guys[i].dir == RIGHT)
+ bad_guys[i].x = bad_guys[i].x + 4;
+ else if (bad_guys[i].dir == LEFT)
+ bad_guys[i].x = bad_guys[i].x - 4;
+ }
+
+
+ /* Move vertically: */
+
+ bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
+
+
+ /* Bump into things horizontally: */
+
+ if (!bad_guys[i].dying)
+ {
+ if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
+ bad_guys[i].dir = !bad_guys[i].dir;
+ }
+
+
+ /* Bump into other bad guys: */
+
+ for (j = 0; j < NUM_BAD_GUYS; j++)
+ {
+ if (j != i && bad_guys[j].alive &&
+ !bad_guys[j].dying && !bad_guys[i].dying &&
+ bad_guys[i].x >= bad_guys[j].x - 32 &&
+ bad_guys[i].x <= bad_guys[j].x + 32 &&
+ bad_guys[i].y >= bad_guys[j].y - 32 &&
+ bad_guys[i].y <= bad_guys[j].y + 32)
+ {
+ bad_guys[i].dir = !bad_guys[i].dir;
+ }
+ }
+
+
+ /* Fall if we get off the ground: */
+
+ if (bad_guys[i].dying != FALLING)
+ {
+ if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
+ bad_guys[i].ym < MAX_YM)
+ {
+ bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
+ }
+ else
+ {
+ /* Land: */
+
+ if (bad_guys[i].ym > 0)
+ {
+ bad_guys[i].y = (bad_guys[i].y / 32) * 32;
+ bad_guys[i].ym = 0;
+ }
+ }
+ }
+ else
+ bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
+
+ if (bad_guys[i].y > 480)
+ bad_guys[i].alive = NO;
+ }
+ else if (bad_guys[i].kind == BAD_LAPTOP)
+ {
+ /* --- LAPTOP MONSTER: --- */
+
+ /* Move left/right: */
+
+ if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
+ {
+ if (bad_guys[i].dying == NO ||
+ bad_guys[i].dying == FALLING)
+ {
+ if (bad_guys[i].dir == RIGHT)
+ bad_guys[i].x = bad_guys[i].x + 4;
+ else if (bad_guys[i].dir == LEFT)
+ bad_guys[i].x = bad_guys[i].x - 4;
+ }
+ }
+ else if (bad_guys[i].mode == KICK)
+ {
+ if (bad_guys[i].dir == RIGHT)
+ bad_guys[i].x = bad_guys[i].x + 16;
+ else if (bad_guys[i].dir == LEFT)
+ bad_guys[i].x = bad_guys[i].x - 16;
+ }
+
+
+ /* Move vertically: */
+
+ bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
+
+
+ /* Bump into things horizontally: */
+
+ if (!bad_guys[i].dying)
+ {
+ if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
+ {
+ bad_guys[i].dir = !bad_guys[i].dir;
+
+ if (bad_guys[i].mode == KICK)
+ play_sound(sounds[SND_RICOCHET]);
+ }
+ }
+
+
+ /* Bump into other bad guys: */
+
+ for (j = 0; j < NUM_BAD_GUYS; j++)
+ {
+ if (j != i && bad_guys[j].alive &&
+ !bad_guys[j].dying && !bad_guys[i].dying &&
+ bad_guys[i].x >= bad_guys[j].x - 32 &&
+ bad_guys[i].x <= bad_guys[j].x + 32 &&
+ bad_guys[i].y >= bad_guys[j].y - 32 &&
+ bad_guys[i].y <= bad_guys[j].y + 32)
+ {
+ if (bad_guys[i].mode != KICK)
+ bad_guys[i].dir = !bad_guys[i].dir;
+ else
+ {
+ /* We're in kick mode, kill the other guy: */
+
+ bad_guys[j].dying = FALLING;
+ bad_guys[j].ym = -8;
+ play_sound(sounds[SND_FALL]);
+
+ add_score(bad_guys[i].x - scroll_x,
+ bad_guys[i].y, 100);
+ }
+ }
+ }
+
+
+ /* Fall if we get off the ground: */
+
+ if (bad_guys[i].dying != FALLING)
+ {
+ if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
+ bad_guys[i].ym < MAX_YM)
+ {
+ bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
+ }
+ else
+ {
+ /* Land: */
+
+ if (bad_guys[i].ym > 0)
+ {
+ bad_guys[i].y = (bad_guys[i].y / 32) * 32;
+ bad_guys[i].ym = 0;
+ }
+ }
+ }
+ else
+ bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
+
+ if (bad_guys[i].y > 480)
+ bad_guys[i].alive = NO;
+ }
+ else if (bad_guys[i].kind == BAD_MONEY)
+ {
+ /* --- MONEY BAGS: --- */
+
+
+ /* Move vertically: */
+
+ bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
+
+
+ /* Fall if we get off the ground: */
+
+ if (bad_guys[i].dying != FALLING)
+ {
+ if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
+ {
+ if (bad_guys[i].ym < MAX_YM)
+ {
+ bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
+ }
+ }
+ else
+ {
+ /* Land: */
+
+ if (bad_guys[i].ym > 0)
+ {
+ bad_guys[i].y = (bad_guys[i].y / 32) * 32;
+ bad_guys[i].ym = -MAX_YM;
+ }
+ }
+ }
+ else
+ bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
+
+ if (bad_guys[i].y > 480)
+ bad_guys[i].alive = NO;
+ }
+ else if (bad_guys[i].kind == -1)
+ {}
+
+
+ /* Kill it if the player jumped on it: */
+
+ if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
+ tux_x + scroll_x >= bad_guys[i].x - 32 &&
+ tux_x + scroll_x <= bad_guys[i].x + 32 &&
+ tux_y >= bad_guys[i].y - 32 &&
+ tux_y <= bad_guys[i].y - 8
+ /* &&
+ tux_ym >= 0 */)
+ {
+ if (bad_guys[i].kind == BAD_BSOD)
+ {
+ bad_guys[i].dying = SQUISHED;
+ bad_guys[i].timer = 16;
+ tux_ym = -KILL_BOUNCE_YM;
+
+ add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
+ 50 * score_multiplier);
+
+ play_sound(sounds[SND_SQUISH]);
+ }
+ else if (bad_guys[i].kind == BAD_LAPTOP)
+ {
+ if (bad_guys[i].mode != FLAT)
+ {
+ /* Flatten! */
+
+ bad_guys[i].mode = FLAT;
+
+ bad_guys[i].timer = 64;
+
+ tux_y = tux_y - 32;
+ }
+ else
+ {
+ /* Kick! */
+
+ bad_guys[i].mode = KICK;
+
+ if (tux_x + scroll_x <= bad_guys[i].x)
+ bad_guys[i].dir = RIGHT;
+ else
+ bad_guys[i].dir = LEFT;
+
+ bad_guys[i].timer = 8;
+ }
+
+ tux_ym = -KILL_BOUNCE_YM;
+
+ add_score(bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ 25 * score_multiplier);
+
+ /* play_sound(sounds[SND_SQUISH]); */
+ }
+ else if (bad_guys[i].kind == -1)
+ {}
+
+ score_multiplier++;
+ }
+
+
+ /* Hurt the player if he just touched it: */
+
+ if (!bad_guys[i].dying && !tux_dying &&
+ !tux_safe &&
+ tux_x + scroll_x >= bad_guys[i].x - 32 &&
+ tux_x + scroll_x <= bad_guys[i].x + 32 &&
+ tux_y >= bad_guys[i].y - 32 &&
+ tux_y <= bad_guys[i].y + 32)
+ {
+ if (bad_guys[i].mode == FLAT)
+ {
+ /* Kick: */
+
+ bad_guys[i].mode = KICK;
+
+ if (tux_x + scroll_x <= bad_guys[i].x)
+ {
+ bad_guys[i].dir = RIGHT;
+ bad_guys[i].x = bad_guys[i].x + 16;
+ }
+ else
+ {
+ bad_guys[i].dir = LEFT;
+ bad_guys[i].x = bad_guys[i].x - 16;
+ }
+
+ bad_guys[i].timer = 8;
+ }
+ else if (bad_guys[i].mode == KICK)
+ {
+ if (tux_y < bad_guys[i].y - 16 &&
+ bad_guys[i].timer == 0)
+ {
+ /* Step on (stop being kicked) */
+
+ bad_guys[i].mode = FLAT;
+ bad_guys[i].timer = 64;
+ }
+ else
+ {
+ /* Hurt if you get hit by kicked laptop: */
+
+ if (bad_guys[i].timer == 0)
+ {
+ if (tux_invincible_time == 0)
+ {
+ killtux(SHRINK);
+ }
+ else
+ {
+ bad_guys[i].dying = FALLING;
+ bad_guys[i].ym = -8;
+ play_sound(sounds[SND_FALL]);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (tux_invincible_time == 0)
+ {
+ killtux(SHRINK);
+ }
+ else
+ {
+ bad_guys[i].dying = FALLING;
+ bad_guys[i].ym = -8;
+ play_sound(sounds[SND_FALL]);
+ }
+ }
+ }
+
+
+ /* Handle mode timer: */
+
+ if (bad_guys[i].mode == FLAT)
+ {
+ bad_guys[i].timer--;
+
+ if (bad_guys[i].timer <= 0)
+ bad_guys[i].mode = NORMAL;
+ }
+ else if (bad_guys[i].mode == KICK)
+ {
+ if (bad_guys[i].timer > 0)
+ bad_guys[i].timer--;
+ }
+
+
+ /* Handle dying timer: */
+
+ if (bad_guys[i].dying == SQUISHED)
+ {
+ bad_guys[i].timer--;
+
+
+ /* Remove it if time's up: */
+
+ if (bad_guys[i].timer <= 0)
+ bad_guys[i].alive = NO;
+ }
+
+
+ /* Remove if it's far off the screen: */
+
+ if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
+ bad_guys[i].alive = NO;
+ }
+ else /* !seen */
+ {
+ /* Once it's on screen, it's activated! */
+
+ if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
+ bad_guys[i].seen = YES;
+ }
+ }
+ }
+
+
+ /* Handle skidding: */
+
+ if (tux_skidding > 0)
+ {
+ tux_skidding--;
+ }
+
+ return -1;
+}
+
+/* --- GAME DRAW! --- */
+
+void game_draw()
+{
+ int x, y, i;
+
+ /* Draw screen: */
+
+ if (tux_dying && (frame % 4) == 0)
+ clearscreen(255, 255, 255);
+ else
+ {
+ if (super_bkgd_time == 0)
+ clearscreen(bkgd_red, bkgd_green, bkgd_blue);
+ else
+ drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
+ }
+
+
+ /* Draw background: */
+
+ for (y = 0; y < 15; y++)
+ {
+ for (x = 0; x < 21; x++)
+ {
+ drawshape(x * 32 - (scroll_x % 32), y * 32,
+ tiles[y][x + (scroll_x / 32)]);
+ }
+ }
+
+
+ /* (Bouncy bricks): */
+
+ for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
+ {
+ if (bouncy_bricks[i].alive)
+ {
+ if (bouncy_bricks[i].x >= scroll_x - 32 &&
+ bouncy_bricks[i].x <= scroll_x + 640)
+ {
+ dest.x = bouncy_bricks[i].x - scroll_x;
+ dest.y = bouncy_bricks[i].y;
+ dest.w = 32;
+ dest.h = 32;
+
+ SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
+ bkgd_red,
+ bkgd_green,
+ bkgd_blue));
+
+ drawshape(bouncy_bricks[i].x - scroll_x,
+ bouncy_bricks[i].y + bouncy_bricks[i].offset,
+ bouncy_bricks[i].shape);
+ }
+ }
+ }
+
+
+ /* (Bad guys): */
+
+ for (i = 0; i < NUM_BAD_GUYS; i++)
+ {
+ if (bad_guys[i].alive &&
+ bad_guys[i].x > scroll_x - 32 &&
+ bad_guys[i].x < scroll_x + 640)
+ {
+ if (bad_guys[i].kind == BAD_BSOD)
+ {
+ /* --- BLUE SCREEN OF DEATH MONSTER: --- */
+
+ if (bad_guys[i].dying == NO)
+ {
+ /* Alive: */
+
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_bsod_left[(frame / 5) % 4],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_bsod_right[(frame / 5) % 4],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ }
+ else if (bad_guys[i].dying == FALLING)
+ {
+ /* Falling: */
+
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_bsod_falling_left,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_bsod_falling_right,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ }
+ else if (bad_guys[i].dying == SQUISHED)
+ {
+ /* Dying - Squished: */
+
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_bsod_squished_left,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y + 24,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_bsod_squished_right,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y + 24,
+ NO_UPDATE);
+ }
+ }
+ }
+ else if (bad_guys[i].kind == BAD_LAPTOP)
+ {
+ /* --- LAPTOP MONSTER: --- */
+
+ if (bad_guys[i].dying == NO)
+ {
+ /* Alive: */
+
+ if (bad_guys[i].mode == NORMAL)
+ {
+ /* Not flat: */
+
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_laptop_left[(frame / 5) % 3],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_laptop_right[(frame / 5) % 3],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ }
+ else
+ {
+ /* Flat: */
+
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_laptop_flat_left,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_laptop_flat_right,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ }
+ }
+ else if (bad_guys[i].dying == FALLING)
+ {
+ /* Falling: */
+
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_laptop_falling_left,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_laptop_falling_right,
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ }
+ }
+ else if (bad_guys[i].kind == BAD_MONEY)
+ {
+ if (bad_guys[i].ym > -16)
+ {
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_money_left[0],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_money_right[0],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ }
+ else
+ {
+ if (bad_guys[i].dir == LEFT)
+ {
+ drawimage(img_money_left[1],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(img_money_right[1],
+ bad_guys[i].x - scroll_x,
+ bad_guys[i].y,
+ NO_UPDATE);
+ }
+ }
+ }
+ else if (bad_guys[i].kind == -1)
+ {}
+ }
+ }
+
+
+ /* (Tux): */
+
+ if (right == UP && left == UP)
+ {
+ tux_frame_main = 1;
+ tux_frame = 1;
+ }
+ else
+ {
+ if ((fire == DOWN && (frame % 2) == 0) ||
+ (frame % 4) == 0)
+ tux_frame_main = (tux_frame_main + 1) % 4;
+
+ tux_frame = tux_frame_main;
+
+ if (tux_frame == 3)
+ tux_frame = 1;
+ }
+
+
+ if (tux_got_coffee && (frame % 2) == 1)
+ {
+ /* Coffee glow: */
+
+ drawimage(img_red_glow, tux_x - 8, tux_y - 32, NO_UPDATE);
+ }
+
+
+ if (tux_safe == 0 || (frame % 2) == 0)
+ {
+ if (tux_size == SMALL)
+ {
+ if (tux_invincible_time)
+ {
+ /* Draw cape: */
+
+ if (tux_dir == RIGHT)
+ {
+ drawimage(cape_right[frame % 2],
+ tux_x, tux_y,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(cape_left[frame % 2],
+ tux_x, tux_y,
+ NO_UPDATE);
+ }
+ }
+
+
+ if (tux_dir == RIGHT)
+ {
+ drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
+ }
+ else
+ {
+ drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
+ }
+ }
+ else
+ {
+ if (tux_invincible_time)
+ {
+ /* Draw cape: */
+
+ if (tux_dir == RIGHT)
+ {
+ drawimage(bigcape_right[frame % 2],
+ tux_x - 8 - 16, tux_y - 32,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(bigcape_left[frame % 2],
+ tux_x - 8, tux_y - 32,
+ NO_UPDATE);
+ }
+ }
+
+ if (!tux_duck)
+ {
+ if (!tux_skidding)
+ {
+ if (!jumping || tux_ym > 0)
+ {
+ if (tux_dir == RIGHT)
+ {
+ drawimage(bigtux_right[tux_frame],
+ tux_x - 8, tux_y - 32,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(bigtux_left[tux_frame],
+ tux_x - 8, tux_y - 32,
+ NO_UPDATE);
+ }
+ }
+ else
+ {
+ if (tux_dir == RIGHT)
+ {
+ drawimage(bigtux_right_jump,
+ tux_x - 8, tux_y - 32,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(bigtux_left_jump,
+ tux_x - 8, tux_y - 32,
+ NO_UPDATE);
+ }
+ }
+ }
+ else
+ {
+ if (tux_dir == RIGHT)
+ {
+ drawimage(skidtux_right,
+ tux_x - 8, tux_y - 32,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(skidtux_left,
+ tux_x - 8, tux_y - 32,
+ NO_UPDATE);
+ }
+ }
+ }
+ else
+ {
+ if (tux_dir == RIGHT)
+ {
+ drawimage(ducktux_right, tux_x - 8, tux_y - 16,
+ NO_UPDATE);
+ }
+ else
+ {
+ drawimage(ducktux_left, tux_x - 8, tux_y - 16,
+ NO_UPDATE);
+ }
+ }
+ }
+ }
+
+
+ /* (Bullets): */
+
+ for (i = 0; i < NUM_BULLETS; i++)
+ {
+ if (bullets[i].alive &&
+ bullets[i].x >= scroll_x - 4 &&
+ bullets[i].x <= scroll_x + 640)
+ {
+ drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
+ NO_UPDATE);
+ }
+ }
+
+
+ /* (Floating scores): */
+
+ for (i = 0; i < NUM_FLOATING_SCORES; i++)
+ {
+ if (floating_scores[i].alive)
+ {
+ sprintf(str, "%d", floating_scores[i].value);
+ drawtext(str,
+ floating_scores[i].x + 16 - strlen(str) * 8,
+ floating_scores[i].y,
+ letters_gold, NO_UPDATE);
+ }
+ }
+
+
+ /* (Upgrades): */
+
+ for (i = 0; i < NUM_UPGRADES; i++)
+ {
+ if (upgrades[i].alive)
+ {
+ if (upgrades[i].height < 32)
+ {
+ /* Rising up... */
+
+ dest.x = upgrades[i].x - scroll_x;
+ dest.y = upgrades[i].y + 32 - upgrades[i].height;
+ dest.w = 32;
+ dest.h = upgrades[i].height;
+
+ src.x = 0;
+ src.y = 0;
+ src.w = 32;
+ src.h = upgrades[i].height;
+
+ if (upgrades[i].kind == UPGRADE_MINTS)
+ SDL_BlitSurface(img_mints, &src, screen, &dest);
+ else if (upgrades[i].kind == UPGRADE_COFFEE)
+ SDL_BlitSurface(img_coffee, &src, screen, &dest);
+ else if (upgrades[i].kind == UPGRADE_HERRING)
+ SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
+ }
+ else
+ {
+ if (upgrades[i].kind == UPGRADE_MINTS)
+ {
+ drawimage(img_mints,
+ upgrades[i].x - scroll_x, upgrades[i].y,
+ NO_UPDATE);
+ }
+ else if (upgrades[i].kind == UPGRADE_COFFEE)
+ {
+ drawimage(img_coffee,
+ upgrades[i].x - scroll_x, upgrades[i].y,
+ NO_UPDATE);
+ }
+ else if (upgrades[i].kind == UPGRADE_HERRING)
+ {
+ drawimage(img_golden_herring,
+ upgrades[i].x - scroll_x, upgrades[i].y,
+ NO_UPDATE);
+ }
+ }
+ }
+ }
+
+
+ /* (Bouncy distros): */
+
+ for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
+ {
+ if (bouncy_distros[i].alive)
+ {
+ drawimage(img_distro[0],
+ bouncy_distros[i].x - scroll_x,
+ bouncy_distros[i].y,
+ NO_UPDATE);
+ }
+ }
+
+
+ /* (Broken bricks): */
+
+ for (i = 0; i < NUM_BROKEN_BRICKS; i++)
+ {
+ if (broken_bricks[i].alive)
+ {
+ src.x = rand() % 16;
+ src.y = rand() % 16;
+ src.w = 16;
+ src.h = 16;
+
+ dest.x = broken_bricks[i].x - scroll_x;
+ dest.y = broken_bricks[i].y;
+ dest.w = 16;
+ dest.h = 16;
+
+ SDL_BlitSurface(img_brick[0], &src, screen, &dest);
+ }
+ }
+
+
+ /* (Status): */
+
+ sprintf(str, "%d", score);
+ drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE);
+ drawtext(str, 96, 0, letters_gold, NO_UPDATE);
+
+ sprintf(str, "%d", highscore);
+ drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE);
+ drawtext(str, 96, 20, letters_gold, NO_UPDATE);
+
+ if (time_left >= TIME_WARNING || (frame % 10) < 5)
+ {
+ sprintf(str, "%d", time_left);
+ drawtext("TIME", 224, 0, letters_blue, NO_UPDATE);
+ drawtext(str, 304, 0, letters_gold, NO_UPDATE);
+ }
+
+ sprintf(str, "%d", distros);
+ drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE);
+ drawtext(str, 608, 0, letters_gold, NO_UPDATE);
+
+ drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE);
+
+ for(i=0; i < lives; ++i)
+ {
+ drawimage(tux_life,565+(18*i),20,NO_UPDATE);
+ }
+
+ if(game_pause)
+ drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE);
+
+ if(show_menu)
+ done = drawmenu();
+
+ /* (Update it all!) */
+
+ updatescreen();
+
+
+}
+
+/* --- GAME LOOP! --- */
+
+int gameloop(void)
+{
+
+ Uint32 last_time, now_time;
+
+ /* Clear screen: */
+
+ clearscreen(0, 0, 0);
+ updatescreen();
+
+
+ /* Init the game: */
+
+ initmenu();
+ initgame();
+ loadshared();
+ loadlevel();
+ loadlevelgfx();
+ loadlevelsong();
+ highscore = load_hs();
+
+
+ /* --- MAIN GAME LOOP!!! --- */