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:
193
client/World.h
Normal file
193
client/World.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
// Client view of a safari zone: builds the HD-2D diorama from the shared
|
||||
// Zone layout, predicts the local player, interpolates every networked
|
||||
// entity, and turns server events into effects (grass bursts, splashes,
|
||||
// capsule throws, fishing bobbers).
|
||||
|
||||
#include "CharacterSprite.h"
|
||||
#include "Common.h"
|
||||
#include "Movement.h"
|
||||
#include "NetClient.h"
|
||||
#include "Roster.h"
|
||||
#include "Zone.h"
|
||||
|
||||
#include "hd2d/Billboard.h"
|
||||
#include "hd2d/Camera.h"
|
||||
#include "hd2d/DayCycle.h"
|
||||
#include "hd2d/GroundOcclusion.h"
|
||||
#include "hd2d/Model.h"
|
||||
#include "hd2d/Particles.h"
|
||||
#include "hd2d/Scene.h"
|
||||
#include "hd2d/SpriteAtlas.h"
|
||||
#include "hd2d/Terrain.h"
|
||||
#include "hd2d/Water.h"
|
||||
#include "hd2d/Weather.h"
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace bs {
|
||||
|
||||
struct FrameInput {
|
||||
glm::vec2 move{0.0f}; // camera-relative: x = screen right, y = screen up
|
||||
bool run = false;
|
||||
};
|
||||
|
||||
class World {
|
||||
public:
|
||||
bool init(); // static assets (models, textures, character art, roster); once per process
|
||||
bool buildZone(const std::string& id, uint32_t seed);
|
||||
const Zone& zone() const { return zone_; }
|
||||
bool zoneBuilt() const { return built_; }
|
||||
|
||||
// Online: consume snapshots/events and predict the local player.
|
||||
void update(float dt, float time, const FrameInput& in, NetClient& net, const hd2d::Camera& cam);
|
||||
// Offline backdrop (title screen): just animate the scene at a fixed hour.
|
||||
void updateBackdrop(float dt, float time, float hour, Weather w);
|
||||
void reset(); // forget all entities (on disconnect)
|
||||
|
||||
// Gameplay queries for the HUD / input handling.
|
||||
glm::vec3 localPos() const { return localRender_; }
|
||||
float localYaw() const { return predicted_.yaw; }
|
||||
bool localSpawned() const { return localSpawned_; }
|
||||
uint32_t targetCreature() const { return target_; }
|
||||
uint32_t nearbyNpc() const; // Henry when in talking range, else 0
|
||||
bool canFish(glm::vec2& bobber) const;
|
||||
bool lineOut() const; // the local player's fishing line is in the water
|
||||
bool biting() const { return biteTimer_ > 0.0f; }
|
||||
float hour() const { return hour_; }
|
||||
Weather weatherState() const { return weatherState_; }
|
||||
|
||||
// Character preview / creator.
|
||||
const CharacterArt& characterArt() const { return charArt_; }
|
||||
const CharacterManifest& manifest() const { return manifest_; }
|
||||
const Roster& roster() const { return roster_; }
|
||||
|
||||
// Screen-space labels (players, Henry, the targeted creature).
|
||||
struct Label {
|
||||
glm::vec3 world;
|
||||
std::string text;
|
||||
uint32_t accent;
|
||||
bool chat = false;
|
||||
uint32_t entity = 0; // players: App fills the name from NetClient::players
|
||||
};
|
||||
std::vector<Label> labels() const;
|
||||
void showChatBubble(uint32_t entity, const std::string& text);
|
||||
|
||||
hd2d::Scene scene;
|
||||
hd2d::Weather weather;
|
||||
hd2d::DayCycle day;
|
||||
|
||||
private:
|
||||
struct Snap {
|
||||
float tick;
|
||||
EntityState s;
|
||||
};
|
||||
struct Visual {
|
||||
uint32_t id = 0;
|
||||
EntityKind kind = EntityKind::Wild;
|
||||
uint16_t species = 0;
|
||||
uint32_t owner = 0;
|
||||
std::deque<Snap> history;
|
||||
glm::vec3 pos{0.0f}, lastPos{0.0f};
|
||||
float yaw = 0.0f;
|
||||
Anim anim = Anim::Idle;
|
||||
float walkPhase = 0.0f, speed = 0.0f;
|
||||
float flip = 0.0f, flipTarget = 0.0f, turnAnim = 0.0f; // paper-turn when flipping
|
||||
float born = -1.0f, lastSeen = 0.0f, flash = 0.0f, hide = 0.0f;
|
||||
int atlasSlot = -1;
|
||||
std::string chat;
|
||||
float chatAge = 1e9f;
|
||||
};
|
||||
struct PlayerArt {
|
||||
Appearance look;
|
||||
std::unique_ptr<hd2d::BillboardBatch> batch;
|
||||
};
|
||||
struct Capsule {
|
||||
uint32_t thrower = 0, target = 0;
|
||||
glm::vec3 from, to;
|
||||
float start = 0.0f, flight = 0.5f;
|
||||
int result = -1; // -1 pending, 0 fail, 1 success
|
||||
float resultAt = 0.0f;
|
||||
};
|
||||
struct Bobber {
|
||||
uint32_t player = 0;
|
||||
glm::vec3 pos;
|
||||
float bite = -1.0f; // time of the last bite
|
||||
};
|
||||
|
||||
void buildTerrain();
|
||||
void buildProps();
|
||||
void buildDecor();
|
||||
void applySnapshots(NetClient& net);
|
||||
void handleEvent(const GameEvent& e, NetClient& net);
|
||||
void predict(float dt, const FrameInput& in, NetClient& net, const hd2d::Camera& cam);
|
||||
void sampleEntities(float dt);
|
||||
void updateDayWeather(float dt);
|
||||
void updateSprites(float dt, const hd2d::Camera& cam, NetClient* net);
|
||||
void updateLights();
|
||||
int creatureSlot(uint16_t species);
|
||||
hd2d::BillboardBatch* playerBatch(uint32_t entity, const NetClient& net);
|
||||
void drawCharacter(hd2d::BillboardBatch& batch, glm::vec3 pos, float yaw, bool moving, bool running,
|
||||
float phase, const hd2d::Camera& cam, int anchorRow, float alpha = 1.0f);
|
||||
float groundAt(glm::vec2 p) const { return zone_.groundHeight(p); }
|
||||
|
||||
// static assets
|
||||
hd2d::ModelLibrary scenery_, safari_;
|
||||
CharacterManifest manifest_;
|
||||
CharacterArt charArt_;
|
||||
Roster roster_;
|
||||
hd2d::Image henryImage_;
|
||||
bool assetsLoaded_ = false;
|
||||
|
||||
// zone
|
||||
Zone zone_;
|
||||
bool built_ = false;
|
||||
hd2d::Terrain terrain_;
|
||||
hd2d::Water water_;
|
||||
std::unique_ptr<hd2d::ParticleSystem> particles_;
|
||||
hd2d::GroundOcclusion groundAO_;
|
||||
std::map<std::string, std::unique_ptr<hd2d::ModelBatch>> models_;
|
||||
hd2d::BillboardBatch tallGrass_, tufts_, flowers_;
|
||||
std::vector<hd2d::PointLight> lampLights_;
|
||||
|
||||
// entities
|
||||
std::unordered_map<uint32_t, Visual> visuals_;
|
||||
std::unordered_map<uint32_t, PlayerArt> playerArt_;
|
||||
hd2d::BillboardBatch henry_;
|
||||
hd2d::SpriteAtlas creatureAtlas_;
|
||||
hd2d::BillboardBatch creatures_;
|
||||
std::unordered_map<uint16_t, int> speciesSlot_;
|
||||
std::unordered_map<int, float> slotUsed_; // LRU stamp
|
||||
hd2d::SpriteAtlas fxAtlas_;
|
||||
hd2d::BillboardBatch fx_;
|
||||
int fxCapsule_ = -1, fxBobber_ = -1, fxDot_ = -1;
|
||||
std::vector<Capsule> capsules_;
|
||||
std::vector<Bobber> bobbers_;
|
||||
|
||||
// local prediction
|
||||
uint32_t localId_ = 0;
|
||||
bool localSpawned_ = false;
|
||||
MoveState predicted_, prevPredicted_;
|
||||
std::deque<InputCmd> pending_;
|
||||
uint32_t inputSeq_ = 0;
|
||||
float tickAccum_ = 0.0f;
|
||||
glm::vec2 correction_{0.0f};
|
||||
glm::vec3 localRender_{0.0f};
|
||||
float localPhase_ = 0.0f;
|
||||
Anim localServerAnim_ = Anim::Idle;
|
||||
float serverTick_ = 0.0f;
|
||||
bool haveTick_ = false;
|
||||
uint32_t target_ = 0;
|
||||
float biteTimer_ = 0.0f;
|
||||
float stepTimer_ = 0.0f;
|
||||
|
||||
float time_ = 0.0f;
|
||||
float hour_ = 12.0f, hourShown_ = -1.0f;
|
||||
Weather weatherState_ = Weather::Clear;
|
||||
};
|
||||
|
||||
} // namespace bs
|
||||
Reference in New Issue
Block a user