mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(creatures): refine pig movement physics
Add movement constants for pigs and switch deceleration to per-axis friction so creatures stop naturally. Extend wander boost duration for smoother behavior.
This commit is contained in:
@@ -3,4 +3,11 @@
|
||||
namespace Cubed {
|
||||
struct PigTag {};
|
||||
|
||||
namespace PigDefaults {
|
||||
constexpr float MAX_SPEED = 0.1f; // tiles/tick → 2 tiles/sec
|
||||
constexpr float ACCELERATION = 0.01f; // ~10 ticks (0.5s) to reach full speed
|
||||
constexpr float DECELERATION = 0.02f; // ~5 ticks (0.25s) to stop
|
||||
constexpr float GRAVITY = 1.0f; // ≈20 tiles/s², close to the player
|
||||
} // namespace PigDefaults
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/ecs/movement.hpp"
|
||||
#include "Cubed/gameplay/ecs/transform.hpp"
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
namespace Cubed {
|
||||
class ServerWorld;
|
||||
class PhysicalSystem {
|
||||
public:
|
||||
static glm::vec3 get_move_distance(const Direction& d,
|
||||
const TickVelocity& v);
|
||||
static glm::vec3 get_move_distance(const TickVelocity& v);
|
||||
|
||||
static void update(ServerWorld& world, entt::registry& registry);
|
||||
|
||||
|
||||
@@ -20,9 +20,10 @@ void ServerEntityManager::init() {
|
||||
m_factories.try_emplace("cubed:pig", [this]() {
|
||||
BaseServerCreature c;
|
||||
c.hitbox = HitboxManager::instance().get_hitbox_id("cubed:pig");
|
||||
c.gravity.value = 1.0f;
|
||||
c.movement.acceleration = 1.0f;
|
||||
c.movement.deceleration = 1.0f;
|
||||
c.gravity.value = PigDefaults::GRAVITY;
|
||||
c.movement.acceleration = PigDefaults::ACCELERATION;
|
||||
c.movement.deceleration = PigDefaults::DECELERATION;
|
||||
c.velocity.max.x = c.velocity.max.z = PigDefaults::MAX_SPEED;
|
||||
return create_entity_in_factory(
|
||||
Entity{m_next}, EntityInfo{"cubed:pig", ""}, std::move(c), PigTag{},
|
||||
AIBase{}, WanderAITag{}, MoveBoost{});
|
||||
|
||||
@@ -107,8 +107,7 @@ void PhysicalSystem::update(ServerWorld& world, entt::registry& registry) {
|
||||
auto view = registry.view<BaseServerCreature>();
|
||||
for (auto e : view) {
|
||||
auto& creature = view.get<BaseServerCreature>(e);
|
||||
auto distance =
|
||||
get_move_distance(creature.direction, creature.velocity);
|
||||
auto distance = get_move_distance(creature.velocity);
|
||||
auto box = HitboxManager::hitbox(creature.hitbox);
|
||||
auto& pos = creature.transform.position.value;
|
||||
auto& v = creature.velocity;
|
||||
@@ -135,8 +134,7 @@ void PhysicalSystem::update(ServerWorld& world, entt::registry& registry) {
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 PhysicalSystem::get_move_distance(const Direction& d,
|
||||
const TickVelocity& v) {
|
||||
return glm::vec3{d.value.x * v.value.x, v.value.y, d.value.z * v.value.z};
|
||||
glm::vec3 PhysicalSystem::get_move_distance(const TickVelocity& v) {
|
||||
return v.value; // Per-tick forward distance equals the velocity magnitud
|
||||
}
|
||||
} // namespace Cubed
|
||||
@@ -10,31 +10,31 @@ void SpeedSystem::update(float dt, entt::registry& registry) {
|
||||
|
||||
for (auto e : view) {
|
||||
auto [creature, moveboost] = view.get<BaseServerCreature, MoveBoost>(e);
|
||||
auto& v = creature.velocity.value;
|
||||
if (moveboost.count <= moveboost.duration) {
|
||||
++moveboost.count;
|
||||
creature.velocity.value +=
|
||||
creature.direction.value * creature.movement.acceleration;
|
||||
} else if (glm::dot(creature.velocity.value, creature.velocity.value) >=
|
||||
0.001f) {
|
||||
creature.velocity.value -=
|
||||
creature.direction.value * creature.movement.deceleration;
|
||||
v += creature.direction.value * creature.movement.acceleration;
|
||||
} else {
|
||||
creature.velocity.value = glm::vec3(0.0f);
|
||||
// Decelerated by friction in all directions
|
||||
auto decay = [](float& c, float d) {
|
||||
if (c > 0.0f)
|
||||
c = std::max(0.0f, c - d);
|
||||
else if (c < 0.0f)
|
||||
c = std::min(0.0f, c + d);
|
||||
};
|
||||
decay(v.x, creature.movement.deceleration);
|
||||
decay(v.z, creature.movement.deceleration);
|
||||
}
|
||||
creature.velocity.value.y += -creature.gravity.value * dt;
|
||||
auto v_clamp = [](float& v, float max) {
|
||||
v.y += -creature.gravity.value * dt;
|
||||
auto v_clamp = [](float& c, float max) {
|
||||
if (max < 0.0f) {
|
||||
return;
|
||||
}
|
||||
auto sign = v < 0.0f ? -1.0f : 1.0f;
|
||||
v = sign * std::clamp(std::abs(v), 0.0f, max);
|
||||
if (v < 0.0f) {
|
||||
v = 0.0f;
|
||||
return; //-1 = unlimited
|
||||
}
|
||||
c = std::clamp(c, -max, max);
|
||||
};
|
||||
v_clamp(creature.velocity.value.x, creature.velocity.max.x);
|
||||
v_clamp(creature.velocity.value.y, creature.velocity.max.y);
|
||||
v_clamp(creature.velocity.value.z, creature.velocity.max.z);
|
||||
v_clamp(v.x, creature.velocity.max.x);
|
||||
v_clamp(v.y, creature.velocity.max.y);
|
||||
v_clamp(v.z, creature.velocity.max.z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ void WanderAISystem::do_ai(BaseServerCreature& creature,
|
||||
creature.direction.value = r.random_direction_horizontal();
|
||||
}
|
||||
if (r.random_bool(MOVE_PROBABILITY)) {
|
||||
move_boost.duration = r.random_int(5, 8);
|
||||
|
||||
move_boost.duration = r.random_int(20, 40);
|
||||
move_boost.count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user