mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
refactor(gameplay): extract Entity base class from ClientPlayer
Move position, walk pose, velocity, orientation, movement, and gravity fields and their accessors into a new Entity base class. ClientPlayer now inherits from Entity, removing duplicated members. Also update velocity handling to use 3D vector per axis and adjust related logic.
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
namespace Cubed {
|
||||
|
||||
class ClientWorld;
|
||||
class ClientPlayer {
|
||||
class ClientPlayer : public Entity {
|
||||
public:
|
||||
static constexpr size_t HOTBAR_SUM = 10;
|
||||
static constexpr float WALK_SOUND_INTERVAL = 0.45f;
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
static AABB get_aabb(const glm::vec3& pos);
|
||||
const glm::vec3& get_front() const;
|
||||
Gait get_gait() const;
|
||||
|
||||
const std::optional<LookBlock>& get_look_block_pos() const;
|
||||
// thread safe
|
||||
glm::vec3 get_player_pos() const;
|
||||
@@ -54,15 +54,10 @@ public:
|
||||
|
||||
float& max_walk_speed();
|
||||
float& max_run_speed();
|
||||
float& max_speed();
|
||||
float& acceleration();
|
||||
float& deceleration();
|
||||
float& g();
|
||||
float& fly_y_speed();
|
||||
|
||||
const ItemStack& get_current_itemstack() const;
|
||||
|
||||
void set_gait(Gait gait);
|
||||
GameMode& game_mode();
|
||||
|
||||
ClientWorld& get_world();
|
||||
@@ -73,10 +68,6 @@ public:
|
||||
void reset_key_status();
|
||||
void init(std::string_view name);
|
||||
|
||||
float yaw() const;
|
||||
float pitch() const;
|
||||
float& angle();
|
||||
float& walk_time();
|
||||
bool ray_cast(const glm::vec3& start, const glm::vec3& dir,
|
||||
glm::ivec3& block_pos, glm::vec3& normal,
|
||||
float distance = 4.0f);
|
||||
@@ -98,13 +89,10 @@ private:
|
||||
Movement m_movement{};
|
||||
Gravity m_gravity{};
|
||||
float m_place_time = PLACE_BLOCK_INTERVAL;
|
||||
Orientation m_angle;
|
||||
WalkPose m_walk_pos;
|
||||
|
||||
std::array<ItemStack, HOTBAR_SUM> m_hotbar;
|
||||
float m_sensitivity = 0.15f;
|
||||
|
||||
float m_max_speed = m_max_walk_speed;
|
||||
float m_y_speed = 0.0f;
|
||||
float m_fly_y_speed = 7.5f;
|
||||
bool can_up = true;
|
||||
|
||||
@@ -112,8 +100,6 @@ private:
|
||||
bool space_on = false;
|
||||
bool is_fly = false;
|
||||
|
||||
float m_xz_speed = 0.0f;
|
||||
|
||||
int m_selected_hotbar = 0;
|
||||
|
||||
bool m_moving = false;
|
||||
@@ -123,8 +109,6 @@ private:
|
||||
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
|
||||
|
||||
glm::vec3 m_player_pos{0.0f, 255.0f, 0.0f};
|
||||
ChunkPos m_last_chunk_pos{0, 0};
|
||||
|
||||
glm::vec3 m_front{0, 0, -1};
|
||||
|
||||
@@ -37,6 +37,7 @@ struct Orientation {
|
||||
|
||||
struct Velocity {
|
||||
glm::vec3 value{0.0f};
|
||||
glm::vec3 max{4.5f};
|
||||
};
|
||||
|
||||
struct HitBoxes {
|
||||
@@ -46,11 +47,33 @@ struct HitBoxes {
|
||||
struct Movement {
|
||||
float acceleration = DEFAULT_ACCELERATION;
|
||||
float deceleration = DEFAULT_DECELERATION;
|
||||
float jump_power = 0;
|
||||
float jump_power = 7.5f;
|
||||
};
|
||||
|
||||
struct Gravity {
|
||||
float value = DEFAULT_G;
|
||||
};
|
||||
|
||||
class Entity {
|
||||
public:
|
||||
glm::vec3& max_speed();
|
||||
float& acceleration();
|
||||
float& deceleration();
|
||||
float& g();
|
||||
void set_gait(Gait gait);
|
||||
float yaw() const;
|
||||
float pitch() const;
|
||||
float& roll();
|
||||
float& walk_time();
|
||||
Gait get_gait() const;
|
||||
|
||||
protected:
|
||||
Position m_pos;
|
||||
WalkPose m_walk_pos;
|
||||
Velocity m_velocity;
|
||||
Orientation m_angle;
|
||||
Movement m_movement;
|
||||
Gravity m_gravity;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -97,4 +97,5 @@ target_sources(${PROJECT_NAME}
|
||||
render/model_renderer.cpp
|
||||
gameplay/chunk.cpp
|
||||
gameplay/hitbox_manager.cpp
|
||||
gameplay/entity.cpp
|
||||
)
|
||||
@@ -20,15 +20,13 @@ AABB ClientPlayer::get_aabb(const glm::vec3& pos) {
|
||||
}
|
||||
const glm::vec3& ClientPlayer::get_front() const { return m_front; }
|
||||
|
||||
Gait ClientPlayer::get_gait() const { return m_walk_pos.gait; }
|
||||
|
||||
const std::optional<LookBlock>& ClientPlayer::get_look_block_pos() const {
|
||||
return m_look_block;
|
||||
}
|
||||
glm::vec3 ClientPlayer::get_player_pos() const {
|
||||
|
||||
std::shared_lock lock(m_player_pos_mutex);
|
||||
return m_player_pos;
|
||||
return m_pos.value;
|
||||
}
|
||||
|
||||
const MoveState& ClientPlayer::get_move_state() const { return m_move_state; }
|
||||
@@ -111,17 +109,21 @@ void ClientPlayer::change_mode(GameMode mode) {
|
||||
Logger::info("Change GameMode to {}", to_str(mode));
|
||||
if (mode == CREATIVE) {
|
||||
is_fly = false;
|
||||
m_max_speed = m_max_walk_speed;
|
||||
m_velocity.max = glm::vec3{m_max_walk_speed};
|
||||
} else if (mode == SPECTATOR) {
|
||||
is_fly = true;
|
||||
m_max_speed = m_max_run_speed;
|
||||
m_velocity.max = glm::vec3{m_max_run_speed};
|
||||
}
|
||||
}
|
||||
void ClientPlayer::reload_config() {
|
||||
auto& config = m_world.get_config();
|
||||
m_sensitivity = config.get("player.mouse_sensitivity", 0.15f);
|
||||
}
|
||||
void ClientPlayer::set_player_pos(const glm::vec3& pos) { m_player_pos = pos; }
|
||||
void ClientPlayer::set_player_pos(const glm::vec3& pos) {
|
||||
|
||||
std::lock_guard lock(m_player_pos_mutex);
|
||||
m_pos.value = pos;
|
||||
}
|
||||
|
||||
void ClientPlayer::update(float delta_time) {
|
||||
WalkPose pos = m_walk_pos;
|
||||
@@ -130,9 +132,11 @@ void ClientPlayer::update(float delta_time) {
|
||||
update_move(delta_time);
|
||||
update_lookup_block();
|
||||
place_block(delta_time);
|
||||
d_rep("player_pos", "x: {:.2f} y: {:.2f} z: {:.2f}", m_player_pos.x,
|
||||
m_player_pos.y, m_player_pos.z);
|
||||
d_rep("speed", "Speed: {:.2} m/s", m_xz_speed);
|
||||
std::shared_lock lock(m_player_pos_mutex);
|
||||
d_rep("player_pos", "x: {:.2f} y: {:.2f} z: {:.2f}", m_pos.value.x,
|
||||
m_pos.value.y, m_pos.value.z);
|
||||
d_rep("speed", "Speed(x, y, z): {:.2} m/s {:.2} m/s {:.2} m/s",
|
||||
m_velocity.value.x, m_velocity.value.y, m_velocity.value.z);
|
||||
}
|
||||
bool ClientPlayer::update_player_move_state(Key key, KeyAction action) {
|
||||
if (key == Key::W) {
|
||||
@@ -170,7 +174,7 @@ bool ClientPlayer::update_player_move_state(Key key, KeyAction action) {
|
||||
if (space_on) {
|
||||
if (m_game_mode == CREATIVE) {
|
||||
is_fly = !is_fly;
|
||||
m_y_speed = 0.0f;
|
||||
m_velocity.value.y = 0.0f;
|
||||
}
|
||||
space_on = false;
|
||||
space_on_time = 0.0f;
|
||||
@@ -279,8 +283,9 @@ void ClientPlayer::update_lookup_block() {
|
||||
// calculate the block that is looked
|
||||
glm::ivec3 block_pos;
|
||||
glm::vec3 block_normal;
|
||||
std::shared_lock lock(m_player_pos_mutex);
|
||||
if (ray_cast(
|
||||
glm::vec3(m_player_pos.x, (m_player_pos.y + 1.6f), m_player_pos.z),
|
||||
glm::vec3(m_pos.value.x, (m_pos.value.y + 1.6f), m_pos.value.z),
|
||||
m_front, block_pos, block_normal)) {
|
||||
m_look_block = LookBlock{block_pos, glm::floor(block_normal)};
|
||||
} else {
|
||||
@@ -333,7 +338,7 @@ void ClientPlayer::update_move(float delta_time) {
|
||||
if (delta_time > 1.0f) {
|
||||
return;
|
||||
}
|
||||
if (m_xz_speed < 0.01f) {
|
||||
if (m_velocity.value.x < 0.01f || m_velocity.value.z < 0.01f) {
|
||||
m_sprinting = false;
|
||||
}
|
||||
// ensure the thread safe
|
||||
@@ -341,14 +346,15 @@ void ClientPlayer::update_move(float delta_time) {
|
||||
|
||||
{
|
||||
std::shared_lock lock(m_player_pos_mutex);
|
||||
player_pos = m_player_pos;
|
||||
player_pos = m_pos.value;
|
||||
}
|
||||
|
||||
if (m_game_mode != SPECTATOR) {
|
||||
m_max_speed =
|
||||
(m_walk_pos.gait == Gait::RUN) ? m_max_run_speed : m_max_walk_speed;
|
||||
m_velocity.max = (m_walk_pos.gait == Gait::RUN)
|
||||
? glm::vec3{m_max_run_speed}
|
||||
: glm::vec3{m_max_walk_speed};
|
||||
} else {
|
||||
m_max_speed = m_max_run_speed;
|
||||
m_velocity.max = glm::vec3{m_max_run_speed};
|
||||
}
|
||||
|
||||
if (space_on) {
|
||||
@@ -363,45 +369,55 @@ void ClientPlayer::update_move(float delta_time) {
|
||||
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_xz_speed += m_movement.acceleration * delta_time;
|
||||
if (m_xz_speed > m_max_speed) {
|
||||
m_xz_speed = m_max_speed;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
m_xz_speed += -m_movement.deceleration * delta_time;
|
||||
if (m_xz_speed < 0) {
|
||||
m_xz_speed = 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
update_direction();
|
||||
|
||||
move_distance = {direction.x * m_xz_speed * delta_time, 0.0f,
|
||||
direction.z * m_xz_speed * delta_time};
|
||||
move_distance = {direction.x * m_velocity.value.x * delta_time, 0.0f,
|
||||
direction.z * m_velocity.value.z * delta_time};
|
||||
|
||||
if (is_fly) {
|
||||
if (m_move_state.up) {
|
||||
m_y_speed = m_fly_y_speed;
|
||||
m_velocity.value.y = m_fly_y_speed;
|
||||
}
|
||||
|
||||
if (m_move_state.down) {
|
||||
m_y_speed = -m_fly_y_speed;
|
||||
m_velocity.value.y = -m_fly_y_speed;
|
||||
}
|
||||
|
||||
if (!m_move_state.down && !m_move_state.up) {
|
||||
m_y_speed = 0.0f;
|
||||
m_velocity.value.y = 0.0f;
|
||||
}
|
||||
} else {
|
||||
if (m_move_state.up && can_up) {
|
||||
m_y_speed = 7.5;
|
||||
m_velocity.value.y = m_movement.jump_power;
|
||||
can_up = false;
|
||||
}
|
||||
|
||||
m_y_speed += -m_gravity.value * delta_time;
|
||||
m_velocity.value.y += -m_gravity.value * delta_time;
|
||||
}
|
||||
|
||||
move_distance.y = m_y_speed * delta_time;
|
||||
move_distance.y = m_velocity.value.y * delta_time;
|
||||
// y
|
||||
update_y_move(player_pos);
|
||||
// x
|
||||
@@ -416,7 +432,7 @@ void ClientPlayer::update_move(float delta_time) {
|
||||
|
||||
{
|
||||
std::lock_guard lock(m_player_pos_mutex);
|
||||
m_player_pos = player_pos;
|
||||
m_pos.value = player_pos;
|
||||
}
|
||||
update_player_chunk();
|
||||
auto it = m_timers.find("Player Walk Sound");
|
||||
@@ -491,7 +507,7 @@ void ClientPlayer::update_y_move(glm::vec3& player_pos) {
|
||||
AABB block_box = ClientWorld::get_block_aabb(block_pos);
|
||||
if (player_box.intersects(block_box)) {
|
||||
player_pos.y -= move_distance.y;
|
||||
m_y_speed = 0.0f;
|
||||
m_velocity.value.y = 0.0f;
|
||||
if (move_distance.y < 0) {
|
||||
can_up = true;
|
||||
is_fly = false;
|
||||
@@ -541,8 +557,8 @@ void ClientPlayer::update_player_chunk() {
|
||||
float x, z;
|
||||
{
|
||||
std::shared_lock lock(m_player_pos_mutex);
|
||||
x = m_player_pos.x;
|
||||
z = m_player_pos.z;
|
||||
x = m_pos.value.x;
|
||||
z = m_pos.value.z;
|
||||
}
|
||||
ChunkPos chunk_pos = get_chunk_pos(x, z);
|
||||
float dist = distance2(chunk_pos, m_last_chunk_pos);
|
||||
@@ -554,7 +570,7 @@ void ClientPlayer::update_player_chunk() {
|
||||
}
|
||||
|
||||
Gait ClientPlayer::compute_gait() const {
|
||||
if (m_xz_speed < 0.01f)
|
||||
if (m_velocity.value.x < 0.01f && m_velocity.value.z < 0.01f)
|
||||
return Gait::STOP;
|
||||
|
||||
if (m_sprinting)
|
||||
@@ -566,12 +582,12 @@ Gait ClientPlayer::compute_gait() const {
|
||||
bool ClientPlayer::update_scroll(float yoffset) {
|
||||
if (m_game_mode == SPECTATOR) {
|
||||
if (yoffset > 0) {
|
||||
if (m_max_speed < 500.0f) {
|
||||
m_max_speed += 1.0f;
|
||||
if (m_velocity.max.x < 500.0f || m_velocity.max.z < 500.0f) {
|
||||
m_velocity.max += glm::vec3(1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
} else {
|
||||
if (m_max_speed > 1.0f) {
|
||||
m_max_speed -= 1.0f;
|
||||
if (m_velocity.max.x > 1.0f || m_velocity.max.z > 1.0f) {
|
||||
m_velocity.max -= glm::vec3(1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -650,15 +666,11 @@ 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::max_speed() { return m_max_speed; }
|
||||
float& ClientPlayer::acceleration() { return m_movement.acceleration; }
|
||||
float& ClientPlayer::deceleration() { return m_movement.deceleration; }
|
||||
float& ClientPlayer::g() { return m_gravity.value; }
|
||||
float& ClientPlayer::fly_y_speed() { return m_fly_y_speed; }
|
||||
const ItemStack& ClientPlayer::get_current_itemstack() const {
|
||||
return m_hotbar[m_selected_hotbar];
|
||||
};
|
||||
void ClientPlayer::set_gait(Gait gait) { m_walk_pos.gait = gait; }
|
||||
|
||||
GameMode& ClientPlayer::game_mode() { return m_game_mode; }
|
||||
ClientWorld& ClientPlayer::get_world() { return m_world; }
|
||||
|
||||
@@ -692,7 +704,14 @@ void ClientPlayer::init(std::string_view name) {
|
||||
if (!m_moving || is_fly) {
|
||||
return;
|
||||
}
|
||||
glm::ivec3 block = glm::floor(m_player_pos);
|
||||
glm::ivec3 block;
|
||||
glm::vec3 pos;
|
||||
{
|
||||
std::shared_lock lock(m_player_pos_mutex);
|
||||
block = glm::floor(m_pos.value);
|
||||
pos = m_pos.value;
|
||||
}
|
||||
|
||||
block.y -= 1;
|
||||
BlockType id = m_world.get_block_tpye(block);
|
||||
if (id == 0) {
|
||||
@@ -701,7 +720,7 @@ void ClientPlayer::init(std::string_view name) {
|
||||
std::string name = BlockManager::name_form_id(id);
|
||||
std::string sound = "block/" + name + "/walk.ogg";
|
||||
auto& audio = m_world.get_audio();
|
||||
audio.play_3d(sound, m_player_pos);
|
||||
audio.play_3d(sound, pos);
|
||||
Logger::debug("Player block {} walk sound", name);
|
||||
});
|
||||
|
||||
@@ -712,9 +731,4 @@ void ClientPlayer::init(std::string_view name) {
|
||||
|
||||
bool ClientPlayer::is_underwater() const { return m_underwater; }
|
||||
void ClientPlayer::set_underwater(bool u) { m_underwater = u; }
|
||||
|
||||
float ClientPlayer::yaw() const { return m_angle.yaw; }
|
||||
float ClientPlayer::pitch() const { return m_angle.pitch; }
|
||||
float& ClientPlayer::angle() { return m_angle.roll; }
|
||||
float& ClientPlayer::walk_time() { return m_walk_pos.walk_time; }
|
||||
} // namespace Cubed
|
||||
@@ -956,7 +956,7 @@ void ClientWorld::update_players(float dt) {
|
||||
{
|
||||
auto gait = m_player.get_gait();
|
||||
auto& walk_time = m_player.walk_time();
|
||||
auto& angle = m_player.angle();
|
||||
auto& angle = m_player.roll();
|
||||
if (gait == Gait::WALK || gait == Gait::RUN) {
|
||||
|
||||
walk_time += dt;
|
||||
|
||||
14
src/gameplay/entity.cpp
Normal file
14
src/gameplay/entity.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "Cubed/gameplay/entity.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
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; }
|
||||
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; }
|
||||
} // namespace Cubed
|
||||
Reference in New Issue
Block a user