void FlipLevelTransformer::transform_badguy(float height, BadGuy& badguy) { Vector pos = badguy.get_start_position(); pos.y = height - pos.y; badguy.set_start_position(pos); }
HitResponse Block::collision(GameObject& other, const CollisionHit& ) { Player* player = dynamic_cast<Player*> (&other); if(player) { if(player->get_bbox().get_top() > get_bbox().get_bottom() - 7.0) { hit(*player); } } // only interact with other objects if... // 1) we are bouncing // and // 2) the object is not portable (either never or not currently) Portable* portable = dynamic_cast<Portable*> (&other); if(bouncing && (portable == 0 || (!portable->is_portable()))) { // Badguys get killed BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { badguy->kill_fall(); } // Coins get collected Coin* coin = dynamic_cast<Coin*> (&other); if(coin) { coin->collect(); } } return SOLID; }
HitResponse BonusBlock::collision(GameObject& other, const CollisionHit& hit_){ Player* player = dynamic_cast<Player*> (&other); if (player) { if (player->does_buttjump) try_drop(player); } BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { // hit contains no information for collisions with blocks. // Badguy's bottom has to be below the top of the block // SHIFT_DELTA is required to slide over one tile gaps. if( badguy->can_break() && ( badguy->get_bbox().get_bottom() > bbox.get_top() + SHIFT_DELTA ) ){ try_open(player); } } Portable* portable = dynamic_cast<Portable*> (&other); if(portable) { MovingObject* moving = dynamic_cast<MovingObject*> (&other); if(moving->get_bbox().get_top() > bbox.get_bottom() - SHIFT_DELTA) { try_open(player); } } return Block::collision(other, hit_); }
HitResponse Brick::collision(GameObject& other, const CollisionHit& hit_){ Player* player = dynamic_cast<Player*> (&other); if (player) { if (player->does_buttjump) try_break(player); if (player->is_stone() && player->get_velocity().y >= 280) try_break(player); // stoneform breaks through bricks } BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { // hit contains no information for collisions with blocks. // Badguy's bottom has to be below the top of the brick // SHIFT_DELTA is required to slide over one tile gaps. if( badguy->can_break() && ( badguy->get_bbox().get_bottom() > bbox.get_top() + SHIFT_DELTA ) ){ try_break(player); } } Portable* portable = dynamic_cast<Portable*> (&other); if(portable) { MovingObject* moving = dynamic_cast<MovingObject*> (&other); if(moving->get_bbox().get_top() > bbox.get_bottom() - SHIFT_DELTA) { try_break(player); } } Explosion* explosion = dynamic_cast<Explosion*> (&other); if(explosion && explosion->hurts()) { try_break(player); } IceCrusher* icecrusher = dynamic_cast<IceCrusher*> (&other); if(icecrusher && coin_counter == 0) try_break(player); return Block::collision(other, hit_); }
bool MrIceBlock::collision_squished(GameObject& object) { Player* player = dynamic_cast<Player*>(&object); if(player && (player->does_buttjump || player->is_invincible())) { player->bounce(*this); kill_fall(); return true; } switch(ice_state) { case ICESTATE_KICKED: { BadGuy* badguy = dynamic_cast<BadGuy*>(&object); if (badguy) { badguy->kill_fall(); break; } } // fall through case ICESTATE_NORMAL: { squishcount++; if (squishcount >= MAXSQUISHES) { kill_fall(); return true; } } set_state(ICESTATE_FLAT); nokick_timer.start(NOKICK_TIME); break; case ICESTATE_FLAT: { MovingObject* movingobject = dynamic_cast<MovingObject*>(&object); if (movingobject && (movingobject->get_pos().x < get_pos().x)) { dir = RIGHT; } else { dir = LEFT; } } if (nokick_timer.check()) set_state(ICESTATE_KICKED); break; case ICESTATE_GRABBED: assert(false); break; } if (player) player->bounce(*this); return true; }
HitResponse Brick::collision(GameObject& other, const CollisionHit& hit){ BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { // hit contains no information for collisions with blocks. // Badguy's bottom has to be below the top of the brick // +7 is required to slide over one tile gaps. if( badguy->can_break() && ( badguy->get_bbox().get_bottom() > get_bbox().get_top() + 7.0 ) ){ try_break(false); } } return Block::collision(other, hit); }
HitResponse HurtingPlatform::collision(GameObject& other, const CollisionHit& ) { Player* player = dynamic_cast<Player*>(&other); if (player) { player->kill(false); } BadGuy* badguy = dynamic_cast<BadGuy*>(&other); if (badguy) { badguy->kill_fall(); } return FORCE_MOVE; }
HitResponse BadGuy::collision(GameObject& other, const CollisionHit& hit) { if (!is_active()) return ABORT_MOVE; BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy && badguy->is_active() && badguy->get_group() == COLGROUP_MOVING) { /* Badguys don't let badguys squish other badguys. It's bad. */ #if 0 // hit from above? if (badguy->get_bbox().p2.y < (bbox.p1.y + 16)) { if(collision_squished(*badguy)) { return ABORT_MOVE; } } #endif return collision_badguy(*badguy, hit); } Player* player = dynamic_cast<Player*> (&other); if(player) { // hit from above? if (player->get_bbox().p2.y < (bbox.p1.y + 16)) { if(player->is_stone()) { kill_fall(); return FORCE_MOVE; } if(collision_squished(*player)) { return FORCE_MOVE; } } if(player->is_stone()) { collision_solid(hit); return FORCE_MOVE; } return collision_player(*player, hit); } Bullet* bullet = dynamic_cast<Bullet*> (&other); if(bullet) return collision_bullet(*bullet, hit); return FORCE_MOVE; }
HitResponse Kugelblitz::collision_badguy(BadGuy& other , const CollisionHit& chit) { //Let the Kugelblitz explode, too? The problem with that is that //two Kugelblitzes would cancel each other out on contact... other.kill_fall(); return hit(chit); }
HitResponse Stalactite::collision_badguy(BadGuy& other, const CollisionHit& hit) { if (state == STALACTITE_SQUISHED) return FORCE_MOVE; // ignore other Stalactites if (dynamic_cast<Stalactite*>(&other)) return FORCE_MOVE; if (state != STALACTITE_FALLING) return BadGuy::collision_badguy(other, hit); if (other.is_freezable()) { other.freeze(); } else { other.kill_fall(); } return FORCE_MOVE; }
HitResponse Explosion::collision(GameObject& other, const CollisionHit& ) { if ((state != STATE_EXPLODING) || !hurt) return ABORT_MOVE; Player* player = dynamic_cast<Player*>(&other); if(player != 0) { player->kill(false); } BadGuy* badguy = dynamic_cast<BadGuy*>(&other); if(badguy != 0) { badguy->kill_fall(); } return ABORT_MOVE; }
HitResponse AngryStone::collision_badguy(BadGuy& badguy, const CollisionHit& ) { if (state == ATTACKING) { badguy.kill_fall(); return FORCE_MOVE; } return FORCE_MOVE; }
HitResponse Block::collision(GameObject& other, const CollisionHit& ) { Player* player = dynamic_cast<Player*> (&other); if(player) { if(player->get_bbox().get_top() > get_bbox().get_bottom() - SHIFT_DELTA) { hit(*player); } } // only interact with other objects if... // 1) we are bouncing // 2) the object is not portable (either never or not currently) // 3) the object is being hit from below (baguys don't get killed for activating boxes) Portable* portable = dynamic_cast<Portable*> (&other); MovingObject* moving_object = dynamic_cast<MovingObject*> (&other); bool is_portable = ((portable != 0) && portable->is_portable()); bool hit_mo_from_below = ((moving_object == 0) || (moving_object->get_bbox().get_bottom() < (get_bbox().get_top() + SHIFT_DELTA))); if(bouncing && !is_portable && hit_mo_from_below) { // Badguys get killed BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { badguy->kill_fall(); } // Coins get collected Coin* coin = dynamic_cast<Coin*> (&other); if(coin) { coin->collect(); } //Eggs get jumped GrowUp* growup = dynamic_cast<GrowUp*> (&other); if(growup) { growup->do_jump(); } } return FORCE_MOVE; }
HitResponse BonusBlock::collision(GameObject& other, const CollisionHit& hit){ BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { // hit contains no information for collisions with blocks. // Badguy's bottom has to be below the top of the bonusblock // +7 is required to slide over one tile gaps. if( badguy->can_break() && ( badguy->get_bbox().get_bottom() > get_bbox().get_top() + 7.0) ){ try_open(); } } Portable* portable = dynamic_cast<Portable*> (&other); if(portable) { MovingObject* moving = dynamic_cast<MovingObject*> (&other); if(moving->get_bbox().get_top() > get_bbox().get_bottom() - 7.0) { try_open(); } } return Block::collision(other, hit); }
HitResponse MoleRock::collision_badguy(BadGuy& badguy, const CollisionHit& ) { // ignore collisions with parent if (&badguy == parent) { return FORCE_MOVE; } SoundManager::current()->play("sounds/stomp.wav", get_pos()); remove_me(); badguy.kill_fall(); return ABORT_MOVE; }
HitResponse Block::collision(GameObject& other, const CollisionHit& ) { Player* player = dynamic_cast<Player*> (&other); if(player) { if(player->get_bbox().get_top() > get_bbox().get_bottom() - 7.0) { hit(*player); } } if(bouncing) { BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { badguy->kill_fall(); } Coin* coin = dynamic_cast<Coin*> (&other); if(coin) { coin->collect(); } } return SOLID; }
HitResponse IceCrusher::collision(GameObject& other, const CollisionHit& hit) { Player* player = dynamic_cast<Player*>(&other); /* If the other object is the player, and the collision is at the bottom of * the ice crusher, hurt the player. */ if (player && hit.bottom) { SoundManager::current()->play("sounds/brick.wav"); if (state == CRUSHING) set_state(RECOVERING); if(player->is_invincible()) { return ABORT_MOVE; } player->kill(false); return FORCE_MOVE; } BadGuy* badguy = dynamic_cast<BadGuy*>(&other); if (badguy) { badguy->kill_fall(); } return FORCE_MOVE; }
HitResponse BadGuy::collision(GameObject& other, const CollisionHit& hit) { if (!is_active()) return ABORT_MOVE; BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy && badguy->is_active() && badguy->get_group() == COLGROUP_MOVING) { // hit from above? if (badguy->get_bbox().p2.y < (bbox.p1.y + 16)) { if(collision_squished(*badguy)) { return ABORT_MOVE; } } return collision_badguy(*badguy, hit); } Player* player = dynamic_cast<Player*> (&other); if(player) { // hit from above? if (player->get_bbox().p2.y < (bbox.p1.y + 16)) { if(collision_squished(*player)) { return FORCE_MOVE; } } return collision_player(*player, hit); } Bullet* bullet = dynamic_cast<Bullet*> (&other); if(bullet) return collision_bullet(*bullet, hit); return FORCE_MOVE; }
HitResponse MrIceBlock::collision_badguy(BadGuy& badguy, const CollisionHit& hit) { switch(ice_state) { case ICESTATE_NORMAL: return WalkingBadguy::collision_badguy(badguy, hit); case ICESTATE_FLAT: return FORCE_MOVE; case ICESTATE_KICKED: badguy.kill_fall(); return FORCE_MOVE; default: assert(false); } return ABORT_MOVE; }
HitResponse Snail::collision_badguy(BadGuy& badguy, const CollisionHit& hit) { if (m_frozen) return WalkingBadguy::collision_badguy(badguy, hit); switch (state) { case STATE_NORMAL: return WalkingBadguy::collision_badguy(badguy, hit); case STATE_FLAT: case STATE_KICKED_DELAY: return FORCE_MOVE; case STATE_KICKED: badguy.kill_fall(); return FORCE_MOVE; default: assert(false); } return ABORT_MOVE; }
HitResponse SnowSnail::collision_badguy(BadGuy& badguy, const CollisionHit& hit) { switch(ice_state) { case ICESTATE_NORMAL: if(fabsf(hit.normal.x) > .8) { dir = dir == LEFT ? RIGHT : LEFT; sprite->set_action(dir == LEFT ? "left" : "right"); physic.set_velocity_x(-physic.get_velocity_x()); } return CONTINUE; case ICESTATE_FLAT: return FORCE_MOVE; case ICESTATE_KICKED: badguy.kill_fall(); return FORCE_MOVE; default: assert(false); } return ABORT_MOVE; }
void Player::update(float elapsed_time) { if(dying && dying_timer.check()) { dead = true; return; } if(!dying && !deactivated) handle_input(); // handle_input() calls apply_friction() when Tux is not walking, so we'll have to do this ourselves if (deactivated) apply_friction(); // extend/shrink tux collision rectangle so that we fall through/walk over 1 // tile holes if(fabsf(physic.get_velocity_x()) > MAX_WALK_XM) { set_width(34); } else { set_width(31.8); } // on downward slopes, adjust vertical velocity so tux walks smoothly down if (on_ground()) { if(floor_normal.y != 0) { if ((floor_normal.x * physic.get_velocity_x()) >= 0) { physic.set_velocity_y(250); } } } // handle backflipping if (backflipping) { //prevent player from changing direction when backflipping dir = (backflip_direction == 1) ? LEFT : RIGHT; if (backflip_timer.started()) physic.set_velocity_x(100 * backflip_direction); } // set fall mode... if(on_ground()) { fall_mode = ON_GROUND; last_ground_y = get_pos().y; } else { if(get_pos().y > last_ground_y) fall_mode = FALLING; else if(fall_mode == ON_GROUND) fall_mode = JUMPING; } // check if we landed if(on_ground()) { jumping = false; if (backflipping && (!backflip_timer.started())) { backflipping = false; backflip_direction = 0; // if controls are currently deactivated, we take care of standing up ourselves if (deactivated) do_standup(); } } #if 0 // Do butt jump if (butt_jump && on_ground() && is_big()) { // Add a smoke cloud if (duck) Sector::current()->add_smoke_cloud(Vector(get_pos().x - 32, get_pos().y)); else Sector::current()->add_smoke_cloud( Vector(get_pos().x - 32, get_pos().y + 32)); butt_jump = false; // Break bricks beneath Tux if(Sector::current()->trybreakbrick( Vector(base.x + 1, base.y + base.height), false) || Sector::current()->trybreakbrick( Vector(base.x + base.width - 1, base.y + base.height), false)) { physic.set_velocity_y(-2); butt_jump = true; } // Kill nearby badguys std::vector<GameObject*> gameobjects = Sector::current()->gameobjects; for (std::vector<GameObject*>::iterator i = gameobjects.begin(); i != gameobjects.end(); i++) { BadGuy* badguy = dynamic_cast<BadGuy*> (*i); if(badguy) { // don't kill when badguys are already dying or in a certain mode if(badguy->dying == DYING_NOT && badguy->mode != BadGuy::BOMB_TICKING && badguy->mode != BadGuy::BOMB_EXPLODE) { if (fabsf(base.x - badguy->base.x) < 96 && fabsf(base.y - badguy->base.y) < 64) badguy->kill_me(25); } } } } #endif // calculate movement for this frame movement = physic.get_movement(elapsed_time); if(grabbed_object != NULL && !dying) { Vector pos = get_pos() + Vector(dir == LEFT ? -16 : 16, get_bbox().get_height()*0.66666 - 32); grabbed_object->grab(*this, pos, dir); } if(grabbed_object != NULL && dying){ grabbed_object->ungrab(*this, dir); grabbed_object = NULL; } on_ground_flag = false; }