mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
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.
This commit is contained in:
17
include/Cubed/gameplay/ecs/ai_struct.hpp
Normal file
17
include/Cubed/gameplay/ecs/ai_struct.hpp
Normal file
@@ -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
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Cubed/gameplay/ecs/health.hpp"
|
#include "Cubed/gameplay/ecs/health.hpp"
|
||||||
#include "Cubed/gameplay/ecs/movement.hpp"
|
#include "Cubed/gameplay/ecs/movement.hpp"
|
||||||
#include "Cubed/gameplay/ecs/state.hpp"
|
|
||||||
#include "Cubed/gameplay/ecs/transform.hpp"
|
#include "Cubed/gameplay/ecs/transform.hpp"
|
||||||
#include "Cubed/gameplay/hitbox.hpp"
|
#include "Cubed/gameplay/hitbox.hpp"
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
@@ -13,8 +12,6 @@ struct BaseServerCreature {
|
|||||||
|
|
||||||
Movement movement{};
|
Movement movement{};
|
||||||
|
|
||||||
MoveState move_state{};
|
|
||||||
|
|
||||||
Direction direction{};
|
Direction direction{};
|
||||||
|
|
||||||
Gravity gravity{};
|
Gravity gravity{};
|
||||||
|
|||||||
14
include/Cubed/gameplay/systems/wander_ai_system.hpp
Normal file
14
include/Cubed/gameplay/systems/wander_ai_system.hpp
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Cubed/gameplay/ecs/ai_struct.hpp"
|
||||||
|
#include "Cubed/gameplay/ecs/server_entity.hpp"
|
||||||
|
|
||||||
|
#include <entt/entt.hpp>
|
||||||
|
namespace Cubed {
|
||||||
|
class WanderAISystem {
|
||||||
|
public:
|
||||||
|
static void update(entt::registry& registry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void do_ai(BaseServerCreature& creature, MoveBoost& move_boost);
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "glm/ext/vector_float3.hpp"
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
@@ -14,6 +16,8 @@ public:
|
|||||||
int random_int(int min, int max);
|
int random_int(int min, int max);
|
||||||
float random_float(float min, float max);
|
float random_float(float min, float max);
|
||||||
|
|
||||||
|
glm::vec3 random_direction_horizontal();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int m_seed = 0;
|
unsigned int m_seed = 0;
|
||||||
std::mt19937 m_engine;
|
std::mt19937 m_engine;
|
||||||
|
|||||||
@@ -102,4 +102,5 @@ target_sources(${PROJECT_NAME}
|
|||||||
gameplay/client_player_manager.cpp
|
gameplay/client_player_manager.cpp
|
||||||
gameplay/server_entity_manager.cpp
|
gameplay/server_entity_manager.cpp
|
||||||
gameplay/client_entity_manager.cpp
|
gameplay/client_entity_manager.cpp
|
||||||
|
gameplay/systems/wander_ai_system.cpp
|
||||||
)
|
)
|
||||||
40
src/gameplay/systems/wander_ai_system.cpp
Normal file
40
src/gameplay/systems/wander_ai_system.cpp
Normal file
@@ -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<AIBase, WanderAITag, BaseServerCreature, MoveBoost>();
|
||||||
|
|
||||||
|
for (auto e : view) {
|
||||||
|
auto [ai, creature, move_boost] =
|
||||||
|
view.get<AIBase, BaseServerCreature, MoveBoost>(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
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
#include "Cubed/tools/cubed_random.hpp"
|
#include "Cubed/tools/cubed_random.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <numbers>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
Random::Random() {}
|
Random::Random() {}
|
||||||
|
|
||||||
Random::Random(unsigned seed) { init(seed); }
|
Random::Random(unsigned seed) { init(seed); }
|
||||||
bool Random::random_bool(double probability) {
|
bool Random::random_bool(double probability) {
|
||||||
if (probability <= 0.0)
|
if (probability <= 0.0)
|
||||||
@@ -44,4 +47,12 @@ float Random::random_float(float min, float max) {
|
|||||||
|
|
||||||
return result;
|
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
|
} // namespace Cubed
|
||||||
Reference in New Issue
Block a user