feat(gameplay): implement entity movement system with collision detection

- Add Velocity and HitBoxes components to entity
- Introduce HitboxManager for loading per-entity collision AABBs from JSON
- Create MoveSystem with per-axis collision handling
- Move get_block_aabb to base World class and add virtual get_per_tick_time
- Remove static get_block_aabb from ClientWorld; use member m_per_tick_time for tick duration
This commit is contained in:
2026-07-25 17:47:13 +08:00
parent f9bf2f4b89
commit 930226cc47
11 changed files with 263 additions and 13 deletions

View File

@@ -91,7 +91,7 @@ public:
void request_exit();
bool is_receive_exit();
int chunk_size() const;
static AABB get_block_aabb(const glm::ivec3& pos);
AudioEngine& get_audio();
const AudioEngine& get_audio() const;
Config& get_config();
@@ -103,6 +103,7 @@ public:
void receive_voice_message(VoiceMsg& msg);
bool enable_voice_chat() const;
const entt::registry& get_registry();
int get_per_tick_time() const override;
template <typename Fn>
void register_ticktimer(std::string_view id, TickType threshold, Fn&& f) {
m_ticktimers.emplace(
@@ -181,6 +182,7 @@ private:
std::atomic<int> m_rendering_distance{24};
std::atomic<TickType> m_game_ticks{0};
std::atomic<TickType> m_day_tick{6000};
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME;
std::atomic<bool> m_requesting_chunk{false};
std::atomic<bool> m_is_rebuilding{false};
std::atomic<int> m_chunk_task_id{0};

View File

@@ -1,4 +1,5 @@
#pragma once
#include "Cubed/AABB.hpp"
#include "Cubed/gameplay/player.hpp"
#include <glm/glm.hpp>
@@ -34,4 +35,14 @@ struct ViewAngles {
float angle = 0.0f;
};
struct Velocity {
float dx = 0.0f;
float dy = 0.0f;
float dz = 0.0f;
};
struct HitBoxes {
std::vector<AABB> boxex;
};
} // namespace Cubed

View File

@@ -0,0 +1,24 @@
#pragma once
#include "Cubed/AABB.hpp"
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class HitboxManager {
public:
HitboxManager();
~HitboxManager();
static HitboxManager& instance();
AABB get_aabb(const std::string& key);
static AABB aabb(const std::string& key);
private:
using HitBoxMap = tbb::concurrent_hash_map<std::string, AABB>;
using cacc = HitBoxMap::const_accessor;
using acc = HitBoxMap::accessor;
HitBoxMap m_hitboxes;
AABB load(const std::string& path);
};
} // namespace Cubed

View File

@@ -0,0 +1,20 @@
#pragma once
#include "Cubed/gameplay/entity.hpp"
#include "Cubed/gameplay/world.hpp"
#include <entt/entt.hpp>
namespace Cubed {
class MoveSystem {
public:
static void update(World& world, entt::registry& registry);
private:
static void move_x(World& world, Transform& transform, Velocity& v,
const EntityInfo& info);
static void move_y(World& world, Transform& transform, Velocity& v,
const EntityInfo& info);
static void move_z(World& world, Transform& transform, Velocity& v,
const EntityInfo& info);
};
} // namespace Cubed

View File

@@ -91,7 +91,7 @@ public:
bool is_solid(const glm::ivec3& block_pos) const override;
bool can_pass_block(const glm::ivec3& block_pos) const override;
BlockType get_block_tpye(const glm::ivec3& block_pos) const override;
int get_per_tick_time() const override;
template <typename Fn>
void register_timer(std::string_view id, TickType threshold, Fn&& f) {
m_timers.emplace(std::piecewise_construct,

View File

@@ -1,4 +1,5 @@
#pragma once
#include "Cubed/AABB.hpp"
#include "Cubed/gameplay/block.hpp"
#include <glm/glm.hpp>
@@ -16,5 +17,13 @@ public:
virtual bool is_solid(const glm::ivec3& block_pos) const = 0;
virtual bool can_pass_block(const glm::ivec3& block_pos) const = 0;
virtual BlockType get_block_tpye(const glm::ivec3& block_pos) const = 0;
virtual int get_per_tick_time() const = 0;
static AABB get_block_aabb(const glm::ivec3& pos) {
return {glm::vec3{static_cast<float>(pos.x) + 0.5f,
static_cast<float>(pos.y) + 0.5f,
static_cast<float>(pos.z) + 0.5f},
glm::vec3{0.5f, 0.5f, 0.5f}};
}
};
} // namespace Cubed