From 412f88565ac5a6f624657ee12419b06ef8c62377 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Fri, 31 Jul 2026 19:59:33 +0800 Subject: [PATCH] feat(ai): add wander AI system with move boost Add AIBase and WanderAITag components, a WanderAISystem, and a MoveBoost component to control wandering behavior. Replace the old MoveState with MoveBoost and include a horizontal random direction helper. --- include/Cubed/gameplay/ecs/ai_struct.hpp | 17 ++++++++ include/Cubed/gameplay/ecs/server_entity.hpp | 3 -- .../gameplay/systems/wander_ai_system.hpp | 14 +++++++ include/Cubed/tools/cubed_random.hpp | 4 ++ src/CMakeLists.txt | 1 + src/gameplay/systems/wander_ai_system.cpp | 40 +++++++++++++++++++ src/tools/cubed_random.cpp | 11 +++++ 7 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 include/Cubed/gameplay/ecs/ai_struct.hpp create mode 100644 include/Cubed/gameplay/systems/wander_ai_system.hpp create mode 100644 src/gameplay/systems/wander_ai_system.cpp diff --git a/include/Cubed/gameplay/ecs/ai_struct.hpp b/include/Cubed/gameplay/ecs/ai_struct.hpp new file mode 100644 index 0000000..c9715d8 --- /dev/null +++ b/include/Cubed/gameplay/ecs/ai_struct.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "Cubed/gameplay/game_time.hpp" +namespace Cubed { +struct AIBase { + TickType interval = 1; + TickType count = 0; +}; + +struct WanderAITag {}; + +struct MoveBoost { + TickType duration = 0; + TickType count = 0; +}; + +} // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/gameplay/ecs/server_entity.hpp b/include/Cubed/gameplay/ecs/server_entity.hpp index e2ef45c..eb6f7e8 100644 --- a/include/Cubed/gameplay/ecs/server_entity.hpp +++ b/include/Cubed/gameplay/ecs/server_entity.hpp @@ -1,7 +1,6 @@ #pragma once #include "Cubed/gameplay/ecs/health.hpp" #include "Cubed/gameplay/ecs/movement.hpp" -#include "Cubed/gameplay/ecs/state.hpp" #include "Cubed/gameplay/ecs/transform.hpp" #include "Cubed/gameplay/hitbox.hpp" namespace Cubed { @@ -13,8 +12,6 @@ struct BaseServerCreature { Movement movement{}; - MoveState move_state{}; - Direction direction{}; Gravity gravity{}; diff --git a/include/Cubed/gameplay/systems/wander_ai_system.hpp b/include/Cubed/gameplay/systems/wander_ai_system.hpp new file mode 100644 index 0000000..934a62a --- /dev/null +++ b/include/Cubed/gameplay/systems/wander_ai_system.hpp @@ -0,0 +1,14 @@ +#pragma once +#include "Cubed/gameplay/ecs/ai_struct.hpp" +#include "Cubed/gameplay/ecs/server_entity.hpp" + +#include +namespace Cubed { +class WanderAISystem { +public: + static void update(entt::registry& registry); + +private: + static void do_ai(BaseServerCreature& creature, MoveBoost& move_boost); +}; +} // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/tools/cubed_random.hpp b/include/Cubed/tools/cubed_random.hpp index 8e13065..7553dba 100644 --- a/include/Cubed/tools/cubed_random.hpp +++ b/include/Cubed/tools/cubed_random.hpp @@ -1,4 +1,6 @@ #pragma once +#include "glm/ext/vector_float3.hpp" + #include namespace Cubed { @@ -14,6 +16,8 @@ public: int random_int(int min, int max); float random_float(float min, float max); + glm::vec3 random_direction_horizontal(); + private: unsigned int m_seed = 0; std::mt19937 m_engine; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed7d286..6427fe9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,4 +102,5 @@ target_sources(${PROJECT_NAME} gameplay/client_player_manager.cpp gameplay/server_entity_manager.cpp gameplay/client_entity_manager.cpp + gameplay/systems/wander_ai_system.cpp ) \ No newline at end of file diff --git a/src/gameplay/systems/wander_ai_system.cpp b/src/gameplay/systems/wander_ai_system.cpp new file mode 100644 index 0000000..31e75d0 --- /dev/null +++ b/src/gameplay/systems/wander_ai_system.cpp @@ -0,0 +1,40 @@ +#include "Cubed/gameplay/systems/wander_ai_system.hpp" + +#include "Cubed/gameplay/ecs/ai_struct.hpp" +#include "Cubed/gameplay/ecs/server_entity.hpp" +#include "Cubed/tools/cubed_random.hpp" + +namespace { +constexpr double DIRECTION_PROBABILITY = 0.1; +constexpr double MOVE_PROBABILITY = 0.1; +} // namespace + +namespace Cubed { +void WanderAISystem::update(entt::registry& registry) { + auto view = + registry.view(); + + for (auto e : view) { + auto [ai, creature, move_boost] = + view.get(e); + ++ai.count; + if (ai.count >= ai.interval) { + ai.count = 0; + do_ai(creature, move_boost); + } + } +} + +void WanderAISystem::do_ai(BaseServerCreature& creature, + MoveBoost& move_boost) { + thread_local Random r{std::random_device()()}; + if (r.random_bool(DIRECTION_PROBABILITY)) { + creature.direction.value = r.random_direction_horizontal(); + } + if (r.random_bool(MOVE_PROBABILITY)) { + move_boost.duration = r.random_int(5, 8); + move_boost.count = 0; + } +} + +} // namespace Cubed \ No newline at end of file diff --git a/src/tools/cubed_random.cpp b/src/tools/cubed_random.cpp index 701a521..9f50864 100644 --- a/src/tools/cubed_random.cpp +++ b/src/tools/cubed_random.cpp @@ -1,8 +1,11 @@ #include "Cubed/tools/cubed_random.hpp" +#include +#include namespace Cubed { Random::Random() {} + Random::Random(unsigned seed) { init(seed); } bool Random::random_bool(double probability) { if (probability <= 0.0) @@ -44,4 +47,12 @@ float Random::random_float(float min, float max) { return result; } + +glm::vec3 Random::random_direction_horizontal() { + float x = std::cos(random_float(0.0f, 2 * std::numbers::pi)); + float z = std::sin(random_float(0.0f, 2 * std::numbers::pi)); + + return glm::vec3{x, 0.0f, z}; +} + } // namespace Cubed \ No newline at end of file