@zylem/behaviors 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/behavior-system-CeJXzNvr.d.ts +868 -0
- package/dist/{chunk-GFARAJV2.js → chunk-2PAHQZZD.js} +44 -73
- package/dist/chunk-2PAHQZZD.js.map +1 -0
- package/dist/chunk-52FJIDGL.js +30 -0
- package/dist/chunk-52FJIDGL.js.map +1 -0
- package/dist/{chunk-UYFOLI2X.js → chunk-5A5AYP2C.js} +1 -1
- package/dist/{chunk-UYFOLI2X.js.map → chunk-5A5AYP2C.js.map} +1 -1
- package/dist/{chunk-64HKCSXD.js → chunk-5EBIIYZD.js} +25 -45
- package/dist/chunk-5EBIIYZD.js.map +1 -0
- package/dist/{chunk-WXXXJ22R.js → chunk-5NJGASUJ.js} +87 -129
- package/dist/chunk-5NJGASUJ.js.map +1 -0
- package/dist/{chunk-XLUJDKCT.js → chunk-5UMCWV5A.js} +24 -15
- package/dist/chunk-5UMCWV5A.js.map +1 -0
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/chunk-5WRI5ZAA.js.map +1 -0
- package/dist/{chunk-5SM5SH5O.js → chunk-7JLWZXPA.js} +2 -2
- package/dist/{chunk-HNESASBB.js → chunk-AEBDZWCP.js} +19 -28
- package/dist/chunk-AEBDZWCP.js.map +1 -0
- package/dist/chunk-AS3HR7AS.js +188 -0
- package/dist/chunk-AS3HR7AS.js.map +1 -0
- package/dist/chunk-E4X4YJZB.js +841 -0
- package/dist/chunk-E4X4YJZB.js.map +1 -0
- package/dist/{chunk-PWF757B6.js → chunk-F6ESSHQK.js} +19 -25
- package/dist/chunk-F6ESSHQK.js.map +1 -0
- package/dist/chunk-GQAPBNGT.js +210 -0
- package/dist/chunk-GQAPBNGT.js.map +1 -0
- package/dist/chunk-JGXRQUTC.js +191 -0
- package/dist/chunk-JGXRQUTC.js.map +1 -0
- package/dist/{chunk-BXP4K7RF.js → chunk-JVADRLWX.js} +57 -186
- package/dist/chunk-JVADRLWX.js.map +1 -0
- package/dist/{chunk-ZA43LPRM.js → chunk-KIYUUSPK.js} +2 -2
- package/dist/{chunk-V74N7D6Q.js → chunk-KOWGILCN.js} +24 -15
- package/dist/chunk-KOWGILCN.js.map +1 -0
- package/dist/{chunk-WWVD5DR5.js → chunk-M3QDKKDF.js} +2 -8
- package/dist/chunk-M3QDKKDF.js.map +1 -0
- package/dist/{chunk-FTDZAKZW.js → chunk-NQPYMUDF.js} +7 -5
- package/dist/{chunk-FTDZAKZW.js.map → chunk-NQPYMUDF.js.map} +1 -1
- package/dist/{chunk-XP3ASVGJ.js → chunk-NW4SE5XW.js} +2 -2
- package/dist/{chunk-KDY5N6J4.js → chunk-OPZ2LVS2.js} +1 -22
- package/dist/{chunk-KDY5N6J4.js.map → chunk-OPZ2LVS2.js.map} +1 -1
- package/dist/{chunk-5XZWTFGF.js → chunk-PLIXVF7B.js} +3 -3
- package/dist/chunk-PLIXVF7B.js.map +1 -0
- package/dist/{chunk-Y7YIAWPW.js → chunk-SGHIGTVZ.js} +1 -11
- package/dist/{chunk-Y7YIAWPW.js.map → chunk-SGHIGTVZ.js.map} +1 -1
- package/dist/{chunk-UL6Q5HDP.js → chunk-TBUKJKY6.js} +3 -25
- package/dist/chunk-TBUKJKY6.js.map +1 -0
- package/dist/chunk-VFDUKGRZ.js +155 -0
- package/dist/chunk-VFDUKGRZ.js.map +1 -0
- package/dist/chunk-VT3H43QA.js +288 -0
- package/dist/chunk-VT3H43QA.js.map +1 -0
- package/dist/chunk-W26PHBME.js +309 -0
- package/dist/chunk-W26PHBME.js.map +1 -0
- package/dist/components-BANNjAZP.d.ts +30 -0
- package/dist/cooldown.d.ts +2 -2
- package/dist/cooldown.js +1 -0
- package/dist/coordinators/boundary-ricochet-3d.d.ts +4 -4
- package/dist/coordinators/boundary-ricochet-3d.js +1 -0
- package/dist/coordinators/boundary-ricochet.d.ts +4 -4
- package/dist/coordinators/boundary-ricochet.js +3 -2
- package/dist/coordinators/first-person-shooter.js +1 -0
- package/dist/coordinators/multidirectional-space-shooter.d.ts +3 -3
- package/dist/coordinators/multidirectional-space-shooter.js +5 -3
- package/dist/coordinators/top-down-shooter.d.ts +3 -3
- package/dist/coordinators/top-down-shooter.js +5 -3
- package/dist/core.d.ts +288 -8
- package/dist/core.js +492 -19
- package/dist/core.js.map +1 -1
- package/dist/destructible-3d.d.ts +32 -4
- package/dist/destructible-3d.js +2 -1
- package/dist/destructible-prebake.js +1 -0
- package/dist/{entity-types-CmtQ-IBp.d.ts → entity-types-DhfsZbSK.d.ts} +5 -3
- package/dist/first-person.d.ts +27 -38
- package/dist/first-person.js +8 -7
- package/dist/index.d.ts +14 -15
- package/dist/index.js +37 -52
- package/dist/jumper-2d.d.ts +3 -17
- package/dist/jumper-2d.js +4 -8
- package/dist/jumper-3d.d.ts +5 -39
- package/dist/jumper-3d.js +5 -9
- package/dist/{moveable-BLTHO7Jq.d.ts → moveable-XhzWPAw5.d.ts} +21 -4
- package/dist/particle-emitter/presets.js +1 -0
- package/dist/particle-emitter.d.ts +3 -3
- package/dist/particle-emitter.js +3 -2
- package/dist/platformer-2d.d.ts +13 -82
- package/dist/platformer-2d.js +4 -4
- package/dist/platformer-3d.d.ts +13 -78
- package/dist/platformer-3d.js +4 -4
- package/dist/ricochet-2d.d.ts +3 -3
- package/dist/ricochet-2d.js +4 -3
- package/dist/ricochet-3d.d.ts +3 -3
- package/dist/ricochet-3d.js +4 -3
- package/dist/runtime-2d.d.ts +2 -2
- package/dist/runtime-2d.js +1 -0
- package/dist/runtime-2d.js.map +1 -1
- package/dist/screen-visibility.d.ts +2 -2
- package/dist/screen-visibility.js +1 -0
- package/dist/screen-wrap.d.ts +2 -2
- package/dist/screen-wrap.js +4 -3
- package/dist/shooter-2d.d.ts +3 -3
- package/dist/shooter-2d.js +4 -3
- package/dist/thruster.d.ts +5 -34
- package/dist/thruster.js +4 -6
- package/dist/top-down-movement.d.ts +9 -27
- package/dist/top-down-movement.js +6 -6
- package/dist/{vector-Bm65-FOG.d.ts → vector-DjhLUrak.d.ts} +2 -4
- package/dist/world-boundary-2d.d.ts +2 -2
- package/dist/world-boundary-2d.js +5 -4
- package/dist/world-boundary-3d.d.ts +2 -2
- package/dist/world-boundary-3d.js +4 -3
- package/package.json +4 -3
- package/dist/behavior-system-DSNek0W9.d.ts +0 -483
- package/dist/chunk-4URF65BR.js +0 -44
- package/dist/chunk-4URF65BR.js.map +0 -1
- package/dist/chunk-4V7TIRO2.js +0 -44
- package/dist/chunk-4V7TIRO2.js.map +0 -1
- package/dist/chunk-5XZWTFGF.js.map +0 -1
- package/dist/chunk-64HKCSXD.js.map +0 -1
- package/dist/chunk-BXP4K7RF.js.map +0 -1
- package/dist/chunk-FRJDQM23.js +0 -506
- package/dist/chunk-FRJDQM23.js.map +0 -1
- package/dist/chunk-GFARAJV2.js.map +0 -1
- package/dist/chunk-GTLA6LOJ.js +0 -400
- package/dist/chunk-GTLA6LOJ.js.map +0 -1
- package/dist/chunk-HNESASBB.js.map +0 -1
- package/dist/chunk-JXMF4NUI.js +0 -309
- package/dist/chunk-JXMF4NUI.js.map +0 -1
- package/dist/chunk-MJFMNRMZ.js +0 -240
- package/dist/chunk-MJFMNRMZ.js.map +0 -1
- package/dist/chunk-OTLSUYQQ.js +0 -29
- package/dist/chunk-OTLSUYQQ.js.map +0 -1
- package/dist/chunk-PWF757B6.js.map +0 -1
- package/dist/chunk-RONH2KDI.js +0 -455
- package/dist/chunk-RONH2KDI.js.map +0 -1
- package/dist/chunk-RTRFJVCZ.js +0 -454
- package/dist/chunk-RTRFJVCZ.js.map +0 -1
- package/dist/chunk-UL6Q5HDP.js.map +0 -1
- package/dist/chunk-V74N7D6Q.js.map +0 -1
- package/dist/chunk-WWVD5DR5.js.map +0 -1
- package/dist/chunk-WXXXJ22R.js.map +0 -1
- package/dist/chunk-XLUJDKCT.js.map +0 -1
- package/dist/components-BWG1GkZA.d.ts +0 -20
- package/dist/use-behavior-h9-T5FSv.d.ts +0 -13
- /package/dist/{chunk-5SM5SH5O.js.map → chunk-7JLWZXPA.js.map} +0 -0
- /package/dist/{chunk-ZA43LPRM.js.map → chunk-KIYUUSPK.js.map} +0 -0
- /package/dist/{chunk-XP3ASVGJ.js.map → chunk-NW4SE5XW.js.map} +0 -0
package/dist/chunk-JXMF4NUI.js
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
// src/lib/behaviors/shared/ground-probe-3d.ts
|
|
2
|
-
import { Ball, Capsule, Cuboid } from "@dimforge/rapier3d-compat";
|
|
3
|
-
import {
|
|
4
|
-
BoxGeometry,
|
|
5
|
-
Mesh,
|
|
6
|
-
MeshBasicMaterial
|
|
7
|
-
} from "three";
|
|
8
|
-
|
|
9
|
-
// src/lib/physics/collider-desc-inspect.ts
|
|
10
|
-
function inspectColliderDesc(desc) {
|
|
11
|
-
const internal = desc;
|
|
12
|
-
const customShapeData = internal.__zylemShapeData;
|
|
13
|
-
if (customShapeData?.shape === "convexHull") {
|
|
14
|
-
const result = finalize("convexHull", [], internal);
|
|
15
|
-
result.vertices = [...customShapeData.vertices];
|
|
16
|
-
return result;
|
|
17
|
-
}
|
|
18
|
-
if (customShapeData?.shape === "trimesh") {
|
|
19
|
-
const result = finalize("trimesh", [], internal);
|
|
20
|
-
result.vertices = [...customShapeData.vertices];
|
|
21
|
-
result.indices = [...customShapeData.indices];
|
|
22
|
-
return result;
|
|
23
|
-
}
|
|
24
|
-
const shapeType = internal.shape?.type ?? internal.shapeType ?? 0;
|
|
25
|
-
const { shape, dimensions } = extractShapeData(shapeType, internal);
|
|
26
|
-
return finalize(shape, dimensions, internal);
|
|
27
|
-
}
|
|
28
|
-
function finalize(shape, dimensions, internal) {
|
|
29
|
-
const result = { shape, dimensions };
|
|
30
|
-
const t = internal.translation;
|
|
31
|
-
if (t && (t.x !== 0 || t.y !== 0 || t.z !== 0)) {
|
|
32
|
-
result.translation = [t.x, t.y, t.z];
|
|
33
|
-
}
|
|
34
|
-
return result;
|
|
35
|
-
}
|
|
36
|
-
function extractShapeData(shapeType, internal) {
|
|
37
|
-
switch (shapeType) {
|
|
38
|
-
case 0:
|
|
39
|
-
return {
|
|
40
|
-
shape: "ball",
|
|
41
|
-
dimensions: [internal.shape?.radius ?? internal.halfExtents?.x ?? 1]
|
|
42
|
-
};
|
|
43
|
-
case 1:
|
|
44
|
-
return {
|
|
45
|
-
shape: "cuboid",
|
|
46
|
-
dimensions: [
|
|
47
|
-
internal.shape?.halfExtents?.x ?? internal.halfExtents?.x ?? 0.5,
|
|
48
|
-
internal.shape?.halfExtents?.y ?? internal.halfExtents?.y ?? 0.5,
|
|
49
|
-
internal.shape?.halfExtents?.z ?? internal.halfExtents?.z ?? 0.5
|
|
50
|
-
]
|
|
51
|
-
};
|
|
52
|
-
case 2:
|
|
53
|
-
return {
|
|
54
|
-
shape: "capsule",
|
|
55
|
-
dimensions: [
|
|
56
|
-
internal.shape?.halfHeight ?? 0.5,
|
|
57
|
-
internal.shape?.radius ?? 0.5
|
|
58
|
-
]
|
|
59
|
-
};
|
|
60
|
-
case 6:
|
|
61
|
-
return {
|
|
62
|
-
shape: "cone",
|
|
63
|
-
dimensions: [
|
|
64
|
-
internal.shape?.halfHeight ?? 1,
|
|
65
|
-
internal.shape?.radius ?? 1
|
|
66
|
-
]
|
|
67
|
-
};
|
|
68
|
-
case 7:
|
|
69
|
-
return {
|
|
70
|
-
shape: "cylinder",
|
|
71
|
-
dimensions: [
|
|
72
|
-
internal.shape?.halfHeight ?? 1,
|
|
73
|
-
internal.shape?.radius ?? 1
|
|
74
|
-
]
|
|
75
|
-
};
|
|
76
|
-
case 11: {
|
|
77
|
-
const heights = internal.shape?.heights;
|
|
78
|
-
return {
|
|
79
|
-
shape: "heightfield",
|
|
80
|
-
dimensions: heights ? Array.from(heights) : []
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
default:
|
|
84
|
-
return { shape: "cuboid", dimensions: [0.5, 0.5, 0.5] };
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// src/lib/behaviors/shared/ground-probe-3d.ts
|
|
89
|
-
function inspectLiveColliderShape(entity) {
|
|
90
|
-
const shape = entity.collider?.shape;
|
|
91
|
-
if (!shape) return null;
|
|
92
|
-
if (shape instanceof Capsule) {
|
|
93
|
-
return {
|
|
94
|
-
halfBelow: shape.halfHeight + shape.radius,
|
|
95
|
-
halfX: shape.radius,
|
|
96
|
-
halfZ: shape.radius
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
if (shape instanceof Cuboid) {
|
|
100
|
-
return {
|
|
101
|
-
halfBelow: shape.halfExtents.y,
|
|
102
|
-
halfX: shape.halfExtents.x,
|
|
103
|
-
halfZ: shape.halfExtents.z
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
if (shape instanceof Ball) {
|
|
107
|
-
return {
|
|
108
|
-
halfBelow: shape.radius,
|
|
109
|
-
halfX: shape.radius,
|
|
110
|
-
halfZ: shape.radius
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
function getLiveColliderCenterOffsetY(entity) {
|
|
116
|
-
const collider = entity.collider;
|
|
117
|
-
const body = entity.body;
|
|
118
|
-
if (!collider || !body) return 0;
|
|
119
|
-
try {
|
|
120
|
-
return collider.translation().y - body.translation().y;
|
|
121
|
-
} catch {
|
|
122
|
-
return 0;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
var GROUND_SNAP_EPSILON = 1e-3;
|
|
126
|
-
var CENTER_BOX_HALF = 0.05;
|
|
127
|
-
var DEFAULT_BOX_THICKNESS = 0.05;
|
|
128
|
-
var GroundProbe3D = class {
|
|
129
|
-
constructor(world) {
|
|
130
|
-
this.world = world;
|
|
131
|
-
}
|
|
132
|
-
world;
|
|
133
|
-
debugMeshes = /* @__PURE__ */ new Map();
|
|
134
|
-
probeSupport(entity, options) {
|
|
135
|
-
if (!this.world?.world || !entity.body) return null;
|
|
136
|
-
const translation = entity.body.translation();
|
|
137
|
-
const originYOffset = options.originYOffset ?? 0;
|
|
138
|
-
const box = options.box ?? deriveDefaultBox(entity, options.mode ?? "any");
|
|
139
|
-
const shapePos = {
|
|
140
|
-
x: translation.x,
|
|
141
|
-
y: translation.y + originYOffset,
|
|
142
|
-
z: translation.z
|
|
143
|
-
};
|
|
144
|
-
const shapeRot = { x: 0, y: 0, z: 0, w: 1 };
|
|
145
|
-
const shapeVel = { x: 0, y: -1, z: 0 };
|
|
146
|
-
const shape = new Cuboid(box.x, box.y, box.z);
|
|
147
|
-
const hit = this.world.world.castShape(
|
|
148
|
-
shapePos,
|
|
149
|
-
shapeRot,
|
|
150
|
-
shapeVel,
|
|
151
|
-
shape,
|
|
152
|
-
options.rayLength,
|
|
153
|
-
true,
|
|
154
|
-
void 0,
|
|
155
|
-
void 0,
|
|
156
|
-
void 0,
|
|
157
|
-
entity.body
|
|
158
|
-
);
|
|
159
|
-
let support = null;
|
|
160
|
-
if (hit) {
|
|
161
|
-
support = {
|
|
162
|
-
toi: hit.toi,
|
|
163
|
-
point: {
|
|
164
|
-
x: shapePos.x,
|
|
165
|
-
y: shapePos.y - hit.toi - box.y,
|
|
166
|
-
z: shapePos.z
|
|
167
|
-
},
|
|
168
|
-
origin: { ...shapePos },
|
|
169
|
-
colliderUuid: hit.collider?._parent?.userData?.uuid
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
if (options.debug && options.scene) {
|
|
173
|
-
this.updateDebugMesh(
|
|
174
|
-
entity.uuid,
|
|
175
|
-
shapePos,
|
|
176
|
-
box,
|
|
177
|
-
options.rayLength,
|
|
178
|
-
Boolean(support),
|
|
179
|
-
options.scene
|
|
180
|
-
);
|
|
181
|
-
} else {
|
|
182
|
-
this.disposeDebugMesh(entity.uuid);
|
|
183
|
-
}
|
|
184
|
-
return support;
|
|
185
|
-
}
|
|
186
|
-
detect(entity, options) {
|
|
187
|
-
return this.probeSupport(entity, options) != null;
|
|
188
|
-
}
|
|
189
|
-
destroyEntity(uuid) {
|
|
190
|
-
this.disposeDebugMesh(uuid);
|
|
191
|
-
}
|
|
192
|
-
destroy() {
|
|
193
|
-
for (const uuid of this.debugMeshes.keys()) {
|
|
194
|
-
this.disposeDebugMesh(uuid);
|
|
195
|
-
}
|
|
196
|
-
this.debugMeshes.clear();
|
|
197
|
-
}
|
|
198
|
-
updateDebugMesh(uuid, shapePos, box, rayLength, hasGround, scene) {
|
|
199
|
-
let mesh = this.debugMeshes.get(uuid);
|
|
200
|
-
if (!mesh) {
|
|
201
|
-
const geometry = new BoxGeometry(2 * box.x, 2 * box.y, 2 * box.z);
|
|
202
|
-
const material = new MeshBasicMaterial({
|
|
203
|
-
wireframe: true,
|
|
204
|
-
color: 16711680
|
|
205
|
-
});
|
|
206
|
-
mesh = new Mesh(geometry, material);
|
|
207
|
-
scene.add(mesh);
|
|
208
|
-
this.debugMeshes.set(uuid, mesh);
|
|
209
|
-
}
|
|
210
|
-
mesh.position.set(
|
|
211
|
-
shapePos.x,
|
|
212
|
-
shapePos.y - rayLength * 0.5,
|
|
213
|
-
shapePos.z
|
|
214
|
-
);
|
|
215
|
-
mesh.scale.set(1, Math.max(rayLength / Math.max(2 * box.y, 1e-6), 1), 1);
|
|
216
|
-
mesh.material.color.setHex(
|
|
217
|
-
hasGround ? 65280 : 16711680
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
disposeDebugMesh(uuid) {
|
|
221
|
-
const mesh = this.debugMeshes.get(uuid);
|
|
222
|
-
if (!mesh) return;
|
|
223
|
-
mesh.removeFromParent();
|
|
224
|
-
mesh.geometry.dispose();
|
|
225
|
-
mesh.material.dispose();
|
|
226
|
-
this.debugMeshes.delete(uuid);
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
function deriveDefaultBox(entity, mode) {
|
|
230
|
-
if (mode === "center") {
|
|
231
|
-
return { x: CENTER_BOX_HALF, y: CENTER_BOX_HALF, z: CENTER_BOX_HALF };
|
|
232
|
-
}
|
|
233
|
-
const live = inspectLiveColliderShape(entity);
|
|
234
|
-
if (live) {
|
|
235
|
-
return {
|
|
236
|
-
x: Math.max(live.halfX * 0.7, CENTER_BOX_HALF),
|
|
237
|
-
y: DEFAULT_BOX_THICKNESS,
|
|
238
|
-
z: Math.max(live.halfZ * 0.7, CENTER_BOX_HALF)
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
const runtimeColliderDesc = entity?.colliderDesc;
|
|
242
|
-
if (runtimeColliderDesc) {
|
|
243
|
-
const inspected = inspectColliderDesc(runtimeColliderDesc);
|
|
244
|
-
if (inspected.shape === "capsule" && inspected.dimensions.length >= 2) {
|
|
245
|
-
const radius = inspected.dimensions[1] ?? 0.5;
|
|
246
|
-
const half = Math.max(radius * 0.7, CENTER_BOX_HALF);
|
|
247
|
-
return { x: half, y: DEFAULT_BOX_THICKNESS, z: half };
|
|
248
|
-
}
|
|
249
|
-
if (inspected.shape === "cuboid" && inspected.dimensions.length >= 3) {
|
|
250
|
-
const halfX = (inspected.dimensions[0] ?? 0.5) * 0.7;
|
|
251
|
-
const halfZ = (inspected.dimensions[2] ?? 0.5) * 0.7;
|
|
252
|
-
return {
|
|
253
|
-
x: Math.max(halfX, CENTER_BOX_HALF),
|
|
254
|
-
y: DEFAULT_BOX_THICKNESS,
|
|
255
|
-
z: Math.max(halfZ, CENTER_BOX_HALF)
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
const collisionSize = entity?.options?.collision?.size ?? entity?.options?.collisionSize ?? entity?.options?.size;
|
|
260
|
-
if (collisionSize) {
|
|
261
|
-
const halfX = (collisionSize.x ?? 1) / 2 * 0.7;
|
|
262
|
-
const halfZ = (collisionSize.z ?? collisionSize.x ?? 1) / 2 * 0.7;
|
|
263
|
-
return {
|
|
264
|
-
x: Math.max(halfX, CENTER_BOX_HALF),
|
|
265
|
-
y: DEFAULT_BOX_THICKNESS,
|
|
266
|
-
z: Math.max(halfZ, CENTER_BOX_HALF)
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
return { x: 0.35, y: DEFAULT_BOX_THICKNESS, z: 0.35 };
|
|
270
|
-
}
|
|
271
|
-
function getGroundAnchorOffsetY(entity) {
|
|
272
|
-
const live = inspectLiveColliderShape(entity);
|
|
273
|
-
if (live) {
|
|
274
|
-
const centerY2 = getLiveColliderCenterOffsetY(entity);
|
|
275
|
-
return live.halfBelow - centerY2;
|
|
276
|
-
}
|
|
277
|
-
const runtimeColliderDesc = entity?.colliderDesc;
|
|
278
|
-
if (runtimeColliderDesc) {
|
|
279
|
-
const inspected = inspectColliderDesc(runtimeColliderDesc);
|
|
280
|
-
const centerY2 = inspected.translation?.[1] ?? 0;
|
|
281
|
-
if (inspected.shape === "capsule" && inspected.dimensions.length >= 2) {
|
|
282
|
-
const halfCylinder = inspected.dimensions[0] ?? 0;
|
|
283
|
-
const radius = inspected.dimensions[1] ?? 0;
|
|
284
|
-
return halfCylinder + radius - centerY2;
|
|
285
|
-
}
|
|
286
|
-
if (inspected.shape === "cuboid" && inspected.dimensions.length >= 2) {
|
|
287
|
-
const halfHeight = inspected.dimensions[1] ?? 0;
|
|
288
|
-
return halfHeight - centerY2;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
const collisionSize = entity?.options?.collision?.size ?? entity?.options?.collisionSize ?? entity?.options?.size;
|
|
292
|
-
const height = collisionSize?.y ?? 0;
|
|
293
|
-
if (height <= 0) {
|
|
294
|
-
return 0;
|
|
295
|
-
}
|
|
296
|
-
const collisionPosition = entity?.options?.collision?.position ?? entity?.options?.collisionPosition;
|
|
297
|
-
const centerY = collisionPosition?.y ?? height / 2;
|
|
298
|
-
return height / 2 - centerY;
|
|
299
|
-
}
|
|
300
|
-
function getGroundSnapTargetY(entity, support, epsilon = GROUND_SNAP_EPSILON) {
|
|
301
|
-
return support.point.y + getGroundAnchorOffsetY(entity) + epsilon;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
export {
|
|
305
|
-
GroundProbe3D,
|
|
306
|
-
getGroundAnchorOffsetY,
|
|
307
|
-
getGroundSnapTargetY
|
|
308
|
-
};
|
|
309
|
-
//# sourceMappingURL=chunk-JXMF4NUI.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/shared/ground-probe-3d.ts","../src/lib/physics/collider-desc-inspect.ts"],"sourcesContent":["import { Ball, Capsule, Cuboid, type Collider, type RigidBody } from '@dimforge/rapier3d-compat';\nimport {\n\tBoxGeometry,\n\tMesh,\n\tMeshBasicMaterial,\n} from 'three';\nimport type { ZylemWorld } from '../../collision/world';\nimport { inspectColliderDesc } from '../../physics/collider-desc-inspect';\n\n/**\n * Probe sizing hint.\n *\n * - `center`: prefer a tiny box that behaves close to a single downward ray\n * (used by `Jumper3DBehavior` for thin/single-point ground tests).\n * - `any`: prefer a box sized from the entity's collider footprint\n * (used by `Platformer3D` so the character \"feels\" the ground under any\n * foot, not just dead-center).\n *\n * The actual box dimensions are still configurable via `options.box`.\n */\nexport type GroundProbeMode = 'center' | 'any';\n\nexport interface GroundProbeEntity {\n\tuuid: string;\n\tbody: RigidBody | null;\n\t/** Live Rapier collider; when present, probe geometry is derived from its shape. */\n\tcollider?: Collider | null;\n}\n\n/**\n * Geometry extracted from a live Rapier collider shape: the half-extent of\n * the shape below its center (`halfBelow`) and the horizontal half-extents\n * of its footprint. First-priority source for probe sizing/anchoring — works\n * for any entity with a live collider, engine metadata or not.\n */\ninterface LiveShapeInfo {\n\thalfBelow: number;\n\thalfX: number;\n\thalfZ: number;\n}\n\nfunction inspectLiveColliderShape(entity: GroundProbeEntity): LiveShapeInfo | null {\n\tconst shape = entity.collider?.shape;\n\tif (!shape) return null;\n\n\tif (shape instanceof Capsule) {\n\t\treturn {\n\t\t\thalfBelow: shape.halfHeight + shape.radius,\n\t\t\thalfX: shape.radius,\n\t\t\thalfZ: shape.radius,\n\t\t};\n\t}\n\tif (shape instanceof Cuboid) {\n\t\treturn {\n\t\t\thalfBelow: shape.halfExtents.y,\n\t\t\thalfX: shape.halfExtents.x,\n\t\t\thalfZ: shape.halfExtents.z,\n\t\t};\n\t}\n\tif (shape instanceof Ball) {\n\t\treturn {\n\t\t\thalfBelow: shape.radius,\n\t\t\thalfX: shape.radius,\n\t\t\thalfZ: shape.radius,\n\t\t};\n\t}\n\treturn null;\n}\n\n/**\n * Vertical offset of the collider center relative to the body origin\n * (0 when either translation is unavailable).\n */\nfunction getLiveColliderCenterOffsetY(entity: GroundProbeEntity): number {\n\tconst collider = entity.collider;\n\tconst body = entity.body;\n\tif (!collider || !body) return 0;\n\ttry {\n\t\treturn collider.translation().y - body.translation().y;\n\t} catch {\n\t\treturn 0;\n\t}\n}\n\nexport interface GroundProbeOptions {\n\t/** Maximum cast distance in world units. */\n\trayLength: number;\n\t/** Selects the default box size when `box` is not explicitly provided. */\n\tmode?: GroundProbeMode;\n\t/** Render a wireframe of the cast box for debugging. Requires `scene`. */\n\tdebug?: boolean;\n\t/** Three.js scene used to host the debug wireframe mesh. */\n\tscene?: any;\n\t/**\n\t * Vertical offset added to the body translation when computing the cast\n\t * origin. Allows callers to shift the probe to e.g. just above the\n\t * capsule's bottom face.\n\t */\n\toriginYOffset?: number;\n\t/**\n\t * Half-extents of the cast cuboid. When omitted the probe derives a\n\t * sensible default from the entity's collider:\n\t * - capsule: `(r * 0.7, 0.05, r * 0.7)` — a thin slab smaller than the\n\t * capsule footprint, so side walls don't register as ground.\n\t * - cuboid: shrink the bottom face by 30% so the probe sits well inside\n\t * the collider footprint.\n\t * - `mode: 'center'`: forces a tiny `(0.05, 0.05, 0.05)` box.\n\t */\n\tbox?: { x: number; y: number; z: number };\n}\n\nexport interface GroundProbeSupportHit {\n\ttoi: number;\n\tpoint: {\n\t\tx: number;\n\t\ty: number;\n\t\tz: number;\n\t};\n\torigin: {\n\t\tx: number;\n\t\ty: number;\n\t\tz: number;\n\t};\n\tcolliderUuid?: string;\n}\n\nexport const GROUND_SNAP_EPSILON = 0.001;\n\n/**\n * Tiny box used when the caller selects `mode: 'center'` — close enough to a\n * point cast that it preserves the old single-ray behavior of `Jumper3DBehavior`.\n */\nconst CENTER_BOX_HALF = 0.05;\n\n/**\n * Default vertical thickness of the cast cuboid. The box is intentionally thin\n * vertically so the impact distance closely matches a downward ray's TOI;\n * existing snap-to-ground math (which assumes `point.y ≈ origin.y - toi`)\n * keeps working with negligible drift.\n */\nconst DEFAULT_BOX_THICKNESS = 0.05;\n\n/**\n * GroundProbe3D — single-cast cuboid probe used by 3D platformer and jumper\n * behaviors to detect the ground beneath an entity.\n *\n * Replaces the previous 5-ray probe: a single shape-cast handles edge cases\n * (corner of a platform, narrow gap) more robustly and produces a single,\n * intuitive debug visualization (a wireframe box).\n */\nexport class GroundProbe3D {\n\tprivate debugMeshes = new Map<string, Mesh>();\n\n\tconstructor(private world: ZylemWorld | null) {}\n\n\tprobeSupport(\n\t\tentity: GroundProbeEntity,\n\t\toptions: GroundProbeOptions,\n\t): GroundProbeSupportHit | null {\n\t\tif (!this.world?.world || !entity.body) return null;\n\n\t\tconst translation = entity.body.translation();\n\t\tconst originYOffset = options.originYOffset ?? 0;\n\t\tconst box = options.box ?? deriveDefaultBox(entity, options.mode ?? 'any');\n\n\t\tconst shapePos = {\n\t\t\tx: translation.x,\n\t\t\ty: translation.y + originYOffset,\n\t\t\tz: translation.z,\n\t\t};\n\t\tconst shapeRot = { x: 0, y: 0, z: 0, w: 1 };\n\t\tconst shapeVel = { x: 0, y: -1, z: 0 };\n\n\t\tconst shape = new Cuboid(box.x, box.y, box.z);\n\t\tconst hit = this.world.world.castShape(\n\t\t\tshapePos,\n\t\t\tshapeRot,\n\t\t\tshapeVel,\n\t\t\tshape,\n\t\t\toptions.rayLength,\n\t\t\ttrue,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tentity.body,\n\t\t);\n\n\t\tlet support: GroundProbeSupportHit | null = null;\n\t\tif (hit) {\n\t\t\tsupport = {\n\t\t\t\ttoi: hit.toi,\n\t\t\t\tpoint: {\n\t\t\t\t\tx: shapePos.x,\n\t\t\t\t\ty: shapePos.y - hit.toi - box.y,\n\t\t\t\t\tz: shapePos.z,\n\t\t\t\t},\n\t\t\t\torigin: { ...shapePos },\n\t\t\t\tcolliderUuid: (hit.collider as any)?._parent?.userData?.uuid,\n\t\t\t};\n\t\t}\n\n\t\tif (options.debug && options.scene) {\n\t\t\tthis.updateDebugMesh(\n\t\t\t\tentity.uuid,\n\t\t\t\tshapePos,\n\t\t\t\tbox,\n\t\t\t\toptions.rayLength,\n\t\t\t\tBoolean(support),\n\t\t\t\toptions.scene,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.disposeDebugMesh(entity.uuid);\n\t\t}\n\n\t\treturn support;\n\t}\n\n\tdetect(entity: GroundProbeEntity, options: GroundProbeOptions): boolean {\n\t\treturn this.probeSupport(entity, options) != null;\n\t}\n\n\tdestroyEntity(uuid: string): void {\n\t\tthis.disposeDebugMesh(uuid);\n\t}\n\n\tdestroy(): void {\n\t\tfor (const uuid of this.debugMeshes.keys()) {\n\t\t\tthis.disposeDebugMesh(uuid);\n\t\t}\n\t\tthis.debugMeshes.clear();\n\t}\n\n\tprivate updateDebugMesh(\n\t\tuuid: string,\n\t\tshapePos: { x: number; y: number; z: number },\n\t\tbox: { x: number; y: number; z: number },\n\t\trayLength: number,\n\t\thasGround: boolean,\n\t\tscene: any,\n\t): void {\n\t\tlet mesh = this.debugMeshes.get(uuid);\n\t\tif (!mesh) {\n\t\t\tconst geometry = new BoxGeometry(2 * box.x, 2 * box.y, 2 * box.z);\n\t\t\tconst material = new MeshBasicMaterial({\n\t\t\t\twireframe: true,\n\t\t\t\tcolor: 0xff0000,\n\t\t\t});\n\t\t\tmesh = new Mesh(geometry, material);\n\t\t\tscene.add(mesh);\n\t\t\tthis.debugMeshes.set(uuid, mesh);\n\t\t}\n\n\t\t// Position the box at the cast midpoint so users can see the swept volume.\n\t\tmesh.position.set(\n\t\t\tshapePos.x,\n\t\t\tshapePos.y - rayLength * 0.5,\n\t\t\tshapePos.z,\n\t\t);\n\t\tmesh.scale.set(1, Math.max(rayLength / Math.max(2 * box.y, 1e-6), 1), 1);\n\t\t(mesh.material as MeshBasicMaterial).color.setHex(\n\t\t\thasGround ? 0x00ff00 : 0xff0000,\n\t\t);\n\t}\n\n\tprivate disposeDebugMesh(uuid: string): void {\n\t\tconst mesh = this.debugMeshes.get(uuid);\n\t\tif (!mesh) return;\n\n\t\tmesh.removeFromParent();\n\t\tmesh.geometry.dispose();\n\t\t(mesh.material as MeshBasicMaterial).dispose();\n\n\t\tthis.debugMeshes.delete(uuid);\n\t}\n}\n\nfunction deriveDefaultBox(\n\tentity: GroundProbeEntity,\n\tmode: GroundProbeMode,\n): { x: number; y: number; z: number } {\n\tif (mode === 'center') {\n\t\treturn { x: CENTER_BOX_HALF, y: CENTER_BOX_HALF, z: CENTER_BOX_HALF };\n\t}\n\n\t// First priority: derive from the live Rapier collider shape. Works for\n\t// any consumer (e.g. the web harness) without engine collider metadata.\n\tconst live = inspectLiveColliderShape(entity);\n\tif (live) {\n\t\treturn {\n\t\t\tx: Math.max(live.halfX * 0.7, CENTER_BOX_HALF),\n\t\t\ty: DEFAULT_BOX_THICKNESS,\n\t\t\tz: Math.max(live.halfZ * 0.7, CENTER_BOX_HALF),\n\t\t};\n\t}\n\n\tconst runtimeColliderDesc = (entity as any)?.colliderDesc;\n\tif (runtimeColliderDesc) {\n\t\tconst inspected = inspectColliderDesc(runtimeColliderDesc);\n\t\tif (inspected.shape === 'capsule' && inspected.dimensions.length >= 2) {\n\t\t\tconst radius = inspected.dimensions[1] ?? 0.5;\n\t\t\tconst half = Math.max(radius * 0.7, CENTER_BOX_HALF);\n\t\t\treturn { x: half, y: DEFAULT_BOX_THICKNESS, z: half };\n\t\t}\n\t\tif (inspected.shape === 'cuboid' && inspected.dimensions.length >= 3) {\n\t\t\tconst halfX = (inspected.dimensions[0] ?? 0.5) * 0.7;\n\t\t\tconst halfZ = (inspected.dimensions[2] ?? 0.5) * 0.7;\n\t\t\treturn {\n\t\t\t\tx: Math.max(halfX, CENTER_BOX_HALF),\n\t\t\t\ty: DEFAULT_BOX_THICKNESS,\n\t\t\t\tz: Math.max(halfZ, CENTER_BOX_HALF),\n\t\t\t};\n\t\t}\n\t}\n\n\tconst collisionSize =\n\t\t(entity as any)?.options?.collision?.size ??\n\t\t(entity as any)?.options?.collisionSize ??\n\t\t(entity as any)?.options?.size;\n\tif (collisionSize) {\n\t\tconst halfX = ((collisionSize.x ?? 1) / 2) * 0.7;\n\t\tconst halfZ = ((collisionSize.z ?? collisionSize.x ?? 1) / 2) * 0.7;\n\t\treturn {\n\t\t\tx: Math.max(halfX, CENTER_BOX_HALF),\n\t\t\ty: DEFAULT_BOX_THICKNESS,\n\t\t\tz: Math.max(halfZ, CENTER_BOX_HALF),\n\t\t};\n\t}\n\n\treturn { x: 0.35, y: DEFAULT_BOX_THICKNESS, z: 0.35 };\n}\n\nexport function getGroundAnchorOffsetY(entity: any): number {\n\t// First priority: live Rapier collider shape (see inspectLiveColliderShape).\n\tconst live = inspectLiveColliderShape(entity);\n\tif (live) {\n\t\tconst centerY = getLiveColliderCenterOffsetY(entity);\n\t\treturn live.halfBelow - centerY;\n\t}\n\n\tconst runtimeColliderDesc = entity?.colliderDesc;\n\tif (runtimeColliderDesc) {\n\t\tconst inspected = inspectColliderDesc(runtimeColliderDesc);\n\t\tconst centerY = inspected.translation?.[1] ?? 0;\n\t\tif (inspected.shape === 'capsule' && inspected.dimensions.length >= 2) {\n\t\t\tconst halfCylinder = inspected.dimensions[0] ?? 0;\n\t\t\tconst radius = inspected.dimensions[1] ?? 0;\n\t\t\treturn halfCylinder + radius - centerY;\n\t\t}\n\t\tif (inspected.shape === 'cuboid' && inspected.dimensions.length >= 2) {\n\t\t\tconst halfHeight = inspected.dimensions[1] ?? 0;\n\t\t\treturn halfHeight - centerY;\n\t\t}\n\t}\n\n\tconst collisionSize =\n\t\tentity?.options?.collision?.size ??\n\t\tentity?.options?.collisionSize ??\n\t\tentity?.options?.size;\n\tconst height = collisionSize?.y ?? 0;\n\tif (height <= 0) {\n\t\treturn 0;\n\t}\n\n\tconst collisionPosition =\n\t\tentity?.options?.collision?.position ??\n\t\tentity?.options?.collisionPosition;\n\tconst centerY = collisionPosition?.y ?? height / 2;\n\treturn (height / 2) - centerY;\n}\n\nexport function getGroundSnapTargetY(\n\tentity: any,\n\tsupport: GroundProbeSupportHit,\n\tepsilon: number = GROUND_SNAP_EPSILON,\n): number {\n\treturn support.point.y + getGroundAnchorOffsetY(entity) + epsilon;\n}\n","import type { ColliderDesc } from '@dimforge/rapier3d-compat';\n\n/**\n * Subset of Rapier shape kinds that game-lib introspects for sizing decisions\n * (e.g. ground probes derive their cast box from the entity collider). Mirrors\n * the public Rapier shape vocabulary, kept as string literals so callers can\n * branch without depending on Rapier's internal shape enum.\n */\nexport type ColliderShapeKind =\n\t| 'ball'\n\t| 'cuboid'\n\t| 'capsule'\n\t| 'cone'\n\t| 'cylinder'\n\t| 'heightfield'\n\t| 'convexHull'\n\t| 'trimesh';\n\n/**\n * Plain, runtime-agnostic snapshot of a {@link ColliderDesc}'s shape and\n * placement. Only contains the fields game-lib needs today; extend as new\n * call sites appear.\n *\n * - `shape` — discriminator for the underlying Rapier shape.\n * - `dimensions` — shape-specific numbers (see {@link inspectColliderDesc}).\n * - `translation` — local offset relative to the parent body, when set.\n * - `vertices` / `indices` — raw geometry payload for `convexHull` and\n * `trimesh` shapes; tagged via `__zylemShapeData` at construction time.\n */\nexport interface ColliderDescInspection {\n\tshape: ColliderShapeKind;\n\tdimensions: number[];\n\ttranslation?: [number, number, number];\n\tvertices?: number[];\n\tindices?: number[];\n}\n\n/**\n * Read the shape kind, dimensions, and local translation off a Rapier\n * {@link ColliderDesc} without going through the WASM-backed accessors that\n * cannot cross worker boundaries.\n *\n * Layout per shape (matches Rapier's primitive constructors):\n * - `ball` → `[radius]`\n * - `cuboid` → `[halfX, halfY, halfZ]`\n * - `capsule` → `[halfHeight, radius]`\n * - `cone` → `[halfHeight, radius]`\n * - `cylinder` → `[halfHeight, radius]`\n * - `heightfield` → flattened heights array\n * - `convexHull` → flattened vertex array (set via the `__zylemShapeData` tag)\n * - `trimesh` → flattened vertex array (indices ignored here)\n */\nexport function inspectColliderDesc(desc: ColliderDesc): ColliderDescInspection {\n\tconst internal = desc as any;\n\tconst customShapeData = internal.__zylemShapeData as\n\t\t| { shape: 'convexHull'; vertices: number[] }\n\t\t| { shape: 'trimesh'; vertices: number[]; indices: number[] }\n\t\t| undefined;\n\n\tif (customShapeData?.shape === 'convexHull') {\n\t\tconst result = finalize('convexHull', [], internal);\n\t\tresult.vertices = [...customShapeData.vertices];\n\t\treturn result;\n\t}\n\tif (customShapeData?.shape === 'trimesh') {\n\t\tconst result = finalize('trimesh', [], internal);\n\t\tresult.vertices = [...customShapeData.vertices];\n\t\tresult.indices = [...customShapeData.indices];\n\t\treturn result;\n\t}\n\n\tconst shapeType = internal.shape?.type ?? internal.shapeType ?? 0;\n\tconst { shape, dimensions } = extractShapeData(shapeType, internal);\n\treturn finalize(shape, dimensions, internal);\n}\n\nfunction finalize(\n\tshape: ColliderShapeKind,\n\tdimensions: number[],\n\tinternal: any,\n): ColliderDescInspection {\n\tconst result: ColliderDescInspection = { shape, dimensions };\n\tconst t = internal.translation;\n\tif (t && (t.x !== 0 || t.y !== 0 || t.z !== 0)) {\n\t\tresult.translation = [t.x, t.y, t.z];\n\t}\n\treturn result;\n}\n\n/**\n * Rapier shape type enum values (from rapier internals):\n * 0 = Ball, 1 = Cuboid, 2 = Capsule, 6 = Cone, 7 = Cylinder, 11 = HeightField\n */\nfunction extractShapeData(\n\tshapeType: number,\n\tinternal: any,\n): { shape: ColliderShapeKind; dimensions: number[] } {\n\tswitch (shapeType) {\n\t\tcase 0:\n\t\t\treturn {\n\t\t\t\tshape: 'ball',\n\t\t\t\tdimensions: [internal.shape?.radius ?? internal.halfExtents?.x ?? 1],\n\t\t\t};\n\t\tcase 1:\n\t\t\treturn {\n\t\t\t\tshape: 'cuboid',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfExtents?.x ?? internal.halfExtents?.x ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.y ?? internal.halfExtents?.y ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.z ?? internal.halfExtents?.z ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 2:\n\t\t\treturn {\n\t\t\t\tshape: 'capsule',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 0.5,\n\t\t\t\t\tinternal.shape?.radius ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 6:\n\t\t\treturn {\n\t\t\t\tshape: 'cone',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 7:\n\t\t\treturn {\n\t\t\t\tshape: 'cylinder',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 11: {\n\t\t\tconst heights = internal.shape?.heights;\n\t\t\treturn {\n\t\t\t\tshape: 'heightfield',\n\t\t\t\tdimensions: heights ? Array.from(heights) : [],\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\treturn { shape: 'cuboid', dimensions: [0.5, 0.5, 0.5] };\n\t}\n}\n"],"mappings":"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","names":["centerY"]}
|
package/dist/chunk-MJFMNRMZ.js
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createThrusterInputComponent,
|
|
3
|
-
createThrusterMovementComponent
|
|
4
|
-
} from "./chunk-IZJFUAXB.js";
|
|
5
|
-
import {
|
|
6
|
-
getRotationAngle2D,
|
|
7
|
-
normalizeDirection2DInto
|
|
8
|
-
} from "./chunk-Y7YIAWPW.js";
|
|
9
|
-
import {
|
|
10
|
-
SyncStateMachine,
|
|
11
|
-
t
|
|
12
|
-
} from "./chunk-4URF65BR.js";
|
|
13
|
-
import {
|
|
14
|
-
defineBehavior
|
|
15
|
-
} from "./chunk-EZNCCO4L.js";
|
|
16
|
-
|
|
17
|
-
// src/lib/behaviors/thruster/thruster-fsm.ts
|
|
18
|
-
var ThrusterState = /* @__PURE__ */ ((ThrusterState2) => {
|
|
19
|
-
ThrusterState2["Idle"] = "idle";
|
|
20
|
-
ThrusterState2["Active"] = "active";
|
|
21
|
-
ThrusterState2["Boosting"] = "boosting";
|
|
22
|
-
ThrusterState2["Disabled"] = "disabled";
|
|
23
|
-
ThrusterState2["Docked"] = "docked";
|
|
24
|
-
return ThrusterState2;
|
|
25
|
-
})(ThrusterState || {});
|
|
26
|
-
var ThrusterEvent = /* @__PURE__ */ ((ThrusterEvent2) => {
|
|
27
|
-
ThrusterEvent2["Activate"] = "activate";
|
|
28
|
-
ThrusterEvent2["Deactivate"] = "deactivate";
|
|
29
|
-
ThrusterEvent2["Boost"] = "boost";
|
|
30
|
-
ThrusterEvent2["EndBoost"] = "endBoost";
|
|
31
|
-
ThrusterEvent2["Disable"] = "disable";
|
|
32
|
-
ThrusterEvent2["Enable"] = "enable";
|
|
33
|
-
ThrusterEvent2["Dock"] = "dock";
|
|
34
|
-
ThrusterEvent2["Undock"] = "undock";
|
|
35
|
-
return ThrusterEvent2;
|
|
36
|
-
})(ThrusterEvent || {});
|
|
37
|
-
var ThrusterFSM = class {
|
|
38
|
-
constructor(ctx) {
|
|
39
|
-
this.ctx = ctx;
|
|
40
|
-
this.machine = new SyncStateMachine(
|
|
41
|
-
"idle" /* Idle */,
|
|
42
|
-
[
|
|
43
|
-
// Core transitions
|
|
44
|
-
t("idle" /* Idle */, "activate" /* Activate */, "active" /* Active */),
|
|
45
|
-
t("active" /* Active */, "deactivate" /* Deactivate */, "idle" /* Idle */),
|
|
46
|
-
t("active" /* Active */, "boost" /* Boost */, "boosting" /* Boosting */),
|
|
47
|
-
t("active" /* Active */, "disable" /* Disable */, "disabled" /* Disabled */),
|
|
48
|
-
t("active" /* Active */, "dock" /* Dock */, "docked" /* Docked */),
|
|
49
|
-
t("boosting" /* Boosting */, "endBoost" /* EndBoost */, "active" /* Active */),
|
|
50
|
-
t("boosting" /* Boosting */, "disable" /* Disable */, "disabled" /* Disabled */),
|
|
51
|
-
t("disabled" /* Disabled */, "enable" /* Enable */, "idle" /* Idle */),
|
|
52
|
-
t("docked" /* Docked */, "undock" /* Undock */, "idle" /* Idle */),
|
|
53
|
-
// Self-transitions (no-ops for redundant events)
|
|
54
|
-
t("idle" /* Idle */, "deactivate" /* Deactivate */, "idle" /* Idle */),
|
|
55
|
-
t("active" /* Active */, "activate" /* Activate */, "active" /* Active */)
|
|
56
|
-
]
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
ctx;
|
|
60
|
-
machine;
|
|
61
|
-
/**
|
|
62
|
-
* Get current state
|
|
63
|
-
*/
|
|
64
|
-
getState() {
|
|
65
|
-
return this.machine.getState();
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Dispatch an event to transition state
|
|
69
|
-
*/
|
|
70
|
-
dispatch(event) {
|
|
71
|
-
if (this.machine.can(event)) {
|
|
72
|
-
this.machine.syncDispatch(event);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Update FSM state based on player input.
|
|
77
|
-
* Auto-transitions between Idle/Active to report current state.
|
|
78
|
-
* Does NOT modify input - just observes and reports.
|
|
79
|
-
*/
|
|
80
|
-
update(playerInput) {
|
|
81
|
-
const state = this.machine.getState();
|
|
82
|
-
const hasInput = Math.abs(playerInput.thrust) > 0.01 || Math.abs(playerInput.rotate) > 0.01 || Math.abs(playerInput.thrustX ?? 0) > 0.01 || Math.abs(playerInput.thrustY ?? 0) > 0.01;
|
|
83
|
-
if (hasInput && state === "idle" /* Idle */) {
|
|
84
|
-
this.dispatch("activate" /* Activate */);
|
|
85
|
-
} else if (!hasInput && state === "active" /* Active */) {
|
|
86
|
-
this.dispatch("deactivate" /* Deactivate */);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// src/lib/behaviors/thruster/thruster.system.ts
|
|
92
|
-
var _thrustDirection = { x: 0, y: 0 };
|
|
93
|
-
var ThrusterSystem = class {
|
|
94
|
-
constructor(world) {
|
|
95
|
-
this.world = world;
|
|
96
|
-
}
|
|
97
|
-
world;
|
|
98
|
-
/**
|
|
99
|
-
* Update a single thruster-enabled entity.
|
|
100
|
-
*/
|
|
101
|
-
updateEntity(gameEntity, _dt) {
|
|
102
|
-
if (!gameEntity.physics?.body || !gameEntity.thruster || !gameEntity.$thruster) {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
const e = {
|
|
106
|
-
physics: gameEntity.physics,
|
|
107
|
-
thruster: gameEntity.thruster,
|
|
108
|
-
$thruster: gameEntity.$thruster
|
|
109
|
-
};
|
|
110
|
-
const body = e.physics.body;
|
|
111
|
-
const thruster = e.thruster;
|
|
112
|
-
const input = e.$thruster;
|
|
113
|
-
if (thruster.linearDamping != null && typeof body.setLinearDamping === "function") {
|
|
114
|
-
body.setLinearDamping(thruster.linearDamping);
|
|
115
|
-
}
|
|
116
|
-
const rotationZ = getRotationAngle2D(body.rotation());
|
|
117
|
-
const currentVel = body.linvel();
|
|
118
|
-
const hasVectorThrust = normalizeDirection2DInto(input.thrustX, input.thrustY, _thrustDirection);
|
|
119
|
-
if (hasVectorThrust) {
|
|
120
|
-
const thrustScale = Math.min(1, Math.hypot(input.thrustX, input.thrustY));
|
|
121
|
-
const thrustAmount = thruster.linearThrust * thrustScale * 0.1;
|
|
122
|
-
body.setLinvel({
|
|
123
|
-
x: currentVel.x + _thrustDirection.x * thrustAmount,
|
|
124
|
-
y: currentVel.y + _thrustDirection.y * thrustAmount,
|
|
125
|
-
z: currentVel.z
|
|
126
|
-
}, true);
|
|
127
|
-
} else if (input.thrust !== 0) {
|
|
128
|
-
const forwardX = Math.sin(-rotationZ);
|
|
129
|
-
const forwardY = Math.cos(-rotationZ);
|
|
130
|
-
const thrustAmount = thruster.linearThrust * input.thrust * 0.1;
|
|
131
|
-
body.setLinvel({
|
|
132
|
-
x: currentVel.x + forwardX * thrustAmount,
|
|
133
|
-
y: currentVel.y + forwardY * thrustAmount,
|
|
134
|
-
z: currentVel.z
|
|
135
|
-
}, true);
|
|
136
|
-
}
|
|
137
|
-
if (input.rotate !== 0) {
|
|
138
|
-
body.setAngvel({ x: 0, y: 0, z: -thruster.angularThrust * input.rotate }, true);
|
|
139
|
-
} else {
|
|
140
|
-
const angVel = body.angvel();
|
|
141
|
-
body.setAngvel({ x: angVel.x, y: angVel.y, z: 0 }, true);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
update(dt) {
|
|
145
|
-
if (!this.world?.collisionMap) return;
|
|
146
|
-
for (const [, entity] of this.world.collisionMap) {
|
|
147
|
-
this.updateEntity(entity, dt);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
// src/lib/behaviors/thruster/thruster.descriptor.ts
|
|
153
|
-
var defaultOptions = {
|
|
154
|
-
linearThrust: 10,
|
|
155
|
-
angularThrust: 5,
|
|
156
|
-
linearDamping: void 0
|
|
157
|
-
};
|
|
158
|
-
var THRUSTER_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:thruster");
|
|
159
|
-
var ThrusterBehaviorSystem = class {
|
|
160
|
-
constructor(world, wasmStage, getBehaviorLinks) {
|
|
161
|
-
this.wasmStage = wasmStage;
|
|
162
|
-
this.getBehaviorLinks = getBehaviorLinks;
|
|
163
|
-
this.movementBehavior = new ThrusterSystem(world);
|
|
164
|
-
}
|
|
165
|
-
wasmStage;
|
|
166
|
-
getBehaviorLinks;
|
|
167
|
-
movementBehavior;
|
|
168
|
-
attachedRuntimeSlots = /* @__PURE__ */ new Set();
|
|
169
|
-
update(_ecs, delta) {
|
|
170
|
-
const links = this.getBehaviorLinks?.(THRUSTER_BEHAVIOR_KEY);
|
|
171
|
-
if (!links) return;
|
|
172
|
-
for (const link of links) {
|
|
173
|
-
const gameEntity = link.entity;
|
|
174
|
-
const thrusterRef = link.ref;
|
|
175
|
-
const options = thrusterRef.options;
|
|
176
|
-
if (!gameEntity.thruster) {
|
|
177
|
-
gameEntity.thruster = createThrusterMovementComponent(
|
|
178
|
-
options.linearThrust,
|
|
179
|
-
options.angularThrust,
|
|
180
|
-
{ linearDamping: options.linearDamping }
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
if (!gameEntity.$thruster) {
|
|
184
|
-
gameEntity.$thruster = createThrusterInputComponent();
|
|
185
|
-
}
|
|
186
|
-
if (!thrusterRef.fsm && gameEntity.$thruster) {
|
|
187
|
-
thrusterRef.fsm = new ThrusterFSM({ input: gameEntity.$thruster });
|
|
188
|
-
}
|
|
189
|
-
if (thrusterRef.fsm && gameEntity.$thruster) {
|
|
190
|
-
thrusterRef.fsm.update({
|
|
191
|
-
thrust: gameEntity.$thruster.thrust,
|
|
192
|
-
rotate: gameEntity.$thruster.rotate,
|
|
193
|
-
thrustX: gameEntity.$thruster.thrustX,
|
|
194
|
-
thrustY: gameEntity.$thruster.thrustY
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
const handle = gameEntity.runtimeHandle ?? -1;
|
|
198
|
-
if (this.wasmStage && handle >= 0) {
|
|
199
|
-
this.ensureWasmAttached(handle, options);
|
|
200
|
-
const input = gameEntity.$thruster;
|
|
201
|
-
if (input) {
|
|
202
|
-
this.wasmStage.setThrusterInput(handle, input.thrust, input.rotate);
|
|
203
|
-
}
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
206
|
-
if (!gameEntity.body) continue;
|
|
207
|
-
if (!gameEntity.physics) {
|
|
208
|
-
gameEntity.physics = { body: gameEntity.body };
|
|
209
|
-
}
|
|
210
|
-
this.movementBehavior.updateEntity(gameEntity, delta);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
ensureWasmAttached(handle, options) {
|
|
214
|
-
if (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;
|
|
215
|
-
this.wasmStage.attachThruster(handle, {
|
|
216
|
-
maxSpeed: 50,
|
|
217
|
-
acceleration: options.linearThrust,
|
|
218
|
-
turnRateRadPerSec: options.angularThrust,
|
|
219
|
-
linearDamping: options.linearDamping ?? 0
|
|
220
|
-
});
|
|
221
|
-
this.attachedRuntimeSlots.add(handle);
|
|
222
|
-
}
|
|
223
|
-
destroy(_ecs) {
|
|
224
|
-
this.attachedRuntimeSlots.clear();
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
var ThrusterBehavior = defineBehavior({
|
|
228
|
-
name: "thruster",
|
|
229
|
-
defaultOptions,
|
|
230
|
-
systemFactory: (ctx) => new ThrusterBehaviorSystem(ctx.world, ctx.wasmStage ?? null, ctx.getBehaviorLinks)
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
export {
|
|
234
|
-
ThrusterState,
|
|
235
|
-
ThrusterEvent,
|
|
236
|
-
ThrusterFSM,
|
|
237
|
-
ThrusterSystem,
|
|
238
|
-
ThrusterBehavior
|
|
239
|
-
};
|
|
240
|
-
//# sourceMappingURL=chunk-MJFMNRMZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/thruster/thruster-fsm.ts","../src/lib/behaviors/thruster/thruster.system.ts","../src/lib/behaviors/thruster/thruster.descriptor.ts"],"sourcesContent":["/**\n * ThrusterFSM\n * \n * State machine controller for thruster behavior.\n * FSM does NOT touch physics or ThrusterSystem - it only writes ThrusterInputComponent.\n */\n\nimport { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport type { ThrusterInputComponent } from './components';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM State Model\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ThrusterState {\n\tIdle = 'idle',\n\tActive = 'active',\n\tBoosting = 'boosting',\n\tDisabled = 'disabled',\n\tDocked = 'docked',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ThrusterEvent {\n\tActivate = 'activate',\n\tDeactivate = 'deactivate',\n\tBoost = 'boost',\n\tEndBoost = 'endBoost',\n\tDisable = 'disable',\n\tEnable = 'enable',\n\tDock = 'dock',\n\tUndock = 'undock',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM Context Object\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ThrusterFSMContext {\n\tinput: ThrusterInputComponent;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Player Input (raw input from controller/keyboard)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PlayerInput {\n\tthrust: number;\n\trotate: number;\n\tthrustX?: number;\n\tthrustY?: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ThrusterFSM Controller\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class ThrusterFSM {\n\tmachine: SyncStateMachine<ThrusterState, ThrusterEvent, never>;\n\n\tconstructor(private ctx: ThrusterFSMContext) {\n\t\tthis.machine = new SyncStateMachine<ThrusterState, ThrusterEvent, never>(\n\t\t\tThrusterState.Idle,\n\t\t\t[\n\t\t\t\t// Core transitions\n\t\t\t\tt(ThrusterState.Idle, ThrusterEvent.Activate, ThrusterState.Active),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Deactivate, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Boost, ThrusterState.Boosting),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Disable, ThrusterState.Disabled),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Dock, ThrusterState.Docked),\n\t\t\t\tt(ThrusterState.Boosting, ThrusterEvent.EndBoost, ThrusterState.Active),\n\t\t\t\tt(ThrusterState.Boosting, ThrusterEvent.Disable, ThrusterState.Disabled),\n\t\t\t\tt(ThrusterState.Disabled, ThrusterEvent.Enable, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Docked, ThrusterEvent.Undock, ThrusterState.Idle),\n\t\t\t\t// Self-transitions (no-ops for redundant events)\n\t\t\t\tt(ThrusterState.Idle, ThrusterEvent.Deactivate, ThrusterState.Idle),\n\t\t\t\tt(ThrusterState.Active, ThrusterEvent.Activate, ThrusterState.Active),\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Get current state\n\t */\n\tgetState(): ThrusterState {\n\t\treturn this.machine.getState();\n\t}\n\n\t/**\n\t * Dispatch an event to transition state\n\t */\n\tdispatch(event: ThrusterEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n\n\t/**\n\t * Update FSM state based on player input.\n\t * Auto-transitions between Idle/Active to report current state.\n\t * Does NOT modify input - just observes and reports.\n\t */\n\tupdate(playerInput: PlayerInput): void {\n\t\tconst state = this.machine.getState();\n\t\tconst hasInput =\n\t\t\tMath.abs(playerInput.thrust) > 0.01\n\t\t\t|| Math.abs(playerInput.rotate) > 0.01\n\t\t\t|| Math.abs(playerInput.thrustX ?? 0) > 0.01\n\t\t\t|| Math.abs(playerInput.thrustY ?? 0) > 0.01;\n\n\t\t// Auto-transition to report state based on input\n\t\tif (hasInput && state === ThrusterState.Idle) {\n\t\t\tthis.dispatch(ThrusterEvent.Activate);\n\t\t} else if (!hasInput && state === ThrusterState.Active) {\n\t\t\tthis.dispatch(ThrusterEvent.Deactivate);\n\t\t}\n\t}\n}\n","/**\n * ThrusterSystem\n * \n * This is the heart of the thruster movement system - a pure, stateless force generator.\n * Works identically for player, AI, and replay.\n */\n\nimport type { ZylemWorld } from '../../collision/world';\nimport type { PhysicsBodyComponent } from '../components';\nimport type { ThrusterMovementComponent, ThrusterInputComponent } from './components';\nimport {\n\tgetRotationAngle2D,\n\tnormalizeDirection2DInto,\n\ttype Direction2D,\n} from '../shared/direction-2d';\n\n// Per-frame scratch; normalizeDirection2DInto writes here instead of\n// allocating a fresh direction object per entity per frame.\nconst _thrustDirection: Direction2D = { x: 0, y: 0 };\n\n/**\n * Entity with thruster components\n */\nexport interface ThrusterEntity {\n\tphysics: PhysicsBodyComponent;\n\tthruster: ThrusterMovementComponent;\n\t$thruster: ThrusterInputComponent;\n}\n\n/**\n * ThrusterSystem - Force generator for thruster-equipped entities\n * \n * Responsibilities:\n * - Query entities with PhysicsBody, ThrusterMovement, and ThrusterInput components\n * - Apply velocities based on thrust input (2D mode)\n * - Apply angular velocity based on rotation input\n */\nexport class ThrusterSystem {\n\tconstructor(private world: ZylemWorld | null) {}\n\n\t/**\n\t * Update a single thruster-enabled entity.\n\t */\n\tupdateEntity(gameEntity: any, _dt: number): void {\n\t\tif (!gameEntity.physics?.body || !gameEntity.thruster || !gameEntity.$thruster) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst e: ThrusterEntity = {\n\t\t\tphysics: gameEntity.physics,\n\t\t\tthruster: gameEntity.thruster,\n\t\t\t$thruster: gameEntity.$thruster,\n\t\t};\n\n\t\tconst body = e.physics.body;\n\t\tconst thruster = e.thruster;\n\t\tconst input = e.$thruster;\n\n\t\tif (thruster.linearDamping != null && typeof body.setLinearDamping === 'function') {\n\t\t\tbody.setLinearDamping(thruster.linearDamping);\n\t\t}\n\n\t\t// Get Z rotation from quaternion (for 2D sprites)\n\t\tconst rotationZ = getRotationAngle2D(body.rotation());\n\t\tconst currentVel = body.linvel();\n\t\tconst hasVectorThrust = normalizeDirection2DInto(input.thrustX, input.thrustY, _thrustDirection);\n\n\t\t// --- Linear thrust ---\n\t\tif (hasVectorThrust) {\n\t\t\tconst thrustScale = Math.min(1, Math.hypot(input.thrustX, input.thrustY));\n\t\t\tconst thrustAmount = thruster.linearThrust * thrustScale * 0.1;\n\t\t\tbody.setLinvel({\n\t\t\t\tx: currentVel.x + _thrustDirection.x * thrustAmount,\n\t\t\t\ty: currentVel.y + _thrustDirection.y * thrustAmount,\n\t\t\t\tz: currentVel.z,\n\t\t\t}, true);\n\t\t} else if (input.thrust !== 0) {\n\t\t\tconst forwardX = Math.sin(-rotationZ);\n\t\t\tconst forwardY = Math.cos(-rotationZ);\n\t\t\tconst thrustAmount = thruster.linearThrust * input.thrust * 0.1;\n\t\t\tbody.setLinvel({\n\t\t\t\tx: currentVel.x + forwardX * thrustAmount,\n\t\t\t\ty: currentVel.y + forwardY * thrustAmount,\n\t\t\t\tz: currentVel.z\n\t\t\t}, true);\n\t\t}\n\n\t\t// --- Angular thrust (Z-axis for 2D) ---\n\t\tif (input.rotate !== 0) {\n\t\t\tbody.setAngvel({ x: 0, y: 0, z: -thruster.angularThrust * input.rotate }, true);\n\t\t} else {\n\t\t\t// Stop rotation when no input\n\t\t\tconst angVel = body.angvel();\n\t\t\tbody.setAngvel({ x: angVel.x, y: angVel.y, z: 0 }, true);\n\t\t}\n\t}\n\n\tupdate(dt: number): void {\n\t\tif (!this.world?.collisionMap) return;\n\t\tfor (const [, entity] of this.world.collisionMap) {\n\t\t\tthis.updateEntity(entity, dt);\n\t\t}\n\t}\n}\n","/**\n * Thruster Behavior Descriptor\n * \n * Type-safe descriptor for the thruster behavior system using the new entity.use() API.\n * This wraps the existing ThrusterSystem and components.\n */\n\nimport { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { ThrusterSystem, ThrusterEntity } from './thruster.system';\nimport { ThrusterFSM } from './thruster-fsm';\nimport {\n\tcreateThrusterInputComponent,\n\tcreateThrusterMovementComponent,\n\ttype ThrusterMovementComponent,\n\ttype ThrusterInputComponent,\n} from './components';\nimport type { WasmStageRuntime } from '../../runtime/wasm-stage-runtime';\n\n/**\n * Thruster behavior options (typed for entity.use() autocomplete)\n */\nexport interface ThrusterBehaviorOptions {\n\t/** Forward thrust force (default: 10) */\n\tlinearThrust: number;\n\t/** Rotation torque (default: 5) */\n\tangularThrust: number;\n\t/** Optional linear damping override */\n\tlinearDamping?: number;\n}\n\nconst defaultOptions: ThrusterBehaviorOptions = {\n\tlinearThrust: 10,\n\tangularThrust: 5,\n\tlinearDamping: undefined,\n};\n\nconst THRUSTER_BEHAVIOR_KEY = Symbol.for('zylem:behavior:thruster');\n\n/**\n * Adapter that wraps ThrusterSystem as a BehaviorSystem.\n * \n * This bridges the entity.use() pattern with the ECS component-based approach:\n * - Reads options from entity behaviorRefs\n * - Initializes ThrusterMovementComponent and ThrusterInputComponent on entities\n * - Creates FSM lazily and attaches to BehaviorRef for access via handle.getFSM()\n * - Delegates physics to ThrusterSystem\n * \n * NOTE: Input is controlled by the user via entity.onUpdate() - set entity.input.thrust/rotate\n */\nclass ThrusterBehaviorSystem implements BehaviorSystem {\n\tprivate movementBehavior: ThrusterSystem;\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tworld: import('../../collision/world').ZylemWorld | null,\n\t\tprivate wasmStage: WasmStageRuntime | null,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {\n\t\tthis.movementBehavior = new ThrusterSystem(world);\n\t}\n\n\tupdate(_ecs: unknown, delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(THRUSTER_BEHAVIOR_KEY);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst gameEntity = link.entity as any;\n\t\t\tconst thrusterRef = link.ref as any;\n\n\t\t\tconst options = thrusterRef.options as ThrusterBehaviorOptions;\n\n\t\t\tif (!gameEntity.thruster) {\n\t\t\t\tgameEntity.thruster = createThrusterMovementComponent(\n\t\t\t\t\toptions.linearThrust,\n\t\t\t\t\toptions.angularThrust,\n\t\t\t\t\t{ linearDamping: options.linearDamping },\n\t\t\t\t) as ThrusterMovementComponent;\n\t\t\t}\n\n\t\t\tif (!gameEntity.$thruster) {\n\t\t\t\tgameEntity.$thruster = createThrusterInputComponent() as ThrusterInputComponent;\n\t\t\t}\n\n\t\t\tif (!thrusterRef.fsm && gameEntity.$thruster) {\n\t\t\t\tthrusterRef.fsm = new ThrusterFSM({ input: gameEntity.$thruster });\n\t\t\t}\n\n\t\t\tif (thrusterRef.fsm && gameEntity.$thruster) {\n\t\t\t\tthrusterRef.fsm.update({\n\t\t\t\t\tthrust: gameEntity.$thruster.thrust,\n\t\t\t\t\trotate: gameEntity.$thruster.rotate,\n\t\t\t\t\tthrustX: gameEntity.$thruster.thrustX,\n\t\t\t\t\tthrustY: gameEntity.$thruster.thrustY,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst handle = (gameEntity.runtimeHandle ?? -1) as number;\n\t\t\tif (this.wasmStage && handle >= 0) {\n\t\t\t\tthis.ensureWasmAttached(handle, options);\n\t\t\t\tconst input = gameEntity.$thruster as ThrusterInputComponent | undefined;\n\t\t\t\tif (input) {\n\t\t\t\t\tthis.wasmStage.setThrusterInput(handle, input.thrust, input.rotate);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!gameEntity.body) continue;\n\t\t\tif (!gameEntity.physics) {\n\t\t\t\tgameEntity.physics = { body: gameEntity.body };\n\t\t\t}\n\t\t\tthis.movementBehavior.updateEntity(gameEntity, delta);\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: ThrusterBehaviorOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tthis.wasmStage.attachThruster(handle, {\n\t\t\tmaxSpeed: 50,\n\t\t\tacceleration: options.linearThrust,\n\t\t\tturnRateRadPerSec: options.angularThrust,\n\t\t\tlinearDamping: options.linearDamping ?? 0,\n\t\t});\n\t\tthis.attachedRuntimeSlots.add(handle);\n\t}\n\n\tdestroy(_ecs: unknown): void {\n\t\tthis.attachedRuntimeSlots.clear();\n\t}\n}\n\n/**\n * ThrusterBehavior - typed descriptor for thruster movement.\n * \n * Uses the existing ThrusterSystem under the hood.\n * \n * @example\n * ```typescript\n * import { ThrusterBehavior } from \"@zylem/game-lib/behavior\";\n * \n * const ship = createSprite({ ... });\n * ship.use(ThrusterBehavior, { linearThrust: 15, angularThrust: 8 });\n * ```\n */\nexport const ThrusterBehavior = defineBehavior<ThrusterBehaviorOptions, Record<string, never>, ThrusterEntity>({\n\tname: 'thruster',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew ThrusterBehaviorSystem(ctx.world, ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n});\n"],"mappings":"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","names":["ThrusterState","ThrusterEvent"]}
|
package/dist/chunk-OTLSUYQQ.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// src/lib/capabilities/velocity-intents.ts
|
|
2
|
-
function setVelocityIntent(store, sourceId, vector, options = {}) {
|
|
3
|
-
const prev = store.velocityChannels[sourceId];
|
|
4
|
-
const mode = options.mode ?? prev?.mode ?? "replace";
|
|
5
|
-
const priority = options.priority ?? prev?.priority ?? 0;
|
|
6
|
-
const isAdditiveMerge = mode === "add" && prev?.mode === "add";
|
|
7
|
-
const x = vector.x == null ? prev?.x : isAdditiveMerge ? (prev?.x ?? 0) + vector.x : vector.x;
|
|
8
|
-
const y = vector.y == null ? prev?.y : isAdditiveMerge ? (prev?.y ?? 0) + vector.y : vector.y;
|
|
9
|
-
const z = vector.z == null ? prev?.z : isAdditiveMerge ? (prev?.z ?? 0) + vector.z : vector.z;
|
|
10
|
-
store.velocityChannels[sourceId] = {
|
|
11
|
-
x,
|
|
12
|
-
y,
|
|
13
|
-
z,
|
|
14
|
-
mode,
|
|
15
|
-
priority
|
|
16
|
-
};
|
|
17
|
-
store.dirty.velocityChannels = true;
|
|
18
|
-
}
|
|
19
|
-
function clearVelocityIntent(store, sourceId) {
|
|
20
|
-
if (!(sourceId in store.velocityChannels)) return;
|
|
21
|
-
delete store.velocityChannels[sourceId];
|
|
22
|
-
store.dirty.velocityChannels = true;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export {
|
|
26
|
-
setVelocityIntent,
|
|
27
|
-
clearVelocityIntent
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=chunk-OTLSUYQQ.js.map
|