From bd1a9557a5ff3e227377b12ceb9eb33f2762a3b3 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Tue, 28 Jul 2026 10:54:13 +0800 Subject: [PATCH] refactor: move movement logic into SpeedSystem and Entity components --- include/Cubed/gameplay/client_player.hpp | 10 +- include/Cubed/gameplay/entity.hpp | 31 ++++- .../Cubed/gameplay/systems/speed_system.hpp | 63 ++++++++++ include/Cubed/input/input.hpp | 9 -- src/dev_panel.cpp | 1 + src/gameplay/client_player.cpp | 112 ++++++------------ src/gameplay/client_world.cpp | 2 +- src/gameplay/entity.cpp | 15 ++- src/window.cpp | 2 +- 9 files changed, 145 insertions(+), 100 deletions(-) create mode 100644 include/Cubed/gameplay/systems/speed_system.hpp diff --git a/include/Cubed/gameplay/client_player.hpp b/include/Cubed/gameplay/client_player.hpp index 749c9a7..d75fd27 100644 --- a/include/Cubed/gameplay/client_player.hpp +++ b/include/Cubed/gameplay/client_player.hpp @@ -65,7 +65,7 @@ public: void set_uuid(std::string_view uuid); std::string get_uuid() const; const std::string& get_name() const; - void reset_key_status(); + void reset_input_status(); void init(std::string_view name); bool ray_cast(const glm::vec3& start, const glm::vec3& dir, @@ -83,7 +83,7 @@ private: using enum GameMode; float m_max_walk_speed = DEFAULT_MAX_WALK_SPEED; float m_max_run_speed = DEFAULT_MAX_RUN_SPEED; - + float m_max_y_speed = 7.5f; static constexpr float MAX_SPACE_ON_TIME = 0.3f; static constexpr float PLACE_BLOCK_INTERVAL = 0.2f; Movement m_movement{}; @@ -93,12 +93,8 @@ private: std::array m_hotbar; float m_sensitivity = 0.15f; - float m_fly_y_speed = 7.5f; - bool can_up = true; - float space_on_time = 0.0f; bool space_on = false; - bool is_fly = false; int m_selected_hotbar = 0; @@ -106,7 +102,6 @@ private: bool m_sprinting = false; bool m_underwater = false; - glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 move_distance{0.0f, 0.0f, 0.0f}; // player is tow block tall, the pos is the lower pos ChunkPos m_last_chunk_pos{0, 0}; @@ -115,7 +110,6 @@ private: glm::vec3 m_right{0, 0, 0}; static constexpr glm::vec3 M_SIZE{0.6f, 1.8f, 0.6f}; - MoveState m_move_state{}; MouseState m_mouse_state{}; GameMode m_game_mode = CREATIVE; std::optional m_look_block = std::nullopt; diff --git a/include/Cubed/gameplay/entity.hpp b/include/Cubed/gameplay/entity.hpp index 4205dbe..199d318 100644 --- a/include/Cubed/gameplay/entity.hpp +++ b/include/Cubed/gameplay/entity.hpp @@ -37,7 +37,7 @@ struct Orientation { struct Velocity { glm::vec3 value{0.0f}; - glm::vec3 max{4.5f}; + glm::vec3 max{4.5f, 7.5f, 7.5f}; }; struct HitBoxes { @@ -54,6 +54,22 @@ struct Gravity { float value = DEFAULT_G; }; +struct MoveState { + bool forward = false; + bool back = false; + bool left = false; + bool right = false; + bool down = false; + bool up = false; + + bool is_fly = false; + bool can_up = true; +}; + +struct Direction { + glm::vec3 value{0.0f}; +}; + class Entity { public: glm::vec3& max_speed(); @@ -67,13 +83,24 @@ public: float& walk_time(); Gait get_gait() const; + Velocity& velocity(); + Position& pos(); + WalkPose& walk_pose(); + Orientation& angle(); + Movement& movement(); + Gravity& gravity(); + MoveState& move_state(); + Direction& direction(); + protected: Position m_pos; - WalkPose m_walk_pos; + WalkPose m_walk_pose; Velocity m_velocity; Orientation m_angle; Movement m_movement; Gravity m_gravity; + MoveState m_move_state; + Direction m_direction; }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/gameplay/systems/speed_system.hpp b/include/Cubed/gameplay/systems/speed_system.hpp new file mode 100644 index 0000000..2a736cb --- /dev/null +++ b/include/Cubed/gameplay/systems/speed_system.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "Cubed/gameplay/entity.hpp" + +namespace Cubed { +class SpeedSystem { +public: + static void update(float dt, Entity& e) { + auto& m_velocity = e.velocity(); + auto& m_move_state = e.move_state(); + auto& m_movement = e.movement(); + auto& direction = e.direction(); + auto& m_gravity = e.gravity(); + // calculate speed + if (m_move_state.forward || m_move_state.back || m_move_state.left || + m_move_state.right) { + direction.value = glm::vec3(0.0f, 0.0f, 0.0f); + m_velocity.value.x += m_movement.acceleration * dt; + m_velocity.value.z += m_movement.acceleration * dt; + if (m_velocity.value.x > m_velocity.max.x) { + m_velocity.value.x = m_velocity.max.x; + } + if (m_velocity.value.z > m_velocity.max.z) { + m_velocity.value.z = m_velocity.max.z; + } + } else { + m_velocity.value.x += -m_movement.deceleration * dt; + m_velocity.value.z += -m_movement.deceleration * dt; + if (m_velocity.value.z < 0.0f) { + m_velocity.value.z = 0.0f; + } + if (m_velocity.value.x < 0.0f) { + m_velocity.value.x = 0.0f; + } + if (m_velocity.value.z < 0.0f && m_velocity.value.x < 0.0f) { + direction.value = glm::vec3(0.0f, 0.0f, 0.0f); + } + } + if (m_move_state.is_fly) { + if (m_move_state.up) { + m_velocity.value.y = m_velocity.max.y; + } + + if (m_move_state.down) { + m_velocity.value.y = -m_velocity.max.y; + } + + if (!m_move_state.down && !m_move_state.up) { + m_velocity.value.y = 0.0f; + } + } else { + if (m_move_state.up && m_move_state.can_up) { + m_velocity.value.y = m_movement.jump_power; + m_move_state.can_up = false; + } + + m_velocity.value.y += -m_gravity.value * dt; + } + } + +private: +}; +} // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/input/input.hpp b/include/Cubed/input/input.hpp index ef3e549..f634796 100644 --- a/include/Cubed/input/input.hpp +++ b/include/Cubed/input/input.hpp @@ -2,15 +2,6 @@ namespace Cubed { -struct MoveState { - bool forward = false; - bool back = false; - bool left = false; - bool right = false; - bool down = false; - bool up = false; -}; - struct MouseState { bool left = false; bool right = false; diff --git a/src/dev_panel.cpp b/src/dev_panel.cpp index 2854f3a..8c0d54d 100644 --- a/src/dev_panel.cpp +++ b/src/dev_panel.cpp @@ -516,6 +516,7 @@ void DevPanel::show_player_tab_item() { m_player->deceleration() = DEFAULT_DECELERATION; m_player->g() = DEFAULT_G; m_player->change_mode(GameMode::CREATIVE); + m_player->fly_y_speed() = 7.5f; m_player->set_gait(Gait::WALK); m_player_profile.game_mode = 0; m_player_profile.gait = 0; diff --git a/src/gameplay/client_player.cpp b/src/gameplay/client_player.cpp index b738866..5cd5a2d 100644 --- a/src/gameplay/client_player.cpp +++ b/src/gameplay/client_player.cpp @@ -4,7 +4,7 @@ #include "Cubed/config.hpp" #include "Cubed/debug_collector.hpp" #include "Cubed/gameplay/client_world.hpp" - +#include "Cubed/gameplay/systems/speed_system.hpp" namespace {} // namespace namespace Cubed { @@ -108,13 +108,15 @@ void ClientPlayer::change_mode(GameMode mode) { m_game_mode = mode; Logger::info("Change GameMode to {}", to_str(mode)); if (mode == CREATIVE) { - is_fly = false; + m_move_state.is_fly = false; m_max_run_speed = DEFAULT_MAX_RUN_SPEED; - m_velocity.max = glm::vec3{m_max_walk_speed, 0.0f, m_max_walk_speed}; + m_velocity.max = + glm::vec3{m_max_walk_speed, m_max_y_speed, m_max_walk_speed}; } else if (mode == SPECTATOR) { - is_fly = true; - m_walk_pos.gait = Gait::RUN; - m_velocity.max = glm::vec3{m_max_run_speed, 0.0f, m_max_run_speed}; + m_move_state.is_fly = true; + m_walk_pose.gait = Gait::RUN; + m_velocity.max = + glm::vec3{m_max_run_speed, m_max_y_speed, m_max_run_speed}; } } void ClientPlayer::reload_config() { @@ -128,9 +130,9 @@ void ClientPlayer::set_player_pos(const glm::vec3& pos) { } void ClientPlayer::update(float delta_time) { - WalkPose pos = m_walk_pos; + WalkPose pos = m_walk_pose; pos.gait = compute_gait(); - m_walk_pos = pos; + m_walk_pose = pos; update_move(delta_time); update_lookup_block(); place_block(delta_time); @@ -175,7 +177,7 @@ bool ClientPlayer::update_player_move_state(Key key, KeyAction action) { m_move_state.up = true; if (space_on) { if (m_game_mode == CREATIVE) { - is_fly = !is_fly; + m_move_state.is_fly = !m_move_state.is_fly; m_velocity.value.y = 0.0f; } space_on = false; @@ -277,7 +279,7 @@ void ClientPlayer::update_direction() { move_dir = move_dir_front + move_dir_right; if (glm::length(move_dir) > 0.001f) { - direction = glm::normalize(move_dir); + m_direction.value = glm::normalize(move_dir); } } @@ -340,26 +342,10 @@ void ClientPlayer::update_move(float delta_time) { if (delta_time > 1.0f) { return; } + if (m_velocity.value.x < 0.01f || m_velocity.value.z < 0.01f) { m_sprinting = false; } - // ensure the thread safe - glm::vec3 player_pos; - - { - std::shared_lock lock(m_player_pos_mutex); - player_pos = m_pos.value; - } - - if (m_game_mode != SPECTATOR) { - m_velocity.max = - (m_walk_pos.gait == Gait::RUN) - ? glm::vec3{m_max_run_speed, 0.0f, m_max_run_speed} - : glm::vec3{m_max_walk_speed, 0.0f, m_max_walk_speed}; - } else { - m_velocity.max = glm::vec3{m_max_run_speed, 0.0f, m_max_run_speed}; - } - if (space_on) { space_on_time += delta_time; if (space_on_time >= MAX_SPACE_ON_TIME) { @@ -368,59 +354,33 @@ void ClientPlayer::update_move(float delta_time) { } } - // calculate speed - if (m_move_state.forward || m_move_state.back || m_move_state.left || - m_move_state.right) { - direction = glm::vec3(0.0f, 0.0f, 0.0f); - m_velocity.value.x += m_movement.acceleration * delta_time; - m_velocity.value.z += m_movement.acceleration * delta_time; - if (m_velocity.value.x > m_velocity.max.x) { - m_velocity.value.x = m_velocity.max.x; - } - if (m_velocity.value.z > m_velocity.max.z) { - m_velocity.value.z = m_velocity.max.z; - } + if (m_game_mode != SPECTATOR) { + m_velocity.max = + (m_walk_pose.gait == Gait::RUN) + ? glm::vec3{m_max_run_speed, m_max_y_speed, m_max_run_speed} + : glm::vec3{m_max_walk_speed, m_max_y_speed, m_max_walk_speed}; } else { - m_velocity.value.x += -m_movement.deceleration * delta_time; - m_velocity.value.z += -m_movement.deceleration * delta_time; - if (m_velocity.value.z < 0.0f) { - m_velocity.value.z = 0.0f; - } - if (m_velocity.value.x < 0.0f) { - m_velocity.value.x = 0.0f; - } - if (m_velocity.value.z < 0.0f && m_velocity.value.x < 0.0f) { - direction = glm::vec3(0.0f, 0.0f, 0.0f); - } + m_velocity.max = + glm::vec3{m_max_run_speed, m_max_y_speed, m_max_run_speed}; } + SpeedSystem::update(delta_time, *this); + update_direction(); - move_distance = {direction.x * m_velocity.value.x * delta_time, 0.0f, - direction.z * m_velocity.value.z * delta_time}; + move_distance = {m_direction.value.x * m_velocity.value.x * delta_time, + 0.0f, + m_direction.value.z * m_velocity.value.z * delta_time}; + move_distance.y = m_velocity.value.y * delta_time; - if (is_fly) { - if (m_move_state.up) { - m_velocity.value.y = m_fly_y_speed; - } + // ensure the thread safe + glm::vec3 player_pos; - if (m_move_state.down) { - m_velocity.value.y = -m_fly_y_speed; - } - - if (!m_move_state.down && !m_move_state.up) { - m_velocity.value.y = 0.0f; - } - } else { - if (m_move_state.up && can_up) { - m_velocity.value.y = m_movement.jump_power; - can_up = false; - } - - m_velocity.value.y += -m_gravity.value * delta_time; + { + std::shared_lock lock(m_player_pos_mutex); + player_pos = m_pos.value; } - move_distance.y = m_velocity.value.y * delta_time; // y update_y_move(player_pos); // x @@ -512,8 +472,8 @@ void ClientPlayer::update_y_move(glm::vec3& player_pos) { player_pos.y -= move_distance.y; m_velocity.value.y = 0.0f; if (move_distance.y < 0) { - can_up = true; - is_fly = false; + m_move_state.can_up = true; + m_move_state.is_fly = false; } return; } @@ -669,7 +629,7 @@ ClientPlayer::ChunkPosSet ClientPlayer::get_chunk_pos_set() { float& ClientPlayer::max_walk_speed() { return m_max_walk_speed; } float& ClientPlayer::max_run_speed() { return m_max_run_speed; } -float& ClientPlayer::fly_y_speed() { return m_fly_y_speed; } +float& ClientPlayer::fly_y_speed() { return m_max_y_speed; } const ItemStack& ClientPlayer::get_current_itemstack() const { return m_hotbar[m_selected_hotbar]; }; @@ -688,7 +648,7 @@ std::string ClientPlayer::get_uuid() const { } const std::string& ClientPlayer::get_name() const { return m_name; } -void ClientPlayer::reset_key_status() { +void ClientPlayer::reset_input_status() { m_mouse_state.left = false; m_mouse_state.right = false; m_move_state.left = false; @@ -708,7 +668,7 @@ void ClientPlayer::init(std::string_view name) { m_name = name; m_timers.try_emplace("Player Walk Sound", WALK_SOUND_INTERVAL, [this]() { - if (!m_moving || is_fly) { + if (!m_moving || m_move_state.is_fly) { return; } glm::ivec3 block; diff --git a/src/gameplay/client_world.cpp b/src/gameplay/client_world.cpp index 9c5773a..f8c02cf 100644 --- a/src/gameplay/client_world.cpp +++ b/src/gameplay/client_world.cpp @@ -692,7 +692,7 @@ void ClientWorld::request_chunk() { Logger::info("Send Chunk Request Success"); m_requesting_chunk = false; } -void ClientWorld::reset_key_status() { m_player.reset_key_status(); } +void ClientWorld::reset_key_status() { m_player.reset_input_status(); } void ClientWorld::receive_chunk(std::vector raw_data, PacketHeader header) { diff --git a/src/gameplay/entity.cpp b/src/gameplay/entity.cpp index 8218d30..1b9b550 100644 --- a/src/gameplay/entity.cpp +++ b/src/gameplay/entity.cpp @@ -5,10 +5,19 @@ glm::vec3& Entity::max_speed() { return m_velocity.max; } float& Entity::acceleration() { return m_movement.acceleration; } float& Entity::deceleration() { return m_movement.deceleration; } float& Entity::g() { return m_gravity.value; } -void Entity::set_gait(Gait gait) { m_walk_pos.gait = gait; } +void Entity::set_gait(Gait gait) { m_walk_pose.gait = gait; } float Entity::yaw() const { return m_angle.yaw; } float Entity::pitch() const { return m_angle.pitch; } float& Entity::roll() { return m_angle.roll; } -float& Entity::walk_time() { return m_walk_pos.walk_time; } -Gait Entity::get_gait() const { return m_walk_pos.gait; } +float& Entity::walk_time() { return m_walk_pose.walk_time; } +Gait Entity::get_gait() const { return m_walk_pose.gait; } + +Velocity& Entity::velocity() { return m_velocity; } +Position& Entity::pos() { return m_pos; } +WalkPose& Entity::walk_pose() { return m_walk_pose; } +Orientation& Entity::angle() { return m_angle; } +Movement& Entity::movement() { return m_movement; } +Gravity& Entity::gravity() { return m_gravity; } +MoveState& Entity::move_state() { return m_move_state; } +Direction& Entity::direction() { return m_direction; } } // namespace Cubed \ No newline at end of file diff --git a/src/window.cpp b/src/window.cpp index e234b31..f5c7a83 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -330,7 +330,7 @@ void Window::set_imgui_enabled(bool enable) { if (m_camera) { auto player = m_camera->player(); if (player) { - player->reset_key_status(); + player->reset_input_status(); } } }