mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +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 {
|
namespace Cubed {
|
||||||
struct PigTag {};
|
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
|
} // namespace Cubed
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Cubed/gameplay/ecs/movement.hpp"
|
#include "Cubed/gameplay/ecs/movement.hpp"
|
||||||
#include "Cubed/gameplay/ecs/transform.hpp"
|
|
||||||
|
|
||||||
#include <entt/entt.hpp>
|
#include <entt/entt.hpp>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
class ServerWorld;
|
class ServerWorld;
|
||||||
class PhysicalSystem {
|
class PhysicalSystem {
|
||||||
public:
|
public:
|
||||||
static glm::vec3 get_move_distance(const Direction& d,
|
static glm::vec3 get_move_distance(const TickVelocity& v);
|
||||||
const TickVelocity& v);
|
|
||||||
|
|
||||||
static void update(ServerWorld& world, entt::registry& registry);
|
static void update(ServerWorld& world, entt::registry& registry);
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ void ServerEntityManager::init() {
|
|||||||
m_factories.try_emplace("cubed:pig", [this]() {
|
m_factories.try_emplace("cubed:pig", [this]() {
|
||||||
BaseServerCreature c;
|
BaseServerCreature c;
|
||||||
c.hitbox = HitboxManager::instance().get_hitbox_id("cubed:pig");
|
c.hitbox = HitboxManager::instance().get_hitbox_id("cubed:pig");
|
||||||
c.gravity.value = 1.0f;
|
c.gravity.value = PigDefaults::GRAVITY;
|
||||||
c.movement.acceleration = 1.0f;
|
c.movement.acceleration = PigDefaults::ACCELERATION;
|
||||||
c.movement.deceleration = 1.0f;
|
c.movement.deceleration = PigDefaults::DECELERATION;
|
||||||
|
c.velocity.max.x = c.velocity.max.z = PigDefaults::MAX_SPEED;
|
||||||
return create_entity_in_factory(
|
return create_entity_in_factory(
|
||||||
Entity{m_next}, EntityInfo{"cubed:pig", ""}, std::move(c), PigTag{},
|
Entity{m_next}, EntityInfo{"cubed:pig", ""}, std::move(c), PigTag{},
|
||||||
AIBase{}, WanderAITag{}, MoveBoost{});
|
AIBase{}, WanderAITag{}, MoveBoost{});
|
||||||
|
|||||||
@@ -107,8 +107,7 @@ void PhysicalSystem::update(ServerWorld& world, entt::registry& registry) {
|
|||||||
auto view = registry.view<BaseServerCreature>();
|
auto view = registry.view<BaseServerCreature>();
|
||||||
for (auto e : view) {
|
for (auto e : view) {
|
||||||
auto& creature = view.get<BaseServerCreature>(e);
|
auto& creature = view.get<BaseServerCreature>(e);
|
||||||
auto distance =
|
auto distance = get_move_distance(creature.velocity);
|
||||||
get_move_distance(creature.direction, creature.velocity);
|
|
||||||
auto box = HitboxManager::hitbox(creature.hitbox);
|
auto box = HitboxManager::hitbox(creature.hitbox);
|
||||||
auto& pos = creature.transform.position.value;
|
auto& pos = creature.transform.position.value;
|
||||||
auto& v = creature.velocity;
|
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,
|
glm::vec3 PhysicalSystem::get_move_distance(const TickVelocity& v) {
|
||||||
const TickVelocity& v) {
|
return v.value; // Per-tick forward distance equals the velocity magnitud
|
||||||
return glm::vec3{d.value.x * v.value.x, v.value.y, d.value.z * v.value.z};
|
|
||||||
}
|
}
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -10,31 +10,31 @@ void SpeedSystem::update(float dt, entt::registry& registry) {
|
|||||||
|
|
||||||
for (auto e : view) {
|
for (auto e : view) {
|
||||||
auto [creature, moveboost] = view.get<BaseServerCreature, MoveBoost>(e);
|
auto [creature, moveboost] = view.get<BaseServerCreature, MoveBoost>(e);
|
||||||
|
auto& v = creature.velocity.value;
|
||||||
if (moveboost.count <= moveboost.duration) {
|
if (moveboost.count <= moveboost.duration) {
|
||||||
++moveboost.count;
|
++moveboost.count;
|
||||||
creature.velocity.value +=
|
v += creature.direction.value * creature.movement.acceleration;
|
||||||
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;
|
|
||||||
} else {
|
} 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;
|
v.y += -creature.gravity.value * dt;
|
||||||
auto v_clamp = [](float& v, float max) {
|
auto v_clamp = [](float& c, float max) {
|
||||||
if (max < 0.0f) {
|
if (max < 0.0f) {
|
||||||
return;
|
return; //-1 = unlimited
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
c = std::clamp(c, -max, max);
|
||||||
};
|
};
|
||||||
v_clamp(creature.velocity.value.x, creature.velocity.max.x);
|
v_clamp(v.x, creature.velocity.max.x);
|
||||||
v_clamp(creature.velocity.value.y, creature.velocity.max.y);
|
v_clamp(v.y, creature.velocity.max.y);
|
||||||
v_clamp(creature.velocity.value.z, creature.velocity.max.z);
|
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();
|
creature.direction.value = r.random_direction_horizontal();
|
||||||
}
|
}
|
||||||
if (r.random_bool(MOVE_PROBABILITY)) {
|
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;
|
move_boost.count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user