From cc5bf508c6c1a2dac962ea0934a53fa0b0d0443b Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Thu, 19 Mar 2026 12:53:32 +0800 Subject: [PATCH] feat: smooth player movement --- include/Cubed/gameplay/player.hpp | 6 ++- src/gameplay/player.cpp | 79 ++++++++++++++++++------------- src/gameplay/world.cpp | 5 +- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/include/Cubed/gameplay/player.hpp b/include/Cubed/gameplay/player.hpp index 666b967..1c1d947 100644 --- a/include/Cubed/gameplay/player.hpp +++ b/include/Cubed/gameplay/player.hpp @@ -12,13 +12,15 @@ class World; class Player { private: - + constexpr static float ACCELERATION = 30.0f; + constexpr static float DECELERATION = 50.0f; float m_yaw; float m_pitch; float m_sensitivity = 0.05f; - float m_speed = 10.0f; + float m_speed = 5.0f; + // player is tow block tall, the pos is the lower pos glm::vec3 m_player_pos = glm::vec3(0.0f, 15.0f, 0.0f); glm::vec3 m_front = glm::vec3(0, 0, -1); diff --git a/src/gameplay/player.cpp b/src/gameplay/player.cpp index c3d0e5e..8f97393 100644 --- a/src/gameplay/player.cpp +++ b/src/gameplay/player.cpp @@ -109,49 +109,58 @@ void Player::set_player_pos(const glm::vec3& pos) { } void Player::update(float delta_time) { + static float speed = 0; + static glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f); + if (m_move_state.forward || m_move_state.back || m_move_state.left || m_move_state.right || m_move_state.up) { + direction = glm::vec3(0.0f, 0.0f, 0.0f); + speed += ACCELERATION * delta_time; + if (speed > m_speed) { + speed = m_speed; + } + } else { + speed += -DECELERATION * delta_time; + if (speed < 0) { + speed = 0; + direction = glm::vec3(0.0f, 0.0f, 0.0f); + } + } m_right = glm::normalize(glm::cross(m_front, glm::vec3(0.0f, 1.0f, 0.0f))); - float speed = m_speed * delta_time; + glm::vec3 move_dir = glm::vec3(0.0f); if (m_move_state.forward) { - auto new_pos = m_player_pos + glm::normalize(glm::vec3(m_front.x, 0.0f, m_front.z)) * speed; - new_pos.y += 1.0f; - if (m_world.can_move(new_pos)) { - new_pos.y -= 1.0f; - m_player_pos = new_pos; - } + move_dir += glm::normalize(glm::vec3(m_front.x, 0.0f, m_front.z)); + } if (m_move_state.back) { - auto new_pos = m_player_pos - glm::normalize(glm::vec3(m_front.x, 0.0f, m_front.z)) * speed; - new_pos.y += 1.0f; - if (m_world.can_move(new_pos)) { - new_pos.y -= 1.0f; - m_player_pos = new_pos; - } + move_dir -= glm::normalize(glm::vec3(m_front.x, 0.0f, m_front.z)); + } if (m_move_state.left) { - auto new_pos = m_player_pos - glm::normalize(glm::vec3(m_right.x, 0.0f, m_right.z)) * speed; - new_pos.y += 1.0f; - if (m_world.can_move(new_pos)) { - new_pos.y -= 1.0f; - m_player_pos = new_pos; - } + move_dir -= glm::normalize(glm::vec3(m_right.x, 0.0f, m_right.z)); + } if (m_move_state.right) { - auto new_pos = m_player_pos + glm::normalize(glm::vec3(m_right.x, 0.0f, m_right.z)) * speed; - new_pos.y += 1.0f; - if (m_world.can_move(new_pos)) { - new_pos.y -= 1.0f; - m_player_pos = new_pos; - } + move_dir += glm::normalize(glm::vec3(m_right.x, 0.0f, m_right.z)); } + if (glm::length(move_dir) > 0.001f) { + direction = glm::normalize(move_dir); + } + auto new_pos = m_player_pos + direction * speed * delta_time; + new_pos.y += 1.0f; + if (m_world.can_move(new_pos)) { + new_pos.y -= 1.0f; + m_player_pos = new_pos; + } + if (m_move_state.up) { - auto new_pos = m_player_pos + glm::vec3(0.0f, 1.0f, 0.0f) * speed * 2.0f; + auto new_pos = m_player_pos + glm::vec3(0.0f, 1.0f, 0.0f) * speed * 2.0f * delta_time; new_pos.y += 2.0f; if (!m_world.is_block(glm::floor(new_pos))) { new_pos.y -= 2.0f; m_player_pos = new_pos; } } + /* if (m_move_state.down) { m_player_pos -= glm::vec3(0.0f, 1.0f, 0.0f) * speed; @@ -165,7 +174,7 @@ void Player::update(float delta_time) { } else { m_look_block = std::nullopt; } - + if (m_look_block != std::nullopt) { if (Input::get_input_state().mouse_state.left) { if (m_world.is_block(m_look_block->pos)) { @@ -190,12 +199,18 @@ void Player::update(float delta_time) { static bool should_ceil = true; + static float down_speed = 0.0f; + if (!m_world.is_block(glm::floor(m_player_pos)) && !m_move_state.up) { - - m_player_pos -= glm::vec3(0.0f, 1.0f, 0.0f) * speed * 0.7f; - } else if (should_ceil) { - should_ceil = false; - m_player_pos.y = std::floor(m_player_pos.y + 1.0f); + should_ceil = true; + down_speed += 10 * delta_time; + m_player_pos -= glm::vec3(0.0f, 1.0f, 0.0f) * down_speed * delta_time; + } else { + if (should_ceil && m_world.is_block(glm::floor(m_player_pos))) { + should_ceil = false; + m_player_pos.y = std::floor(m_player_pos.y + 1.0f); + } + down_speed = 0.0f; } if (m_player_pos.y < -50.0f) { diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index 349af20..1d6d744 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -14,10 +14,11 @@ World::~World() { bool World::can_move(const glm::vec3& pos) const{ - if (is_block(glm::floor(pos))) { + if (is_block(glm::floor(glm::vec3(pos.x, pos.y - 0.5f, pos.z)))) { return false; } - if (is_block(glm::floor(glm::vec3(pos.x, pos.y + 1.0f, pos.z)))) { + + if (is_block(glm::floor(glm::vec3(pos.x, pos.y + 0.5f, pos.z)))) { return false; } return true;