Smooth player movement and viewbobbing
This commit is contained in:
parent
88c04c1823
commit
c941ed9525
@ -8,7 +8,8 @@ game::Player::Player(World* world, size_t sector_idx, const glm::vec3& position)
|
||||
pitch_(0.0f),
|
||||
input_(0),
|
||||
cam_forward_(0.0f),
|
||||
cam_up_(0.0f)
|
||||
cam_up_(0.0f),
|
||||
cam_right_(0.0f)
|
||||
{
|
||||
|
||||
}
|
||||
@ -35,34 +36,59 @@ void game::Player::Update(float dt)
|
||||
float pitch_sin = glm::sin(pitch_);
|
||||
|
||||
// MOVEMENT
|
||||
glm::vec2 velocity_xy(0.0f);
|
||||
glm::vec2 desire_xy(0.0f);
|
||||
if (input_ & PI_FORWARD)
|
||||
velocity_xy.y += 1.0f;
|
||||
desire_xy.y += 1.0f;
|
||||
|
||||
if (input_ & PI_BACKWARD)
|
||||
velocity_xy.y -= 1.0f;
|
||||
desire_xy.y -= 1.0f;
|
||||
|
||||
if (input_ & PI_LEFT)
|
||||
velocity_xy.x -= 1.0f;
|
||||
desire_xy.x -= 1.0f;
|
||||
|
||||
if (input_ & PI_RIGHT)
|
||||
velocity_xy.x += 1.0f;
|
||||
desire_xy.x += 1.0f;
|
||||
|
||||
glm::mat2 movement_basis(
|
||||
yaw_cos, -yaw_sin,
|
||||
yaw_sin, yaw_cos
|
||||
);
|
||||
|
||||
float speed = 3.0f; // Base speed
|
||||
|
||||
glm::vec2 normalized_velocity_xy(0.0f);
|
||||
if (glm::length(velocity_xy) > 0.01f)
|
||||
if (glm::length(desire_xy) > 0.01f)
|
||||
{
|
||||
normalized_velocity_xy = glm::normalize(movement_basis * velocity_xy);
|
||||
desire_xy = glm::normalize(movement_basis * desire_xy);
|
||||
}
|
||||
else
|
||||
{
|
||||
desire_xy = glm::vec2(0.0f);
|
||||
}
|
||||
|
||||
glm::vec2 target_xy = desire_xy * max_speed_;
|
||||
|
||||
glm::vec2 velocity_xy = glm::vec2(velocity_.x, velocity_.y);
|
||||
glm::vec2 difference_xy = target_xy - velocity_xy;
|
||||
float dist = glm::length(difference_xy);
|
||||
|
||||
if (dist > 0.001f)
|
||||
{
|
||||
float accel = acceleration_;
|
||||
|
||||
if (glm::length(velocity_xy) > glm::length(target_xy))
|
||||
{
|
||||
// If we are moving faster than the target, apply deceleration
|
||||
accel = deceleration_;
|
||||
}
|
||||
|
||||
float delta = dt * accel;
|
||||
float t = glm::clamp(delta / dist, 0.0f, 1.0f);
|
||||
|
||||
velocity_xy = glm::mix(velocity_xy, target_xy, t);
|
||||
}
|
||||
|
||||
current_speed_ = glm::length(velocity_xy);
|
||||
|
||||
glm::vec3 velocity = glm::vec3(
|
||||
normalized_velocity_xy * speed,
|
||||
velocity_xy,
|
||||
-1.0f // No vertical movement for now
|
||||
);
|
||||
|
||||
@ -75,14 +101,52 @@ void game::Player::Update(float dt)
|
||||
const glm::mat3& occu_basis = occu_->GetBasis();
|
||||
cam_forward_ = occu_basis * glm::vec3(yaw_sin * pitch_cos, yaw_cos * pitch_cos, pitch_sin);
|
||||
cam_up_ = occu_basis[2]; // Up vector is always the Z axis in sector space
|
||||
cam_right_ = glm::cross(cam_forward_, cam_up_);
|
||||
}
|
||||
|
||||
time_ += dt;
|
||||
}
|
||||
|
||||
void game::Player::GetPOV(size_t& sector_idx, glm::vec3& position, glm::vec3& forward, glm::vec3& up) const
|
||||
{
|
||||
float scale = 1.0f;
|
||||
|
||||
sector_idx = occu_->GetSector().GetIndex();
|
||||
position = occu_->GetPosition() + cam_up_ * 0.7f;
|
||||
|
||||
glm::vec2 bobbing_offset = GetBobbingOffset(time_, 0.01f * current_speed_);
|
||||
glm::vec3 offset = ((cam_up_ * (0.7f + bobbing_offset.y)) + cam_right_ * bobbing_offset.x) * scale;
|
||||
|
||||
position = occu_->GetPosition() + offset;
|
||||
|
||||
forward = cam_forward_;
|
||||
up = cam_up_;
|
||||
|
||||
if (touching_portal_ && touching_portal_->link)
|
||||
{
|
||||
float sd = glm::dot(glm::vec3(touching_portal_->plane), position) + touching_portal_->plane.w;
|
||||
|
||||
// Position is behind portal, render from other sector
|
||||
if (sd < 0.0f)
|
||||
{
|
||||
sector_idx = touching_portal_->link->sector->GetIndex();
|
||||
position = touching_portal_->tr_position * glm::vec4(position, 1.0f);
|
||||
forward = touching_portal_->tr_basis * forward;
|
||||
up = touching_portal_->tr_basis * up;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 game::Player::GetBobbingOffset(float t, float amplitude)
|
||||
{
|
||||
// Frequency and amplitude can be adjusted to tweak the effect
|
||||
float frequency = 10.0f;// 2f * MathHelper.TwoPi; // One full cycle per t=1
|
||||
float xAmplitude = amplitude;
|
||||
float yAmplitude = 0.25f * amplitude;
|
||||
|
||||
glm::vec2 offset;
|
||||
offset.x = glm::sin(t * frequency) * xAmplitude;
|
||||
offset.y = glm::sin(t * frequency * 2.0f) * yAmplitude;
|
||||
|
||||
return offset;
|
||||
}
|
||||
@ -14,8 +14,16 @@ namespace game
|
||||
|
||||
// in occu's sector space
|
||||
glm::vec3 cam_forward_;
|
||||
glm::vec3 cam_right_;
|
||||
glm::vec3 cam_up_;
|
||||
|
||||
float max_speed_ = 4.0f;
|
||||
float acceleration_ = 50.0f;
|
||||
float deceleration_ = 20.0f;
|
||||
|
||||
float time_ = 0.0f;
|
||||
float current_speed_ = 0.0f;
|
||||
|
||||
public:
|
||||
Player(World* world, size_t sector_idx, const glm::vec3& position);
|
||||
|
||||
@ -28,6 +36,8 @@ namespace game
|
||||
|
||||
void GetPOV(size_t& sector_idx, glm::vec3& position, glm::vec3& forward, glm::vec3& up) const;
|
||||
|
||||
private:
|
||||
static glm::vec2 GetBobbingOffset(float t, float amplitude);
|
||||
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user