From 5980400e2e1764eea355a274ca9c1121bc227d92 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sun, 2 Aug 2026 16:36:56 +0800 Subject: [PATCH] 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. --- include/Cubed/gameplay/creatures/pig.hpp | 7 ++++ .../gameplay/systems/physical_system.hpp | 4 +-- src/gameplay/server_entity_manager.cpp | 7 ++-- src/gameplay/systems/physical_system.cpp | 8 ++--- src/gameplay/systems/speed_system.cpp | 36 +++++++++---------- src/gameplay/systems/wander_ai_system.cpp | 3 +- 6 files changed, 35 insertions(+), 30 deletions(-) diff --git a/include/Cubed/gameplay/creatures/pig.hpp b/include/Cubed/gameplay/creatures/pig.hpp index cf2e83d..fd0f8ce 100644 --- a/include/Cubed/gameplay/creatures/pig.hpp +++ b/include/Cubed/gameplay/creatures/pig.hpp @@ -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 \ No newline at end of file diff --git a/include/Cubed/gameplay/systems/physical_system.hpp b/include/Cubed/gameplay/systems/physical_system.hpp index 7c121c7..f2e1dfd 100644 --- a/include/Cubed/gameplay/systems/physical_system.hpp +++ b/include/Cubed/gameplay/systems/physical_system.hpp @@ -1,14 +1,12 @@ #pragma once #include "Cubed/gameplay/ecs/movement.hpp" -#include "Cubed/gameplay/ecs/transform.hpp" #include 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); diff --git a/src/gameplay/server_entity_manager.cpp b/src/gameplay/server_entity_manager.cpp index 6f6930d..22a0dce 100644 --- a/src/gameplay/server_entity_manager.cpp +++ b/src/gameplay/server_entity_manager.cpp @@ -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{}); diff --git a/src/gameplay/systems/physical_system.cpp b/src/gameplay/systems/physical_system.cpp index 8d35e02..bd4a4db 100644 --- a/src/gameplay/systems/physical_system.cpp +++ b/src/gameplay/systems/physical_system.cpp @@ -107,8 +107,7 @@ void PhysicalSystem::update(ServerWorld& world, entt::registry& registry) { auto view = registry.view(); for (auto e : view) { auto& creature = view.get(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 \ No newline at end of file diff --git a/src/gameplay/systems/speed_system.cpp b/src/gameplay/systems/speed_system.cpp index 119c485..7b25f6c 100644 --- a/src/gameplay/systems/speed_system.cpp +++ b/src/gameplay/systems/speed_system.cpp @@ -10,31 +10,31 @@ void SpeedSystem::update(float dt, entt::registry& registry) { for (auto e : view) { auto [creature, moveboost] = view.get(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); } } diff --git a/src/gameplay/systems/wander_ai_system.cpp b/src/gameplay/systems/wander_ai_system.cpp index 8ff646d..d2aefd3 100644 --- a/src/gameplay/systems/wander_ai_system.cpp +++ b/src/gameplay/systems/wander_ai_system.cpp @@ -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; } }