Brandling Safari: LAN safari-zone creature catching on the HD-2D engine
- Authoritative 30 Hz server (ENet, SQLite): accounts, characters, wild AI, tall grass / water / wandering spawns, fishing, captures, follower chains, clock + weather, LAN beacon - Client: title / join / character creator / play screens, prediction + reconciliation, interpolated players and parties, HD-2D UI (dialogue with Professor Henry, HUD, collection) - Shared deterministic zone generator, movement, protocol, roster, appearance - Paper-doll character art pipeline (PixelLab base walk + per-item animation edits) - Brandling roster from the company list (logo colors, jev types), Blender safari props - Headless test bot
This commit is contained in:
49
shared/Movement.h
Normal file
49
shared/Movement.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
// Player movement, run identically by the server (authoritative) and the
|
||||
// client (prediction + reconciliation). Pure function of state + input.
|
||||
|
||||
#include "Protocol.h"
|
||||
#include "Zone.h"
|
||||
|
||||
namespace bs {
|
||||
|
||||
constexpr float kWalkSpeed = 4.0f; // world units / second
|
||||
constexpr float kRunSpeed = 6.6f;
|
||||
|
||||
struct MoveState {
|
||||
glm::vec2 pos{0.0f};
|
||||
float yaw = 0.0f;
|
||||
bool moving = false;
|
||||
bool running = false;
|
||||
};
|
||||
|
||||
inline void stepMovement(const Zone& zone, MoveState& s, const InputCmd& in, float dt) {
|
||||
glm::vec2 dir = in.move();
|
||||
float amount = std::min(glm::length(dir), 1.0f);
|
||||
s.moving = amount > 0.05f;
|
||||
s.running = s.moving && in.run();
|
||||
if (!s.moving) return;
|
||||
dir = glm::normalize(dir) * amount;
|
||||
s.yaw = yawFromDir(dir);
|
||||
glm::vec2 step = dir * (s.running ? kRunSpeed : kWalkSpeed) * dt;
|
||||
// Axis-separated resolution slides along obstacles.
|
||||
glm::vec2 p = s.pos;
|
||||
if (zone.walkable(p, p + glm::vec2(step.x, 0.0f))) p.x += step.x;
|
||||
if (zone.walkable(p, p + glm::vec2(0.0f, step.y))) p.y += step.y;
|
||||
s.pos = p;
|
||||
}
|
||||
|
||||
// Quantizes a world direction exactly like the network does, so prediction
|
||||
// uses the same input the server will see.
|
||||
inline InputCmd makeInput(uint32_t seq, glm::vec2 worldDir, bool run) {
|
||||
InputCmd c;
|
||||
c.seq = seq;
|
||||
float len = glm::length(worldDir);
|
||||
if (len > 1.0f) worldDir /= len;
|
||||
c.moveX = int8_t(std::lround(glm::clamp(worldDir.x, -1.0f, 1.0f) * 127.0f));
|
||||
c.moveZ = int8_t(std::lround(glm::clamp(worldDir.y, -1.0f, 1.0f) * 127.0f));
|
||||
c.flags = run ? 1 : 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace bs
|
||||
Reference in New Issue
Block a user