载入中...
搜索中...
未找到
CrowdBindings.cpp
浏览该文件的文档.
3
4#include <simplesquirrel/simplesquirrel.hpp>
5
6namespace eve::crowd {
7namespace {
8Result<SpawnBatch> readSpawnBatch(ssq::Array agents, ssq::Table options) {
9 try {
10 if (agents.size() > 1024)
12 DiagnosticCode::InvalidArgument, "Spawn batches support at most 1024 agents", "agents"));
13 SpawnBatch batch;
14 const auto mode = options.get<std::string>("policy");
15 if (mode == "reject")
16 batch.policy = SpawnPolicy::RejectOverlap;
17 else if (mode == "nearestFree")
18 batch.policy = SpawnPolicy::NearestFree;
19 else if (mode == "pushNeighbors")
20 batch.policy = SpawnPolicy::PushNeighbors;
21 else
23 Diagnostic::error(DiagnosticCode::InvalidArgument, "Unknown spawn policy", "policy"));
24 batch.maxDistance = options.get<float>("maxDistance");
25 batch.searchSpacing = options.get<float>("searchSpacing");
26 batch.maxPasses = options.get<int>("maxPasses");
27 batch.maxChecks = options.get<int>("maxChecks");
28 for (size_t i = 0; i < agents.size(); ++i) {
29 auto item = agents.get<ssq::Table>(i);
30 SpawnRequest request;
31 request.stableId = item.get<std::string>("stableId");
32 request.x = item.get<float>("x");
33 request.y = item.get<float>("y");
34 request.heading = item.get<float>("heading");
35 request.radius = item.get<float>("radius");
36 request.interaction = {item.get<float>("pushability"), item.get<bool>("holdPosition"),
37 item.get<int>("layer"), item.get<int>("mask")};
38 batch.agents.push_back(std::move(request));
39 }
40 return Result<SpawnBatch>::success(std::move(batch));
41 } catch (const std::exception &error) {
44 }
45}
46} // namespace
47
48// --- 脚本绑定 ---
49
50void Crowd::expose(ssq::Table &table) {
51 auto cls = table.addClass(name, Crowd::create, false);
52 expose(cls);
53
54 auto state = table.addClass<AgentState>("CrowdAgentState", ssq::Class::Ctor<AgentState()>());
55 state.addVar("x", &AgentState::x);
56 state.addVar("y", &AgentState::y);
57 state.addVar("heading", &AgentState::heading);
58 state.addVar("speed", &AgentState::speed);
59 state.addVar("vx", &AgentState::vx);
60 state.addVar("vy", &AgentState::vy);
61 state.addVar("action", &AgentState::action);
62 state.addVar("data", &AgentState::data);
63 state.addVar("avoidancePriority", &AgentState::avoidancePriority);
64
65 auto flow = table.addClass<FlowVec>("CrowdFlowVec", ssq::Class::Ctor<FlowVec()>());
66 flow.addVar("x", &FlowVec::x);
67 flow.addVar("y", &FlowVec::y);
68}
69
70void Crowd::expose(ssq::Class &cls) {
71 cls.addFunc("getName", &Crowd::getName);
72
73 // 流场
74 cls.addFunc("resizeField", &Crowd::resizeField);
75 cls.addFunc("setBlocked", &Crowd::setBlocked);
76 cls.addFunc("setCellCost", &Crowd::setCellCost);
77 cls.addFunc("getCellCost", &Crowd::getCellCost);
78 cls.addFunc("buildFlowField", &Crowd::buildFlowField);
79 cls.addFunc("addFlowGoal", &Crowd::addFlowGoal);
80 cls.addFunc("clearFlowGoals", &Crowd::clearFlowGoals);
81 cls.addFunc("build", &Crowd::build);
82 cls.addFunc("isFieldBuilt", &Crowd::isFieldBuilt);
83 cls.addFunc("isReachable", &Crowd::isReachable);
84 cls.addFunc("getFieldWidth", &Crowd::getFieldWidth);
85 cls.addFunc("getFieldHeight", &Crowd::getFieldHeight);
86 cls.addFunc("getCellSize", &Crowd::getCellSize);
87 cls.addFunc("getFieldOriginX", &Crowd::getFieldOriginX);
88 cls.addFunc("getFieldOriginY", &Crowd::getFieldOriginY);
89 cls.addFunc("flowAtWorld", &Crowd::flowAtWorld);
90 cls.addFunc("costAtWorld", &Crowd::costAtWorld);
91 cls.addFunc("flowAtCell", &Crowd::flowAtCell);
92
93 // 单位
94 cls.addFunc("addAgent", &Crowd::addAgent);
95 cls.addFunc("addNamedAgent", &Crowd::addNamedAgent);
96 cls.addFunc("hasNamedAgent", &Crowd::hasNamedAgent);
97 cls.addFunc("getNamedAgentIndex", &Crowd::getNamedAgentIndex);
98 cls.addFunc("getAgentStableId", &Crowd::getAgentStableId);
99 cls.addFunc("removeNamedAgent", &Crowd::removeNamedAgent);
100 cls.addFunc("removeAgent", &Crowd::removeAgent);
101 cls.addFunc("clearAgents", &Crowd::clearAgents);
102 cls.addFunc("getAgentCount", &Crowd::getAgentCount);
103 cls.addFunc("setMaxAgents", &Crowd::setMaxAgents);
104 cls.addFunc("getMaxAgents", &Crowd::getMaxAgents);
105 cls.addFunc("setAgentAction", &Crowd::setAgentAction);
106 cls.addFunc("getAgentAction", &Crowd::getAgentAction);
107 cls.addFunc("setAgentTarget", &Crowd::setAgentTarget);
108 cls.addFunc("clearAgentTarget", &Crowd::clearAgentTarget);
109 cls.addFunc("setAgentSpeed", &Crowd::setAgentSpeed);
110 cls.addFunc("setAgentAccel", &Crowd::setAgentAccel);
111 cls.addFunc("setAgentTurnRate", &Crowd::setAgentTurnRate);
112 cls.addFunc("setAgentRadius", &Crowd::setAgentRadius);
113 cls.addFunc("setAgentData", &Crowd::setAgentData);
114 cls.addFunc("getAgentData", &Crowd::getAgentData);
115 cls.addFunc("setAgentAvoidancePriority",
116 [](Crowd *crowd, int id, int priority) { return crowd->setAgentAvoidancePriority(id, priority).ok(); });
117 cls.addFunc("getAgentAvoidancePriority", &Crowd::getAgentAvoidancePriority);
118 cls.addFunc("setAgentInteraction", [vm = cls.getHandle()](Crowd *crowd, int id, float pushability,
119 bool holdPosition, int layer, int mask) {
120 return script::projectResult(vm, crowd->setAgentInteraction(id, {pushability, holdPosition, layer, mask}));
121 });
122 cls.addFunc("getAgentInteraction", [vm = cls.getHandle()](Crowd *crowd, int id) {
123 return script::projectResult(vm, crowd->getAgentInteraction(id), [](AgentInteraction policy) {
124 return Value(Value::Object{{"pushability", Value(policy.pushability)},
125 {"holdPosition", Value(policy.holdPosition)},
126 {"layer", Value(policy.layer)},
127 {"mask", Value(policy.mask)}});
128 });
129 });
130 cls.addFunc("setAgentPosition", &Crowd::setAgentPosition);
131 cls.addFunc("applySpawnBatch", [vm = cls.getHandle()](Crowd *crowd, ssq::Array agents, ssq::Table options) {
132 auto batch = readSpawnBatch(std::move(agents), std::move(options));
133 const auto project = [](const SpawnReceipt &receipt) {
135 for (const auto &item : receipt.created)
136 created.emplace_back(
137 Value::Object{{"stableId", Value(item.stableId)}, {"x", Value(item.x)}, {"y", Value(item.y)}});
138 return Value(Value::Object{{"created", Value(std::move(created))},
139 {"displacedAgents", Value(receipt.displacedAgents)},
140 {"checks", Value(receipt.checks)}});
141 };
142 if (!batch) return script::projectResult(vm, Result<SpawnReceipt>::failure(batch.status()), project);
143 return script::projectResult(vm, crowd->applySpawnBatch(batch.value()), project);
144 });
145 cls.addFunc("getAgentState", &Crowd::getAgentState);
146
147 // 群体参数
148 cls.addFunc("setDefaultSpeed", &Crowd::setDefaultSpeed);
149 cls.addFunc("setDefaultRadius", &Crowd::setDefaultRadius);
150 cls.addFunc("setDefaultTurnRate", &Crowd::setDefaultTurnRate);
151 cls.addFunc("setArriveRadius", &Crowd::setArriveRadius);
152 cls.addFunc("setSeparationRadius", &Crowd::setSeparationRadius);
153 cls.addFunc("setPerceptionRadius", &Crowd::setPerceptionRadius);
154 cls.addFunc("setSeparationWeight", &Crowd::setSeparationWeight);
155 cls.addFunc("setAlignmentWeight", &Crowd::setAlignmentWeight);
156 cls.addFunc("setCohesionWeight", &Crowd::setCohesionWeight);
157 cls.addFunc("setWanderWeight", &Crowd::setWanderWeight);
158 cls.addFunc("setGoalWeight", &Crowd::setGoalWeight);
159 cls.addFunc("setResolveOverlaps", &Crowd::setResolveOverlaps);
160 cls.addFunc("setClampToField", &Crowd::setClampToField);
161 cls.addFunc("configureAvoidance", [vm = cls.getHandle()](Crowd *crowd, bool enabled, float horizon, float margin,
162 int maxNeighbors) {
163 return script::projectResult(vm, crowd->configureAvoidance({enabled, horizon, margin, maxNeighbors}));
164 });
165 cls.addFunc("getAvoidanceSettings", [vm = cls.getHandle()](Crowd *crowd) {
166 const auto settings = crowd->getAvoidanceSettings();
167 ssq::Table result(vm);
168 result.set("enabled", settings.enabled);
169 result.set("horizon", settings.horizon);
170 result.set("margin", settings.margin);
171 result.set("maxNeighbors", settings.maxNeighbors);
172 return result;
173 });
174
175 // 批量读取(脚本预分配数组)
176 cls.addFunc("getPositions", [](Crowd *c, ssq::Array xs, ssq::Array ys) {
177 if (!c) return;
178 const size_t n = std::min<size_t>({xs.size(), ys.size(), c->impl_->xs.size()});
179 for (size_t i = 0; i < n; ++i) {
180 xs.set(i, c->impl_->xs[i]);
181 ys.set(i, c->impl_->ys[i]);
182 }
183 });
184 cls.addFunc("getHeadings", [](Crowd *c, ssq::Array hs) {
185 if (!c) return;
186 const size_t n = std::min<size_t>(hs.size(), c->impl_->headings.size());
187 for (size_t i = 0; i < n; ++i) hs.set(i, c->impl_->headings[i]);
188 });
189 cls.addFunc("step", &Crowd::step);
190 cls.addFunc("advance", [vm = cls.getHandle()](Crowd *crowd, float dt) {
191 return script::projectResult(vm, crowd->advance(dt), [](StepReport report) {
192 return Value(Value::Object{{"avoidanceChecks", Value(report.avoidanceChecks)},
193 {"avoidanceTruncations", Value(report.avoidanceTruncations)},
194 {"substeps", Value(report.substeps)},
195 {"unresolvedContacts", Value(report.unresolvedContacts)},
196 {"unresolvedWalls", Value(report.unresolvedWalls)},
197 {"maxPenetration", Value(report.maxPenetration)}});
198 });
199 });
200}
201
202} // namespace eve::crowd
int mask
int priority
HSQUIRRELVM vm
Definition ECS.cpp:20
HSQOBJECT cls
Definition ECS.cpp:21
const GltfImportRequest & request
glm::vec3 n
Definition Grass.cpp:63
std::int32_t c
std::string name
std::string error
Definition Package.cpp:60
TileLayer * layer
std::string id
Definition PlayHost.cpp:108
int created
const SquirrelValueOptions & options
The single Squirrel projection for common Result, Status and Value.
TerrainThermalSettings settings
int margin
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
virtual std::string getName() const =0
Returns the name.
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
std::map< std::string, Value > Object
Definition Value.h:34
std::vector< Value > Array
Definition Value.h:33
FlowVec flowAtCell(int cx, int cy) const
格级流场方向。
Definition Crowd.cpp:91
bool removeAgent(int id)
删除单位(swap-pop O(1))。
Definition Crowd.cpp:153
std::string getAgentAction(int id) const
查询行动名。
Definition Crowd.cpp:244
void build()
执行 Dijkstra 建场。
Definition Crowd.cpp:71
void addFlowGoal(int gx, int gy)
追加目标格(多目标)。
Definition Crowd.cpp:67
void resizeField(int width, int height, float cellSize, float originX, float originY)
配置流场网格(世界单位/格)。
Definition Crowd.cpp:48
float costAtWorld(float wx, float wy) const
世界坐标积分代价(场外返回 kUnreachable)。
Definition Crowd.cpp:89
bool isFieldBuilt() const
是否已建场。
Definition Crowd.cpp:73
int getNamedAgentIndex(const std::string &stableId) const
Resolve a stable logical identifier to the current compact slot.
Definition Crowd.cpp:139
int getMaxAgents() const
Returns the max agents.
Definition Crowd.cpp:234
bool setAgentData(int id, int data)
设置游戏自定义标记。
Definition Crowd.cpp:287
int getAgentCount() const
当前单位数。
Definition Crowd.cpp:228
bool setAgentAccel(int id, float accel)
设置加速度上限(默认 maxSpeed×2)。
Definition Crowd.cpp:269
void clearFlowGoals()
清空目标列表。
Definition Crowd.cpp:69
void buildFlowField(int gx, int gy)
单目标快捷建场(clearGoals + addGoal + build)。
Definition Crowd.cpp:62
int addNamedAgent(const std::string &stableId, float x, float y, float heading, float radius)
Add an agent with an editor/game-stable logical identifier.
Definition Crowd.cpp:125
int addAgent(float x, float y, float heading, float radius)
添加单位;返回 id(=槽位索引;删除后 id 不稳定)。
Definition Crowd.cpp:99
void setBlocked(int cx, int cy, bool blocked)
设置/清除某格阻挡。
Definition Crowd.cpp:52
int getAgentAvoidancePriority(int id) const
Return overlap-resolution priority, or zero for an invalid id.
Definition Crowd.cpp:306
int getFieldWidth() const
网格信息访问器(调试渲染用)。
Definition Crowd.cpp:77
bool isReachable(int cx, int cy) const
某格是否可达。
Definition Crowd.cpp:75
float getCellSize() const
Returns the cell size.
Definition Crowd.cpp:79
float getFieldOriginY() const
Returns the field origin y.
Definition Crowd.cpp:81
Crowd()
Crowd.
Definition Crowd.cpp:43
void setMaxAgents(int maxAgents)
单位容量上限(默认 100000)。
Definition Crowd.cpp:230
bool removeNamedAgent(const std::string &stableId)
Remove an agent by stable logical identifier.
Definition Crowd.cpp:148
std::string getAgentStableId(int index) const
Return the stable logical identifier for a compact slot.
Definition Crowd.cpp:144
bool clearAgentTarget(int id)
清除目标点。
Definition Crowd.cpp:257
void clearAgents()
清空全部单位。
Definition Crowd.cpp:203
bool setAgentSpeed(int id, float speed)
设置最大速度(世界单位/秒)。
Definition Crowd.cpp:263
FlowVec flowAtWorld(float wx, float wy) const
世界坐标流场方向(双线性插值;场外返回零向量)。
Definition Crowd.cpp:83
float getFieldOriginX() const
Returns the field origin x.
Definition Crowd.cpp:80
bool setAgentAction(int id, const std::string &action)
设置行动:"idle" | "flow" | "seek" | "boids"。
Definition Crowd.cpp:236
float getCellCost(int cx, int cy) const
查询地形代价。
Definition Crowd.cpp:60
int getFieldHeight() const
Returns the field height.
Definition Crowd.cpp:78
bool setAgentRadius(int id, float radius)
设置半径。
Definition Crowd.cpp:281
bool hasNamedAgent(const std::string &stableId) const
Return whether a stable logical agent exists.
Definition Crowd.cpp:135
void setCellCost(int cx, int cy, float cost)
设置地形代价(0=阻挡,>=1 可走)。
Definition Crowd.cpp:56
bool setAgentTurnRate(int id, float radPerSec)
设置转向速率上限(弧度/秒)。
Definition Crowd.cpp:275
int getAgentData(int id) const
Returns the agent data.
Definition Crowd.cpp:293
bool setAgentTarget(int id, float tx, float ty)
设置世界目标点(seek 直接寻点,boids 作迁移偏置)。
Definition Crowd.cpp:249
std::variant< std::monostate, std::int64_t, double, std::string, bool > Value
Definition Database.h:26
ssq::Table project(HSQUIRRELVM vm, const eve::Result< void > &result)
Project a completed editing result that has no payload.
std::unordered_map< std::string, SkillDefinition > & table()
Definition Skill.cpp:65
ssq::Table projectResult(HSQUIRRELVM vm, Result< void > &&result)
Consume and project a void native Result using the common schema.
bool enabled
float vx
速度 X
Definition Crowd.h:24
float heading
朝向(弧度,0=+X)
Definition Crowd.h:22
int action
行动枚举(-1=非法 id)
Definition Crowd.h:26
int avoidancePriority
Higher-priority agents yield less during overlap resolution.
Definition Crowd.h:28
float x
世界 X
Definition Crowd.h:20
float vy
速度 Y
Definition Crowd.h:25
float y
世界 Y
Definition Crowd.h:21
float speed
当前速度大小
Definition Crowd.h:23
int data
游戏自定义标记
Definition Crowd.h:27
float y
方向 Y
Definition Crowd.h:34
float x
方向 X
Definition Crowd.h:33