Skip to content

Commit

Permalink
Various crusher fixes (#3047)
Browse files Browse the repository at this point in the history
This also includes some code style improvements to the `Crusher::collision` and relieves some of the mental pain I have when looking at the SuperTux source code.

---------

Co-authored-by: MatusGuy <[email protected]>
  • Loading branch information
tobbi and MatusGuy authored Dec 27, 2024
1 parent 2ef1008 commit cff5719
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 31 deletions.
67 changes: 44 additions & 23 deletions src/badguy/crusher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,31 +123,37 @@ HitResponse
Crusher::collision(MovingObject& other, const CollisionHit& hit)
{
auto* player = dynamic_cast<Player*>(&other);
bool crushed_bottom = m_state == CRUSHING && !m_sideways && hit.bottom;
bool crushed_sideways = m_state == CRUSHING && m_sideways &&
((hit.left && m_physic.get_velocity_x() < 0.f) ||
(hit.right && m_physic.get_velocity_x() > 0.f));
bool is_crushing = crushed_bottom || crushed_sideways;

// If the other object is the player, and the collision is at the
// bottom of the crusher, hurt the player.
if (player && hit.bottom && player->on_ground() && m_state == CRUSHING) {
if (player && is_crushing &&
((crushed_bottom && player->on_ground()) || crushed_sideways))
{
SoundManager::current()->play("sounds/brick.wav", get_pos());
set_state(RECOVERING);

if (player->is_invincible()) {
return ABORT_MOVE;
}

player->kill(false);

return FORCE_MOVE;
}

auto* badguy = dynamic_cast<BadGuy*>(&other);
if (badguy && m_state == CRUSHING && ((!m_sideways && hit.bottom) ||
(m_sideways && ((hit.left && m_physic.get_velocity_x() < 0.f) ||
(hit.right && m_physic.get_velocity_x() > 0.f)))))
if (badguy && is_crushing)
{
badguy->kill_fall();
}

auto* rock = dynamic_cast<Rock*>(&other);
if (rock && !rock->is_grabbed() && m_state == CRUSHING && ((!m_sideways && hit.bottom) ||
(m_sideways && ((hit.left && m_physic.get_velocity_x() < 0.f) ||
(hit.right && m_physic.get_velocity_x() > 0.f)))))
if (rock && !rock->is_grabbed() && is_crushing)
{
SoundManager::current()->play("sounds/brick.wav", get_pos());
m_physic.reset();
Expand Down Expand Up @@ -226,14 +232,20 @@ Crusher::collision_solid(const CollisionHit& hit)
}
}
}
if (hit.bottom)
spawn_roots(Direction::DOWN);
else if (hit.top)
spawn_roots(Direction::UP);
else if (hit.left)
spawn_roots(Direction::LEFT);
else if (hit.right)
spawn_roots(Direction::RIGHT);
if(m_sideways)
{
if (hit.left)
spawn_roots(Direction::LEFT);
else if (hit.right)
spawn_roots(Direction::RIGHT);
}
else
{
if (hit.bottom)
spawn_roots(Direction::DOWN);
else if (hit.top)
spawn_roots(Direction::UP);
}
break;
default:
log_debug << "Crusher in invalid state" << std::endl;
Expand Down Expand Up @@ -638,18 +650,27 @@ Crusher::eye_position(bool right) const
}
break;
case RECOVERING:
{
// Amplitude dependent on size.
auto amplitude = static_cast<float>(m_sprite->get_width()) / 64.0f * 2.0f;

//Phase factor due to cooldown timer.
auto cooldown_phase_factor = (m_ic_size == NORMAL ? RECOVER_SPEED_NORMAL : RECOVER_SPEED_LARGE) + m_cooldown_timer * 13.0f;

// Phase factor due to y position.
auto y_position_phase_factor = !m_sideways ? get_pos().y / 13 : get_pos().x / 13;

auto phase_factor = y_position_phase_factor - cooldown_phase_factor;

// Eyes spin while crusher is recovering, giving a dazed impression.
return Vector(sinf((right ? 1 : -1) * // X motion of each eye is opposite of the other.
((!m_sideways ? get_pos().y / 13 : get_pos().x / 13) - // Phase factor due to y position.
(m_ic_size == NORMAL ? RECOVER_SPEED_NORMAL : RECOVER_SPEED_LARGE) + m_cooldown_timer * 13.0f)) * //Phase factor due to cooldown timer.
static_cast<float>(m_sprite->get_width()) / 64.0f * 2.0f - (right ? 1 : -1) * // Amplitude dependent on size.
static_cast<float>(m_sprite->get_width()) / 64.0f * 2.0f, // Offset to keep eyes visible.
phase_factor) * amplitude - (right ? 1 : -1) *
amplitude, // Offset to keep eyes visible.

cosf((right ? 3.1415f : 0.0f) + // Eyes spin out of phase of eachother.
(!m_sideways ? get_pos().y / 13 : get_pos().x / 13) - // Phase factor due to y position.
(m_ic_size == NORMAL ? RECOVER_SPEED_NORMAL : RECOVER_SPEED_LARGE) + m_cooldown_timer * 13.0f) * //Phase factor due to cooldown timer.
static_cast<float>(m_sprite->get_width()) / 64.0f * 2.0f - // Amplitude dependent on size.
static_cast<float>(m_sprite->get_width()) / 64.0f * 2.0f); // Offset to keep eyes visible.
phase_factor) * amplitude -
amplitude); // Offset to keep eyes visible.
}
default:
log_debug << "Crusher in invalid state" << std::endl;
break;
Expand Down
10 changes: 2 additions & 8 deletions src/object/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2340,14 +2340,8 @@ Player::collision_solid(const CollisionHit& hit)
m_physic.set_velocity_x(0);
}

// crushed?
if (hit.crush) {
if (hit.left || hit.right) {
kill(true);
} else if (hit.top || hit.bottom) {
kill(false);
}
}
if (hit.crush)
kill(false);

if ((hit.left && m_boost < 0.f) || (hit.right && m_boost > 0.f))
m_boost = 0.f;
Expand Down

0 comments on commit cff5719

Please sign in to comment.