mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
3 Commits
a54858e4c6
...
6b1f9d7354
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b1f9d7354 | |||
| 5980400e2e | |||
| 9bb1882d92 |
@@ -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);
|
||||
|
||||
|
||||
@@ -86,15 +86,19 @@ HitboxManager::Handle HitboxManager::load(std::string_view name) {
|
||||
std::ifstream s{p};
|
||||
json j = json::parse(s);
|
||||
if (j.contains("boxes")) {
|
||||
if (j["boxes"].contains("center")) {
|
||||
center.x = j["boxes"]["center"].at(0).get<float>();
|
||||
center.y = j["boxes"]["center"].at(1).get<float>();
|
||||
center.z = j["boxes"]["center"].at(2).get<float>();
|
||||
const json* box = &j["boxes"];
|
||||
if (box->is_array() && !box->empty()) {
|
||||
box = &(*box)[0];
|
||||
}
|
||||
if (j["boxes"].contains("half")) {
|
||||
half.x = j["boxes"]["half"].at(0).get<float>();
|
||||
half.y = j["boxes"]["half"].at(1).get<float>();
|
||||
half.z = j["boxes"]["half"].at(2).get<float>();
|
||||
if (box->contains("center")) {
|
||||
center.x = (*box)["center"].at(0).get<float>();
|
||||
center.y = (*box)["center"].at(1).get<float>();
|
||||
center.z = (*box)["center"].at(2).get<float>();
|
||||
}
|
||||
if (box->contains("half")) {
|
||||
half.x = (*box)["half"].at(0).get<float>();
|
||||
half.y = (*box)["half"].at(1).get<float>();
|
||||
half.z = (*box)["half"].at(2).get<float>();
|
||||
}
|
||||
}
|
||||
{
|
||||
|
||||
@@ -20,6 +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 = 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{});
|
||||
|
||||
@@ -179,7 +179,7 @@ void ServerWorld::send_chunk(int task_id, const std::string& uuid,
|
||||
void ServerWorld::init_world() {
|
||||
|
||||
m_entity_manager.init();
|
||||
m_entity_manager.add_entity("cubed:pig", {0, 90, 0});
|
||||
m_entity_manager.add_entity("cubed:pig", {0, 225, 0});
|
||||
register_timer("player disconnect", 5, [this]() {
|
||||
std::vector<std::string> disconnect;
|
||||
{
|
||||
|
||||
@@ -107,36 +107,61 @@ 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;
|
||||
if (update_x(pos, distance, world, box.box)) {
|
||||
pos.x += distance.x;
|
||||
|
||||
} else {
|
||||
v.value.x = 0.0f;
|
||||
}
|
||||
|
||||
bool ground =
|
||||
!update_y(pos, glm::vec3{0.0f, -0.1f, 0.0f}, world, box.box);
|
||||
bool stepped = false;
|
||||
if (update_y(pos, distance, world, box.box)) {
|
||||
pos.y += distance.y;
|
||||
|
||||
} else {
|
||||
v.value.y = 0.0f;
|
||||
}
|
||||
if (update_x(pos, distance, world, box.box)) {
|
||||
pos.x += distance.x;
|
||||
|
||||
} else {
|
||||
if (ground && !stepped) {
|
||||
|
||||
glm::vec3 step_pos = pos + glm::vec3{0.0f, 1.0f, 0.0f};
|
||||
if (update_x(step_pos, distance, world, box.box)) {
|
||||
pos.x += distance.x;
|
||||
pos.y += 1.0f;
|
||||
stepped = true;
|
||||
} else {
|
||||
v.value.x = 0.0f;
|
||||
}
|
||||
} else {
|
||||
v.value.x = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_z(pos, distance, world, box.box)) {
|
||||
pos.z += distance.z;
|
||||
|
||||
} else {
|
||||
v.value.z = 0.0f;
|
||||
if (ground && !stepped) {
|
||||
|
||||
glm::vec3 step_pos = pos + glm::vec3{0.0f, 1.0f, 0.0f};
|
||||
if (update_z(step_pos, distance, world, box.box)) {
|
||||
pos.z += distance.z;
|
||||
pos.y += 1.0f;
|
||||
stepped = true;
|
||||
|
||||
} else {
|
||||
v.value.z = 0.0f;
|
||||
}
|
||||
} else {
|
||||
v.value.z = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,28 +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) {
|
||||
auto temp = std::abs(v);
|
||||
max = std::abs(max);
|
||||
temp = std::clamp(temp, 0.0f, max);
|
||||
|
||||
v = temp;
|
||||
v.y += -creature.gravity.value * dt;
|
||||
auto v_clamp = [](float& c, float max) {
|
||||
if (max < 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
|
||||
namespace {
|
||||
constexpr double DIRECTION_PROBABILITY = 0.1;
|
||||
constexpr double MOVE_PROBABILITY = 0.1;
|
||||
constexpr double DIRECTION_PROBABILITY = 0.01;
|
||||
constexpr double MOVE_PROBABILITY = 0.01;
|
||||
} // namespace
|
||||
|
||||
namespace Cubed {
|
||||
@@ -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