@zylem/behaviors 0.2.0
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 +26 -0
- package/dist/behavior-system-DYbx-x_-.d.ts +307 -0
- package/dist/chunk-2C3Z5GE7.js +176 -0
- package/dist/chunk-2C3Z5GE7.js.map +1 -0
- package/dist/chunk-2CLT36VB.js +241 -0
- package/dist/chunk-2CLT36VB.js.map +1 -0
- package/dist/chunk-3PYGRHAL.js +35 -0
- package/dist/chunk-3PYGRHAL.js.map +1 -0
- package/dist/chunk-4I6E6DGV.js +212 -0
- package/dist/chunk-4I6E6DGV.js.map +1 -0
- package/dist/chunk-4URF65BR.js +44 -0
- package/dist/chunk-4URF65BR.js.map +1 -0
- package/dist/chunk-6C6NXNEW.js +38 -0
- package/dist/chunk-6C6NXNEW.js.map +1 -0
- package/dist/chunk-ARJWUNRE.js +431 -0
- package/dist/chunk-ARJWUNRE.js.map +1 -0
- package/dist/chunk-BXP4K7RF.js +1205 -0
- package/dist/chunk-BXP4K7RF.js.map +1 -0
- package/dist/chunk-DYLH6K7B.js +44 -0
- package/dist/chunk-DYLH6K7B.js.map +1 -0
- package/dist/chunk-EIWQM6U3.js +27 -0
- package/dist/chunk-EIWQM6U3.js.map +1 -0
- package/dist/chunk-EZNCCO4L.js +14 -0
- package/dist/chunk-EZNCCO4L.js.map +1 -0
- package/dist/chunk-F3KRX2V4.js +457 -0
- package/dist/chunk-F3KRX2V4.js.map +1 -0
- package/dist/chunk-FPTWVCPN.js +53 -0
- package/dist/chunk-FPTWVCPN.js.map +1 -0
- package/dist/chunk-GCNRXAKH.js +37 -0
- package/dist/chunk-GCNRXAKH.js.map +1 -0
- package/dist/chunk-GYURWCIQ.js +1985 -0
- package/dist/chunk-GYURWCIQ.js.map +1 -0
- package/dist/chunk-HZMY3TT4.js +244 -0
- package/dist/chunk-HZMY3TT4.js.map +1 -0
- package/dist/chunk-ID5QJYF5.js +50 -0
- package/dist/chunk-ID5QJYF5.js.map +1 -0
- package/dist/chunk-JAN34G6S.js +552 -0
- package/dist/chunk-JAN34G6S.js.map +1 -0
- package/dist/chunk-K3UNLQ7W.js +118 -0
- package/dist/chunk-K3UNLQ7W.js.map +1 -0
- package/dist/chunk-KDY5N6J4.js +82 -0
- package/dist/chunk-KDY5N6J4.js.map +1 -0
- package/dist/chunk-KOZUNIIE.js +413 -0
- package/dist/chunk-KOZUNIIE.js.map +1 -0
- package/dist/chunk-KS72RZHX.js +30 -0
- package/dist/chunk-KS72RZHX.js.map +1 -0
- package/dist/chunk-LD5SMIB3.js +32 -0
- package/dist/chunk-LD5SMIB3.js.map +1 -0
- package/dist/chunk-OHCPV2NT.js +86 -0
- package/dist/chunk-OHCPV2NT.js.map +1 -0
- package/dist/chunk-OYWFPIHF.js +115 -0
- package/dist/chunk-OYWFPIHF.js.map +1 -0
- package/dist/chunk-POZER3MQ.js +407 -0
- package/dist/chunk-POZER3MQ.js.map +1 -0
- package/dist/chunk-RTRVBEIB.js +56 -0
- package/dist/chunk-RTRVBEIB.js.map +1 -0
- package/dist/chunk-RTVRUNYR.js +29 -0
- package/dist/chunk-RTVRUNYR.js.map +1 -0
- package/dist/chunk-SS7ELMJ7.js +406 -0
- package/dist/chunk-SS7ELMJ7.js.map +1 -0
- package/dist/chunk-STCCNLPC.js +160 -0
- package/dist/chunk-STCCNLPC.js.map +1 -0
- package/dist/chunk-SVLNF434.js +261 -0
- package/dist/chunk-SVLNF434.js.map +1 -0
- package/dist/chunk-UYFOLI2X.js +24 -0
- package/dist/chunk-UYFOLI2X.js.map +1 -0
- package/dist/chunk-VAN4WW3F.js +67 -0
- package/dist/chunk-VAN4WW3F.js.map +1 -0
- package/dist/chunk-WOMHL23C.js +369 -0
- package/dist/chunk-WOMHL23C.js.map +1 -0
- package/dist/chunk-WWVD5DR5.js +120 -0
- package/dist/chunk-WWVD5DR5.js.map +1 -0
- package/dist/chunk-XG2YMCJW.js +201 -0
- package/dist/chunk-XG2YMCJW.js.map +1 -0
- package/dist/chunk-XIJNE67Y.js +210 -0
- package/dist/chunk-XIJNE67Y.js.map +1 -0
- package/dist/chunk-Y6UJOUE5.js +44 -0
- package/dist/chunk-Y6UJOUE5.js.map +1 -0
- package/dist/chunk-YUO6SKJD.js +348 -0
- package/dist/chunk-YUO6SKJD.js.map +1 -0
- package/dist/components--hjBMTnz.d.ts +120 -0
- package/dist/components-B29WHGQN.d.ts +39 -0
- package/dist/components-BWG1GkZA.d.ts +20 -0
- package/dist/components-XCpL6IYt.d.ts +18 -0
- package/dist/components-qWwOsvwh.d.ts +43 -0
- package/dist/cooldown.d.ts +116 -0
- package/dist/cooldown.js +20 -0
- package/dist/cooldown.js.map +1 -0
- package/dist/coordinators/boundary-ricochet-3d.d.ts +19 -0
- package/dist/coordinators/boundary-ricochet-3d.js +8 -0
- package/dist/coordinators/boundary-ricochet-3d.js.map +1 -0
- package/dist/coordinators/boundary-ricochet.d.ts +34 -0
- package/dist/coordinators/boundary-ricochet.js +8 -0
- package/dist/coordinators/boundary-ricochet.js.map +1 -0
- package/dist/coordinators/first-person-shooter.d.ts +35 -0
- package/dist/coordinators/first-person-shooter.js +9 -0
- package/dist/coordinators/first-person-shooter.js.map +1 -0
- package/dist/coordinators/multidirectional-space-shooter.d.ts +27 -0
- package/dist/coordinators/multidirectional-space-shooter.js +10 -0
- package/dist/coordinators/multidirectional-space-shooter.js.map +1 -0
- package/dist/coordinators/top-down-shooter.d.ts +27 -0
- package/dist/coordinators/top-down-shooter.js +10 -0
- package/dist/coordinators/top-down-shooter.js.map +1 -0
- package/dist/core.d.ts +25 -0
- package/dist/core.js +327 -0
- package/dist/core.js.map +1 -0
- package/dist/destructible-3d.d.ts +42 -0
- package/dist/destructible-3d.js +13 -0
- package/dist/destructible-3d.js.map +1 -0
- package/dist/destructible-prebake.d.ts +28 -0
- package/dist/destructible-prebake.js +23 -0
- package/dist/destructible-prebake.js.map +1 -0
- package/dist/entity-types-CmtQ-IBp.d.ts +15 -0
- package/dist/first-person-perspective-C9Mptl0-.d.ts +23 -0
- package/dist/first-person.d.ts +204 -0
- package/dist/first-person.js +27 -0
- package/dist/first-person.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +263 -0
- package/dist/index.js.map +1 -0
- package/dist/jumper-2d.d.ts +113 -0
- package/dist/jumper-2d.js +27 -0
- package/dist/jumper-2d.js.map +1 -0
- package/dist/jumper-3d.d.ts +164 -0
- package/dist/jumper-3d.js +29 -0
- package/dist/jumper-3d.js.map +1 -0
- package/dist/moveable-BCRpjAQb.d.ts +176 -0
- package/dist/particle-emitter/presets.d.ts +46 -0
- package/dist/particle-emitter/presets.js +15 -0
- package/dist/particle-emitter/presets.js.map +1 -0
- package/dist/particle-emitter.d.ts +78 -0
- package/dist/particle-emitter.js +15 -0
- package/dist/particle-emitter.js.map +1 -0
- package/dist/payload-BQzu-oY_.d.ts +89 -0
- package/dist/platformer-3d.d.ts +347 -0
- package/dist/platformer-3d.js +23 -0
- package/dist/platformer-3d.js.map +1 -0
- package/dist/ricochet-2d.d.ts +274 -0
- package/dist/ricochet-2d.js +16 -0
- package/dist/ricochet-2d.js.map +1 -0
- package/dist/ricochet-3d.d.ts +116 -0
- package/dist/ricochet-3d.js +16 -0
- package/dist/ricochet-3d.js.map +1 -0
- package/dist/runtime-2d.d.ts +2 -0
- package/dist/runtime-2d.js +32 -0
- package/dist/runtime-2d.js.map +1 -0
- package/dist/runtime-pong.d.ts +92 -0
- package/dist/runtime-pong.js +38 -0
- package/dist/runtime-pong.js.map +1 -0
- package/dist/screen-visibility.d.ts +74 -0
- package/dist/screen-visibility.js +10 -0
- package/dist/screen-visibility.js.map +1 -0
- package/dist/screen-wrap.d.ts +86 -0
- package/dist/screen-wrap.js +16 -0
- package/dist/screen-wrap.js.map +1 -0
- package/dist/shooter-2d.d.ts +77 -0
- package/dist/shooter-2d.js +12 -0
- package/dist/shooter-2d.js.map +1 -0
- package/dist/spark-DDlIg1nM.d.ts +148 -0
- package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
- package/dist/thruster.d.ts +132 -0
- package/dist/thruster.js +26 -0
- package/dist/thruster.js.map +1 -0
- package/dist/top-down-movement.d.ts +40 -0
- package/dist/top-down-movement.js +20 -0
- package/dist/top-down-movement.js.map +1 -0
- package/dist/use-behavior-D_82jAL3.d.ts +13 -0
- package/dist/vector-Bm65-FOG.d.ts +45 -0
- package/dist/world-boundary-2d.d.ts +141 -0
- package/dist/world-boundary-2d.js +21 -0
- package/dist/world-boundary-2d.js.map +1 -0
- package/dist/world-boundary-3d.d.ts +75 -0
- package/dist/world-boundary-3d.js +21 -0
- package/dist/world-boundary-3d.js.map +1 -0
- package/package.json +161 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GroundProbe3D,
|
|
3
|
+
getGroundAnchorOffsetY,
|
|
4
|
+
getGroundSnapTargetY
|
|
5
|
+
} from "./chunk-SVLNF434.js";
|
|
6
|
+
import {
|
|
7
|
+
setVelocityIntent
|
|
8
|
+
} from "./chunk-RTVRUNYR.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/jumper-2d/components.ts
|
|
18
|
+
function createJumpConfig2D(options = {}) {
|
|
19
|
+
return {
|
|
20
|
+
jumpHeight: options.jumpHeight ?? 2.5,
|
|
21
|
+
gravity: options.gravity ?? 20,
|
|
22
|
+
maxFallSpeed: options.maxFallSpeed,
|
|
23
|
+
maxJumps: options.maxJumps ?? 1,
|
|
24
|
+
resetJumpsOnGround: options.resetJumpsOnGround ?? true,
|
|
25
|
+
coyoteTimeMs: options.coyoteTimeMs ?? 100,
|
|
26
|
+
jumpBufferMs: options.jumpBufferMs ?? 80,
|
|
27
|
+
minTimeBetweenJumpsMs: options.minTimeBetweenJumpsMs,
|
|
28
|
+
variableJump: options.variableJump
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function createJumpInput2D() {
|
|
32
|
+
return {
|
|
33
|
+
jumpPressed: false,
|
|
34
|
+
jumpHeld: false,
|
|
35
|
+
jumpReleased: false,
|
|
36
|
+
fastFall: false
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function createJumpState2D() {
|
|
40
|
+
return {
|
|
41
|
+
jumpsUsed: 0,
|
|
42
|
+
lastJumpTimeMs: 0,
|
|
43
|
+
bufferedJumpMs: 0,
|
|
44
|
+
coyoteMs: 0,
|
|
45
|
+
isJumping: false,
|
|
46
|
+
jumpHoldMs: 0,
|
|
47
|
+
jumpCutApplied: false
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/lib/behaviors/jumper-2d/jumper-2d.behavior.ts
|
|
52
|
+
function jumpVelocityFromHeight(gravity, height) {
|
|
53
|
+
return Math.sqrt(2 * gravity * height);
|
|
54
|
+
}
|
|
55
|
+
var Jumper2DTickEvent = /* @__PURE__ */ ((Jumper2DTickEvent3) => {
|
|
56
|
+
Jumper2DTickEvent3["None"] = "none";
|
|
57
|
+
Jumper2DTickEvent3["Jump"] = "jump";
|
|
58
|
+
Jumper2DTickEvent3["Fall"] = "fall";
|
|
59
|
+
Jumper2DTickEvent3["Land"] = "land";
|
|
60
|
+
return Jumper2DTickEvent3;
|
|
61
|
+
})(Jumper2DTickEvent || {});
|
|
62
|
+
var Jumper2DBehavior = class {
|
|
63
|
+
tick(config, input, ctx, state) {
|
|
64
|
+
const dtMs = ctx.dt * 1e3;
|
|
65
|
+
const now = performance.now();
|
|
66
|
+
let event = "none" /* None */;
|
|
67
|
+
let jumpedThisFrame = false;
|
|
68
|
+
if (ctx.isGrounded) {
|
|
69
|
+
state.coyoteMs = config.coyoteTimeMs;
|
|
70
|
+
if (config.resetJumpsOnGround) {
|
|
71
|
+
state.jumpsUsed = 0;
|
|
72
|
+
}
|
|
73
|
+
if (state.isJumping) {
|
|
74
|
+
state.isJumping = false;
|
|
75
|
+
state.jumpCutApplied = false;
|
|
76
|
+
event = "land" /* Land */;
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
state.coyoteMs = Math.max(0, state.coyoteMs - dtMs);
|
|
80
|
+
}
|
|
81
|
+
if (input.jumpPressed) {
|
|
82
|
+
state.bufferedJumpMs = config.jumpBufferMs;
|
|
83
|
+
} else {
|
|
84
|
+
state.bufferedJumpMs = Math.max(0, state.bufferedJumpMs - dtMs);
|
|
85
|
+
}
|
|
86
|
+
if (state.isJumping && input.jumpHeld) {
|
|
87
|
+
state.jumpHoldMs += dtMs;
|
|
88
|
+
}
|
|
89
|
+
const wantsJump = state.bufferedJumpMs > 0;
|
|
90
|
+
const isFirstJump = ctx.isGrounded || state.coyoteMs > 0 && state.jumpsUsed === 0;
|
|
91
|
+
const hasAirJumps = state.jumpsUsed > 0 && state.jumpsUsed < config.maxJumps;
|
|
92
|
+
const canJump = isFirstJump || hasAirJumps;
|
|
93
|
+
const cooldownOk = config.minTimeBetweenJumpsMs == null || now - state.lastJumpTimeMs >= config.minTimeBetweenJumpsMs;
|
|
94
|
+
if (wantsJump && canJump && cooldownOk) {
|
|
95
|
+
ctx.setVerticalVelocity(jumpVelocityFromHeight(config.gravity, config.jumpHeight));
|
|
96
|
+
jumpedThisFrame = true;
|
|
97
|
+
state.jumpsUsed++;
|
|
98
|
+
state.lastJumpTimeMs = now;
|
|
99
|
+
state.bufferedJumpMs = 0;
|
|
100
|
+
state.coyoteMs = 0;
|
|
101
|
+
state.isJumping = true;
|
|
102
|
+
state.jumpHoldMs = 0;
|
|
103
|
+
state.jumpCutApplied = false;
|
|
104
|
+
event = "jump" /* Jump */;
|
|
105
|
+
}
|
|
106
|
+
if (!ctx.isGrounded || jumpedThisFrame) {
|
|
107
|
+
let gravityMul = 1;
|
|
108
|
+
const isFalling = ctx.velocityY < 0;
|
|
109
|
+
if (isFalling) {
|
|
110
|
+
gravityMul = input.fastFall ? 1.75 : 1;
|
|
111
|
+
if (event !== "land" /* Land */) {
|
|
112
|
+
event = "fall" /* Fall */;
|
|
113
|
+
}
|
|
114
|
+
} else if (state.isJumping) {
|
|
115
|
+
const variableJump = config.variableJump;
|
|
116
|
+
if (variableJump?.enabled && !state.jumpCutApplied) {
|
|
117
|
+
const holdExpired = variableJump.maxHoldMs != null && state.jumpHoldMs >= variableJump.maxHoldMs;
|
|
118
|
+
if (!input.jumpHeld || holdExpired) {
|
|
119
|
+
gravityMul = variableJump.cutGravityMultiplier;
|
|
120
|
+
state.jumpCutApplied = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
let newVelocityY = ctx.velocityY - config.gravity * gravityMul * ctx.dt;
|
|
125
|
+
if (config.maxFallSpeed != null) {
|
|
126
|
+
newVelocityY = Math.max(-config.maxFallSpeed, newVelocityY);
|
|
127
|
+
}
|
|
128
|
+
ctx.setVerticalVelocity(newVelocityY);
|
|
129
|
+
} else {
|
|
130
|
+
ctx.setVerticalVelocity(0);
|
|
131
|
+
}
|
|
132
|
+
return { event };
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// src/lib/behaviors/jumper-2d/jumper-2d-fsm.ts
|
|
137
|
+
var Jumper2DState = /* @__PURE__ */ ((Jumper2DState2) => {
|
|
138
|
+
Jumper2DState2["Grounded"] = "grounded";
|
|
139
|
+
Jumper2DState2["Jumping"] = "jumping";
|
|
140
|
+
Jumper2DState2["Falling"] = "falling";
|
|
141
|
+
return Jumper2DState2;
|
|
142
|
+
})(Jumper2DState || {});
|
|
143
|
+
var Jumper2DEvent = /* @__PURE__ */ ((Jumper2DEvent2) => {
|
|
144
|
+
Jumper2DEvent2["Jump"] = "jump";
|
|
145
|
+
Jumper2DEvent2["Fall"] = "fall";
|
|
146
|
+
Jumper2DEvent2["Land"] = "land";
|
|
147
|
+
return Jumper2DEvent2;
|
|
148
|
+
})(Jumper2DEvent || {});
|
|
149
|
+
var Jumper2DFSM = class {
|
|
150
|
+
constructor(ctx) {
|
|
151
|
+
this.ctx = ctx;
|
|
152
|
+
this.machine = new SyncStateMachine(
|
|
153
|
+
"grounded" /* Grounded */,
|
|
154
|
+
[
|
|
155
|
+
t("grounded" /* Grounded */, "jump" /* Jump */, "jumping" /* Jumping */),
|
|
156
|
+
t("grounded" /* Grounded */, "fall" /* Fall */, "falling" /* Falling */),
|
|
157
|
+
t("grounded" /* Grounded */, "land" /* Land */, "grounded" /* Grounded */),
|
|
158
|
+
t("jumping" /* Jumping */, "fall" /* Fall */, "falling" /* Falling */),
|
|
159
|
+
t("jumping" /* Jumping */, "land" /* Land */, "grounded" /* Grounded */),
|
|
160
|
+
t("jumping" /* Jumping */, "jump" /* Jump */, "jumping" /* Jumping */),
|
|
161
|
+
t("falling" /* Falling */, "land" /* Land */, "grounded" /* Grounded */),
|
|
162
|
+
t("falling" /* Falling */, "jump" /* Jump */, "jumping" /* Jumping */),
|
|
163
|
+
t("falling" /* Falling */, "fall" /* Fall */, "falling" /* Falling */)
|
|
164
|
+
]
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
ctx;
|
|
168
|
+
machine;
|
|
169
|
+
getState() {
|
|
170
|
+
return this.machine.getState();
|
|
171
|
+
}
|
|
172
|
+
dispatch(event) {
|
|
173
|
+
if (this.machine.can(event)) {
|
|
174
|
+
this.machine.syncDispatch(event);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
isJumping() {
|
|
178
|
+
return this.getState() === "jumping" /* Jumping */;
|
|
179
|
+
}
|
|
180
|
+
isGrounded() {
|
|
181
|
+
return this.getState() === "grounded" /* Grounded */;
|
|
182
|
+
}
|
|
183
|
+
getJumpsUsed() {
|
|
184
|
+
return this.ctx.state.jumpsUsed;
|
|
185
|
+
}
|
|
186
|
+
applyTickEvent(tickEvent, isGrounded) {
|
|
187
|
+
switch (tickEvent) {
|
|
188
|
+
case "jump":
|
|
189
|
+
this.dispatch("jump" /* Jump */);
|
|
190
|
+
break;
|
|
191
|
+
case "fall":
|
|
192
|
+
this.dispatch("fall" /* Fall */);
|
|
193
|
+
break;
|
|
194
|
+
case "land":
|
|
195
|
+
this.dispatch("land" /* Land */);
|
|
196
|
+
break;
|
|
197
|
+
default:
|
|
198
|
+
if (!isGrounded && this.getState() === "grounded" /* Grounded */) {
|
|
199
|
+
this.dispatch("fall" /* Fall */);
|
|
200
|
+
}
|
|
201
|
+
if (isGrounded && this.getState() !== "grounded" /* Grounded */) {
|
|
202
|
+
this.dispatch("land" /* Land */);
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// src/lib/behaviors/jumper-2d/jumper-2d.descriptor.ts
|
|
210
|
+
var defaultOptions = {
|
|
211
|
+
jumpHeight: 2.5,
|
|
212
|
+
gravity: 20,
|
|
213
|
+
maxJumps: 1,
|
|
214
|
+
resetJumpsOnGround: true,
|
|
215
|
+
coyoteTimeMs: 100,
|
|
216
|
+
jumpBufferMs: 80,
|
|
217
|
+
groundRayLength: 1,
|
|
218
|
+
debugGroundProbe: false
|
|
219
|
+
};
|
|
220
|
+
var JUMPER_2D_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:jumper-2d");
|
|
221
|
+
var JUMPER_2D_OFFSETS = [
|
|
222
|
+
{ x: 0, z: 0 },
|
|
223
|
+
{ x: 0.35, z: 0 },
|
|
224
|
+
{ x: -0.35, z: 0 }
|
|
225
|
+
];
|
|
226
|
+
function isJumper2DGrounded(params) {
|
|
227
|
+
if (params.velocityY > 0) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
if (params.snapToGroundDistance != null) {
|
|
231
|
+
return params.supportToi != null && params.supportToi <= params.snapToGroundDistance;
|
|
232
|
+
}
|
|
233
|
+
return params.nearGround === true;
|
|
234
|
+
}
|
|
235
|
+
function shouldSnapJumper2DToGround(support, options, velocityY) {
|
|
236
|
+
return support != null && options.snapToGroundDistance != null && velocityY <= 0 && support.toi <= options.snapToGroundDistance;
|
|
237
|
+
}
|
|
238
|
+
var Jumper2DBehaviorSystem = class {
|
|
239
|
+
constructor(world, scene, wasmStage, getBehaviorLinks) {
|
|
240
|
+
this.world = world;
|
|
241
|
+
this.scene = scene;
|
|
242
|
+
this.wasmStage = wasmStage;
|
|
243
|
+
this.getBehaviorLinks = getBehaviorLinks;
|
|
244
|
+
this.groundProbe = new GroundProbe3D(world);
|
|
245
|
+
}
|
|
246
|
+
world;
|
|
247
|
+
scene;
|
|
248
|
+
wasmStage;
|
|
249
|
+
getBehaviorLinks;
|
|
250
|
+
behavior = new Jumper2DBehavior();
|
|
251
|
+
groundProbe;
|
|
252
|
+
initializedEntities = /* @__PURE__ */ new Set();
|
|
253
|
+
timeSinceGroundedMs = /* @__PURE__ */ new Map();
|
|
254
|
+
wasJumpHeld = /* @__PURE__ */ new Map();
|
|
255
|
+
attachedRuntimeSlots = /* @__PURE__ */ new Set();
|
|
256
|
+
update(_ecs, delta) {
|
|
257
|
+
const links = this.getBehaviorLinks?.(JUMPER_2D_BEHAVIOR_KEY);
|
|
258
|
+
if (!links) return;
|
|
259
|
+
for (const link of links) {
|
|
260
|
+
const gameEntity = link.entity;
|
|
261
|
+
const jumperRef = link.ref;
|
|
262
|
+
const options = jumperRef.options;
|
|
263
|
+
const handle = gameEntity.runtimeHandle ?? -1;
|
|
264
|
+
if (this.wasmStage && handle >= 0) {
|
|
265
|
+
this.ensureWasmAttached(handle, options);
|
|
266
|
+
const input2 = gameEntity.$jumper2d;
|
|
267
|
+
const jumpPressed = !!(input2?.jumpPressed || input2?.jumpHeld);
|
|
268
|
+
this.wasmStage.setJumper2DInput(handle, jumpPressed);
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (!gameEntity.body) continue;
|
|
272
|
+
if (!gameEntity.jumper2d) {
|
|
273
|
+
gameEntity.jumper2d = createJumpConfig2D(options);
|
|
274
|
+
}
|
|
275
|
+
if (!gameEntity.$jumper2d) {
|
|
276
|
+
gameEntity.$jumper2d = createJumpInput2D();
|
|
277
|
+
}
|
|
278
|
+
if (!gameEntity.jumper2dState) {
|
|
279
|
+
gameEntity.jumper2dState = createJumpState2D();
|
|
280
|
+
}
|
|
281
|
+
if (!this.initializedEntities.has(gameEntity.uuid)) {
|
|
282
|
+
this.initializedEntities.add(gameEntity.uuid);
|
|
283
|
+
gameEntity.body.setGravityScale(0, true);
|
|
284
|
+
}
|
|
285
|
+
if (!jumperRef.fsm && gameEntity.jumper2dState) {
|
|
286
|
+
jumperRef.fsm = new Jumper2DFSM({
|
|
287
|
+
state: gameEntity.jumper2dState
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
const rayLength = options.groundRayLength ?? 1;
|
|
291
|
+
const bodyVelocity = gameEntity.body.linvel();
|
|
292
|
+
const probeOriginYOffset = 0.05 - getGroundAnchorOffsetY(gameEntity);
|
|
293
|
+
const support = this.groundProbe.probeSupport(gameEntity, {
|
|
294
|
+
rayLength,
|
|
295
|
+
offsets: JUMPER_2D_OFFSETS,
|
|
296
|
+
mode: "any",
|
|
297
|
+
debug: options.debugGroundProbe ?? false,
|
|
298
|
+
scene: this.scene,
|
|
299
|
+
originYOffset: probeOriginYOffset
|
|
300
|
+
});
|
|
301
|
+
const nearGround = support != null;
|
|
302
|
+
const isGrounded = isJumper2DGrounded({
|
|
303
|
+
nearGround,
|
|
304
|
+
velocityY: bodyVelocity.y,
|
|
305
|
+
supportToi: support?.toi ?? null,
|
|
306
|
+
snapToGroundDistance: options.snapToGroundDistance
|
|
307
|
+
});
|
|
308
|
+
if (shouldSnapJumper2DToGround(support, options, bodyVelocity.y)) {
|
|
309
|
+
const currentPosition = gameEntity.body.translation();
|
|
310
|
+
gameEntity.body.setTranslation(
|
|
311
|
+
{
|
|
312
|
+
x: currentPosition.x,
|
|
313
|
+
y: getGroundSnapTargetY(gameEntity, support),
|
|
314
|
+
z: currentPosition.z
|
|
315
|
+
},
|
|
316
|
+
true
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
let timeSinceGroundedMs = this.timeSinceGroundedMs.get(gameEntity.uuid) ?? 0;
|
|
320
|
+
if (isGrounded) {
|
|
321
|
+
timeSinceGroundedMs = 0;
|
|
322
|
+
} else {
|
|
323
|
+
timeSinceGroundedMs += delta * 1e3;
|
|
324
|
+
}
|
|
325
|
+
this.timeSinceGroundedMs.set(gameEntity.uuid, timeSinceGroundedMs);
|
|
326
|
+
const config = gameEntity.jumper2d;
|
|
327
|
+
const input = gameEntity.$jumper2d;
|
|
328
|
+
const state = gameEntity.jumper2dState;
|
|
329
|
+
const previousHeld = this.wasJumpHeld.get(gameEntity.uuid) ?? false;
|
|
330
|
+
const held = input.jumpHeld === true;
|
|
331
|
+
const effectiveInput = {
|
|
332
|
+
...input,
|
|
333
|
+
jumpPressed: input.jumpPressed || held && !previousHeld,
|
|
334
|
+
jumpReleased: input.jumpReleased || !held && previousHeld
|
|
335
|
+
};
|
|
336
|
+
const store = gameEntity.transformStore;
|
|
337
|
+
const ctx = {
|
|
338
|
+
dt: delta,
|
|
339
|
+
velocityY: bodyVelocity.y,
|
|
340
|
+
isGrounded,
|
|
341
|
+
timeSinceGroundedMs,
|
|
342
|
+
setVerticalVelocity: (y) => {
|
|
343
|
+
setVelocityIntent(
|
|
344
|
+
store,
|
|
345
|
+
"jumper-2d",
|
|
346
|
+
{ y },
|
|
347
|
+
{ mode: "replace", priority: 20 }
|
|
348
|
+
);
|
|
349
|
+
ctx.velocityY = y;
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const result = this.behavior.tick(config, effectiveInput, ctx, state);
|
|
353
|
+
this.wasJumpHeld.set(gameEntity.uuid, held);
|
|
354
|
+
if (jumperRef.fsm) {
|
|
355
|
+
jumperRef.fsm.applyTickEvent(result.event, isGrounded);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
ensureWasmAttached(handle, options) {
|
|
360
|
+
if (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;
|
|
361
|
+
const jumpForce = Math.sqrt(2 * (options.gravity ?? 20) * (options.jumpHeight ?? 2.5));
|
|
362
|
+
this.wasmStage.attachJumper2D(handle, {
|
|
363
|
+
jumpForce,
|
|
364
|
+
maxJumps: options.maxJumps ?? 1,
|
|
365
|
+
jumpBufferTime: (options.jumpBufferMs ?? 80) / 1e3,
|
|
366
|
+
coyoteTime: (options.coyoteTimeMs ?? 100) / 1e3,
|
|
367
|
+
gravity: options.gravity ?? 20
|
|
368
|
+
});
|
|
369
|
+
this.attachedRuntimeSlots.add(handle);
|
|
370
|
+
}
|
|
371
|
+
destroy(_ecs) {
|
|
372
|
+
this.groundProbe.destroy();
|
|
373
|
+
this.initializedEntities.clear();
|
|
374
|
+
this.timeSinceGroundedMs.clear();
|
|
375
|
+
this.wasJumpHeld.clear();
|
|
376
|
+
this.attachedRuntimeSlots.clear();
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
var Jumper2D = defineBehavior({
|
|
380
|
+
name: "jumper-2d",
|
|
381
|
+
defaultOptions,
|
|
382
|
+
systemFactory: (ctx) => new Jumper2DBehaviorSystem(ctx.world, ctx.scene, ctx.wasmStage ?? null, ctx.getBehaviorLinks),
|
|
383
|
+
createHandle: (ref) => ({
|
|
384
|
+
getState: () => ref.fsm?.getState() ?? "grounded" /* Grounded */,
|
|
385
|
+
isJumping: () => ref.fsm?.isJumping() ?? false,
|
|
386
|
+
getJumpsUsed: () => ref.fsm?.getJumpsUsed() ?? 0,
|
|
387
|
+
getJumpsRemaining: () => {
|
|
388
|
+
const maxJumps = ref.options.maxJumps ?? 1;
|
|
389
|
+
const used = ref.fsm?.getJumpsUsed() ?? 0;
|
|
390
|
+
return maxJumps - used;
|
|
391
|
+
}
|
|
392
|
+
})
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
export {
|
|
396
|
+
createJumpConfig2D,
|
|
397
|
+
createJumpInput2D,
|
|
398
|
+
createJumpState2D,
|
|
399
|
+
Jumper2DTickEvent,
|
|
400
|
+
Jumper2DBehavior,
|
|
401
|
+
Jumper2DState,
|
|
402
|
+
Jumper2DEvent,
|
|
403
|
+
Jumper2DFSM,
|
|
404
|
+
Jumper2D
|
|
405
|
+
};
|
|
406
|
+
//# sourceMappingURL=chunk-SS7ELMJ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/jumper-2d/components.ts","../src/lib/behaviors/jumper-2d/jumper-2d.behavior.ts","../src/lib/behaviors/jumper-2d/jumper-2d-fsm.ts","../src/lib/behaviors/jumper-2d/jumper-2d.descriptor.ts"],"sourcesContent":["export interface JumpConfig2D {\n\tjumpHeight: number;\n\tgravity: number;\n\tmaxFallSpeed?: number;\n\tmaxJumps: number;\n\tresetJumpsOnGround: boolean;\n\tcoyoteTimeMs: number;\n\tjumpBufferMs: number;\n\tminTimeBetweenJumpsMs?: number;\n\tvariableJump?: {\n\t\tenabled: boolean;\n\t\tcutGravityMultiplier: number;\n\t\tmaxHoldMs?: number;\n\t};\n}\n\nexport function createJumpConfig2D(\n\toptions: Partial<JumpConfig2D> = {},\n): JumpConfig2D {\n\treturn {\n\t\tjumpHeight: options.jumpHeight ?? 2.5,\n\t\tgravity: options.gravity ?? 20,\n\t\tmaxFallSpeed: options.maxFallSpeed,\n\t\tmaxJumps: options.maxJumps ?? 1,\n\t\tresetJumpsOnGround: options.resetJumpsOnGround ?? true,\n\t\tcoyoteTimeMs: options.coyoteTimeMs ?? 100,\n\t\tjumpBufferMs: options.jumpBufferMs ?? 80,\n\t\tminTimeBetweenJumpsMs: options.minTimeBetweenJumpsMs,\n\t\tvariableJump: options.variableJump,\n\t};\n}\n\nexport interface JumpInput2D {\n\tjumpPressed: boolean;\n\tjumpHeld: boolean;\n\tjumpReleased: boolean;\n\tfastFall?: boolean;\n}\n\nexport function createJumpInput2D(): JumpInput2D {\n\treturn {\n\t\tjumpPressed: false,\n\t\tjumpHeld: false,\n\t\tjumpReleased: false,\n\t\tfastFall: false,\n\t};\n}\n\nexport interface JumpContext2D {\n\tdt: number;\n\tvelocityY: number;\n\tisGrounded: boolean;\n\ttimeSinceGroundedMs: number;\n\tsetVerticalVelocity(y: number): void;\n}\n\nexport interface JumpState2D {\n\tjumpsUsed: number;\n\tlastJumpTimeMs: number;\n\tbufferedJumpMs: number;\n\tcoyoteMs: number;\n\tisJumping: boolean;\n\tjumpHoldMs: number;\n\tjumpCutApplied: boolean;\n}\n\nexport function createJumpState2D(): JumpState2D {\n\treturn {\n\t\tjumpsUsed: 0,\n\t\tlastJumpTimeMs: 0,\n\t\tbufferedJumpMs: 0,\n\t\tcoyoteMs: 0,\n\t\tisJumping: false,\n\t\tjumpHoldMs: 0,\n\t\tjumpCutApplied: false,\n\t};\n}\n","import type {\n\tJumpConfig2D,\n\tJumpContext2D,\n\tJumpInput2D,\n\tJumpState2D,\n} from './components';\n\nfunction jumpVelocityFromHeight(gravity: number, height: number): number {\n\treturn Math.sqrt(2 * gravity * height);\n}\n\nexport enum Jumper2DTickEvent {\n\tNone = 'none',\n\tJump = 'jump',\n\tFall = 'fall',\n\tLand = 'land',\n}\n\nexport interface Jumper2DTickResult {\n\tevent: Jumper2DTickEvent;\n}\n\nexport class Jumper2DBehavior {\n\ttick(\n\t\tconfig: JumpConfig2D,\n\t\tinput: JumpInput2D,\n\t\tctx: JumpContext2D,\n\t\tstate: JumpState2D,\n\t): Jumper2DTickResult {\n\t\tconst dtMs = ctx.dt * 1000;\n\t\tconst now = performance.now();\n\t\tlet event = Jumper2DTickEvent.None;\n\t\tlet jumpedThisFrame = false;\n\n\t\tif (ctx.isGrounded) {\n\t\t\tstate.coyoteMs = config.coyoteTimeMs;\n\t\t\tif (config.resetJumpsOnGround) {\n\t\t\t\tstate.jumpsUsed = 0;\n\t\t\t}\n\t\t\tif (state.isJumping) {\n\t\t\t\tstate.isJumping = false;\n\t\t\t\tstate.jumpCutApplied = false;\n\t\t\t\tevent = Jumper2DTickEvent.Land;\n\t\t\t}\n\t\t} else {\n\t\t\tstate.coyoteMs = Math.max(0, state.coyoteMs - dtMs);\n\t\t}\n\n\t\tif (input.jumpPressed) {\n\t\t\tstate.bufferedJumpMs = config.jumpBufferMs;\n\t\t} else {\n\t\t\tstate.bufferedJumpMs = Math.max(0, state.bufferedJumpMs - dtMs);\n\t\t}\n\n\t\tif (state.isJumping && input.jumpHeld) {\n\t\t\tstate.jumpHoldMs += dtMs;\n\t\t}\n\n\t\tconst wantsJump = state.bufferedJumpMs > 0;\n\t\tconst isFirstJump =\n\t\t\tctx.isGrounded || (state.coyoteMs > 0 && state.jumpsUsed === 0);\n\t\tconst hasAirJumps = state.jumpsUsed > 0 && state.jumpsUsed < config.maxJumps;\n\t\tconst canJump = isFirstJump || hasAirJumps;\n\t\tconst cooldownOk =\n\t\t\tconfig.minTimeBetweenJumpsMs == null ||\n\t\t\tnow - state.lastJumpTimeMs >= config.minTimeBetweenJumpsMs;\n\n\t\tif (wantsJump && canJump && cooldownOk) {\n\t\t\tctx.setVerticalVelocity(jumpVelocityFromHeight(config.gravity, config.jumpHeight));\n\t\t\tjumpedThisFrame = true;\n\t\t\tstate.jumpsUsed++;\n\t\t\tstate.lastJumpTimeMs = now;\n\t\t\tstate.bufferedJumpMs = 0;\n\t\t\tstate.coyoteMs = 0;\n\t\t\tstate.isJumping = true;\n\t\t\tstate.jumpHoldMs = 0;\n\t\t\tstate.jumpCutApplied = false;\n\t\t\tevent = Jumper2DTickEvent.Jump;\n\t\t}\n\n\t\tif (!ctx.isGrounded || jumpedThisFrame) {\n\t\t\tlet gravityMul = 1;\n\t\t\tconst isFalling = ctx.velocityY < 0;\n\n\t\t\tif (isFalling) {\n\t\t\t\tgravityMul = input.fastFall ? 1.75 : 1;\n\t\t\t\tif (event !== Jumper2DTickEvent.Land) {\n\t\t\t\t\tevent = Jumper2DTickEvent.Fall;\n\t\t\t\t}\n\t\t\t} else if (state.isJumping) {\n\t\t\t\tconst variableJump = config.variableJump;\n\t\t\t\tif (variableJump?.enabled && !state.jumpCutApplied) {\n\t\t\t\t\tconst holdExpired =\n\t\t\t\t\t\tvariableJump.maxHoldMs != null &&\n\t\t\t\t\t\tstate.jumpHoldMs >= variableJump.maxHoldMs;\n\t\t\t\t\tif (!input.jumpHeld || holdExpired) {\n\t\t\t\t\t\tgravityMul = variableJump.cutGravityMultiplier;\n\t\t\t\t\t\tstate.jumpCutApplied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet newVelocityY = ctx.velocityY - config.gravity * gravityMul * ctx.dt;\n\t\t\tif (config.maxFallSpeed != null) {\n\t\t\t\tnewVelocityY = Math.max(-config.maxFallSpeed, newVelocityY);\n\t\t\t}\n\t\t\tctx.setVerticalVelocity(newVelocityY);\n\t\t} else {\n\t\t\tctx.setVerticalVelocity(0);\n\t\t}\n\n\t\treturn { event };\n\t}\n}\n","import { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport type { JumpState2D } from './components';\n\nexport enum Jumper2DState {\n\tGrounded = 'grounded',\n\tJumping = 'jumping',\n\tFalling = 'falling',\n}\n\nexport enum Jumper2DEvent {\n\tJump = 'jump',\n\tFall = 'fall',\n\tLand = 'land',\n}\n\nexport interface Jumper2DFSMContext {\n\tstate: JumpState2D;\n}\n\nexport class Jumper2DFSM {\n\tmachine: SyncStateMachine<Jumper2DState, Jumper2DEvent, never>;\n\n\tconstructor(private ctx: Jumper2DFSMContext) {\n\t\tthis.machine = new SyncStateMachine<Jumper2DState, Jumper2DEvent, never>(\n\t\t\tJumper2DState.Grounded,\n\t\t\t[\n\t\t\t\tt(Jumper2DState.Grounded, Jumper2DEvent.Jump, Jumper2DState.Jumping),\n\t\t\t\tt(Jumper2DState.Grounded, Jumper2DEvent.Fall, Jumper2DState.Falling),\n\t\t\t\tt(Jumper2DState.Grounded, Jumper2DEvent.Land, Jumper2DState.Grounded),\n\t\t\t\tt(Jumper2DState.Jumping, Jumper2DEvent.Fall, Jumper2DState.Falling),\n\t\t\t\tt(Jumper2DState.Jumping, Jumper2DEvent.Land, Jumper2DState.Grounded),\n\t\t\t\tt(Jumper2DState.Jumping, Jumper2DEvent.Jump, Jumper2DState.Jumping),\n\t\t\t\tt(Jumper2DState.Falling, Jumper2DEvent.Land, Jumper2DState.Grounded),\n\t\t\t\tt(Jumper2DState.Falling, Jumper2DEvent.Jump, Jumper2DState.Jumping),\n\t\t\t\tt(Jumper2DState.Falling, Jumper2DEvent.Fall, Jumper2DState.Falling),\n\t\t\t],\n\t\t);\n\t}\n\n\tgetState(): Jumper2DState {\n\t\treturn this.machine.getState();\n\t}\n\n\tdispatch(event: Jumper2DEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n\n\tisJumping(): boolean {\n\t\treturn this.getState() === Jumper2DState.Jumping;\n\t}\n\n\tisGrounded(): boolean {\n\t\treturn this.getState() === Jumper2DState.Grounded;\n\t}\n\n\tgetJumpsUsed(): number {\n\t\treturn this.ctx.state.jumpsUsed;\n\t}\n\n\tapplyTickEvent(tickEvent: string, isGrounded: boolean): void {\n\t\tswitch (tickEvent) {\n\t\t\tcase 'jump':\n\t\t\t\tthis.dispatch(Jumper2DEvent.Jump);\n\t\t\t\tbreak;\n\t\t\tcase 'fall':\n\t\t\t\tthis.dispatch(Jumper2DEvent.Fall);\n\t\t\t\tbreak;\n\t\t\tcase 'land':\n\t\t\t\tthis.dispatch(Jumper2DEvent.Land);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (!isGrounded && this.getState() === Jumper2DState.Grounded) {\n\t\t\t\t\tthis.dispatch(Jumper2DEvent.Fall);\n\t\t\t\t}\n\t\t\t\tif (isGrounded && this.getState() !== Jumper2DState.Grounded) {\n\t\t\t\t\tthis.dispatch(Jumper2DEvent.Land);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n","import { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { setVelocityIntent } from '../../actions/capabilities/velocity-intents';\nimport {\n\tGroundProbe3D,\n\tgetGroundAnchorOffsetY,\n\tgetGroundSnapTargetY,\n\ttype GroundProbeSupportHit,\n} from '../shared/ground-probe-3d';\nimport {\n\tcreateJumpConfig2D,\n\tcreateJumpInput2D,\n\tcreateJumpState2D,\n\ttype JumpConfig2D,\n\ttype JumpContext2D,\n\ttype JumpInput2D,\n\ttype JumpState2D,\n} from './components';\nimport {\n\tJumper2DBehavior,\n\tJumper2DTickEvent,\n} from './jumper-2d.behavior';\nimport { Jumper2DFSM, Jumper2DState } from './jumper-2d-fsm';\nimport type { WasmStageRuntime } from '../../runtime/wasm-stage-runtime';\n\nexport interface Jumper2DBehaviorOptions {\n\tjumpHeight?: number;\n\tgravity?: number;\n\tmaxFallSpeed?: number;\n\tmaxJumps?: number;\n\tresetJumpsOnGround?: boolean;\n\tcoyoteTimeMs?: number;\n\tjumpBufferMs?: number;\n\tminTimeBetweenJumpsMs?: number;\n\tvariableJump?: JumpConfig2D['variableJump'];\n\tgroundRayLength?: number;\n\tsnapToGroundDistance?: number;\n\tdebugGroundProbe?: boolean;\n}\n\nconst defaultOptions: Jumper2DBehaviorOptions = {\n\tjumpHeight: 2.5,\n\tgravity: 20,\n\tmaxJumps: 1,\n\tresetJumpsOnGround: true,\n\tcoyoteTimeMs: 100,\n\tjumpBufferMs: 80,\n\tgroundRayLength: 1,\n\tdebugGroundProbe: false,\n};\n\nconst JUMPER_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:jumper-2d');\nconst JUMPER_2D_OFFSETS = [\n\t{ x: 0, z: 0 },\n\t{ x: 0.35, z: 0 },\n\t{ x: -0.35, z: 0 },\n] as const;\n\nexport function isJumper2DGrounded(params: {\n\tnearGround?: boolean;\n\tvelocityY: number;\n\tsupportToi?: number | null;\n\tsnapToGroundDistance?: number;\n}): boolean {\n\tif (params.velocityY > 0) {\n\t\treturn false;\n\t}\n\n\tif (params.snapToGroundDistance != null) {\n\t\treturn (\n\t\t\tparams.supportToi != null &&\n\t\t\tparams.supportToi <= params.snapToGroundDistance\n\t\t);\n\t}\n\n\treturn params.nearGround === true;\n}\n\nfunction shouldSnapJumper2DToGround(\n\tsupport: GroundProbeSupportHit | null,\n\toptions: Jumper2DBehaviorOptions,\n\tvelocityY: number,\n): support is GroundProbeSupportHit {\n\treturn (\n\t\tsupport != null &&\n\t\toptions.snapToGroundDistance != null &&\n\t\tvelocityY <= 0 &&\n\t\tsupport.toi <= options.snapToGroundDistance\n\t);\n}\n\nexport interface Jumper2DEntity {\n\tuuid: string;\n\tbody: any;\n\ttransformStore: any;\n\tjumper2d: JumpConfig2D;\n\t$jumper2d: JumpInput2D;\n\tjumper2dState: JumpState2D;\n}\n\nclass Jumper2DBehaviorSystem implements BehaviorSystem {\n\tprivate behavior = new Jumper2DBehavior();\n\tprivate groundProbe: GroundProbe3D;\n\tprivate initializedEntities = new Set<string>();\n\tprivate timeSinceGroundedMs = new Map<string, number>();\n\tprivate wasJumpHeld = new Map<string, boolean>();\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate world: any,\n\t\tprivate scene: any,\n\t\tprivate wasmStage: WasmStageRuntime | null,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {\n\t\tthis.groundProbe = new GroundProbe3D(world);\n\t}\n\n\tupdate(_ecs: unknown, delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(JUMPER_2D_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 jumperRef = link.ref as any;\n\n\t\t\tconst options = jumperRef.options as Jumper2DBehaviorOptions;\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.$jumper2d as JumpInput2D | undefined;\n\t\t\t\tconst jumpPressed = !!(input?.jumpPressed || input?.jumpHeld);\n\t\t\t\tthis.wasmStage.setJumper2DInput(handle, jumpPressed);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!gameEntity.body) continue;\n\n\t\t\tif (!gameEntity.jumper2d) {\n\t\t\t\tgameEntity.jumper2d = createJumpConfig2D(options);\n\t\t\t}\n\t\t\tif (!gameEntity.$jumper2d) {\n\t\t\t\tgameEntity.$jumper2d = createJumpInput2D();\n\t\t\t}\n\t\t\tif (!gameEntity.jumper2dState) {\n\t\t\t\tgameEntity.jumper2dState = createJumpState2D();\n\t\t\t}\n\t\t\tif (!this.initializedEntities.has(gameEntity.uuid)) {\n\t\t\t\tthis.initializedEntities.add(gameEntity.uuid);\n\t\t\t\tgameEntity.body.setGravityScale(0, true);\n\t\t\t}\n\t\t\tif (!jumperRef.fsm && gameEntity.jumper2dState) {\n\t\t\t\tjumperRef.fsm = new Jumper2DFSM({\n\t\t\t\t\tstate: gameEntity.jumper2dState,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst rayLength = options.groundRayLength ?? 1;\n\t\t\tconst bodyVelocity = gameEntity.body.linvel();\n\t\t\tconst probeOriginYOffset = 0.05 - getGroundAnchorOffsetY(gameEntity);\n\t\t\tconst support = this.groundProbe.probeSupport(gameEntity, {\n\t\t\t\trayLength,\n\t\t\t\toffsets: JUMPER_2D_OFFSETS,\n\t\t\t\tmode: 'any',\n\t\t\t\tdebug: options.debugGroundProbe ?? false,\n\t\t\t\tscene: this.scene,\n\t\t\t\toriginYOffset: probeOriginYOffset,\n\t\t\t});\n\t\t\tconst nearGround = support != null;\n\t\t\tconst isGrounded = isJumper2DGrounded({\n\t\t\t\tnearGround,\n\t\t\t\tvelocityY: bodyVelocity.y,\n\t\t\t\tsupportToi: support?.toi ?? null,\n\t\t\t\tsnapToGroundDistance: options.snapToGroundDistance,\n\t\t\t});\n\t\t\tif (shouldSnapJumper2DToGround(support, options, bodyVelocity.y)) {\n\t\t\t\tconst currentPosition = gameEntity.body.translation();\n\t\t\t\tgameEntity.body.setTranslation(\n\t\t\t\t\t{\n\t\t\t\t\t\tx: currentPosition.x,\n\t\t\t\t\t\ty: getGroundSnapTargetY(gameEntity, support),\n\t\t\t\t\t\tz: currentPosition.z,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet timeSinceGroundedMs = this.timeSinceGroundedMs.get(gameEntity.uuid) ?? 0;\n\t\t\tif (isGrounded) {\n\t\t\t\ttimeSinceGroundedMs = 0;\n\t\t\t} else {\n\t\t\t\ttimeSinceGroundedMs += delta * 1000;\n\t\t\t}\n\t\t\tthis.timeSinceGroundedMs.set(gameEntity.uuid, timeSinceGroundedMs);\n\n\t\t\tconst config: JumpConfig2D = gameEntity.jumper2d;\n\t\t\tconst input: JumpInput2D = gameEntity.$jumper2d;\n\t\t\tconst state: JumpState2D = gameEntity.jumper2dState;\n\t\t\tconst previousHeld = this.wasJumpHeld.get(gameEntity.uuid) ?? false;\n\t\t\tconst held = input.jumpHeld === true;\n\t\t\tconst effectiveInput: JumpInput2D = {\n\t\t\t\t...input,\n\t\t\t\tjumpPressed: input.jumpPressed || (held && !previousHeld),\n\t\t\t\tjumpReleased: input.jumpReleased || (!held && previousHeld),\n\t\t\t};\n\n\t\t\tconst store = gameEntity.transformStore;\n\t\t\tconst ctx: JumpContext2D = {\n\t\t\t\tdt: delta,\n\t\t\t\tvelocityY: bodyVelocity.y,\n\t\t\t\tisGrounded,\n\t\t\t\ttimeSinceGroundedMs,\n\t\t\t\tsetVerticalVelocity: (y: number) => {\n\t\t\t\t\tsetVelocityIntent(\n\t\t\t\t\t\tstore,\n\t\t\t\t\t\t'jumper-2d',\n\t\t\t\t\t\t{ y },\n\t\t\t\t\t\t{ mode: 'replace', priority: 20 },\n\t\t\t\t\t);\n\t\t\t\t\tctx.velocityY = y;\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst result = this.behavior.tick(config, effectiveInput, ctx, state);\n\t\t\tthis.wasJumpHeld.set(gameEntity.uuid, held);\n\n\t\t\tif (jumperRef.fsm) {\n\t\t\t\t(jumperRef.fsm as Jumper2DFSM).applyTickEvent(result.event, isGrounded);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: Jumper2DBehaviorOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tconst jumpForce = Math.sqrt(2 * (options.gravity ?? 20) * (options.jumpHeight ?? 2.5));\n\t\tthis.wasmStage.attachJumper2D(handle, {\n\t\t\tjumpForce,\n\t\t\tmaxJumps: options.maxJumps ?? 1,\n\t\t\tjumpBufferTime: (options.jumpBufferMs ?? 80) / 1000,\n\t\t\tcoyoteTime: (options.coyoteTimeMs ?? 100) / 1000,\n\t\t\tgravity: options.gravity ?? 20,\n\t\t});\n\t\tthis.attachedRuntimeSlots.add(handle);\n\t}\n\n\tdestroy(_ecs: unknown): void {\n\t\tthis.groundProbe.destroy();\n\t\tthis.initializedEntities.clear();\n\t\tthis.timeSinceGroundedMs.clear();\n\t\tthis.wasJumpHeld.clear();\n\t\tthis.attachedRuntimeSlots.clear();\n\t}\n}\n\nexport const Jumper2D = defineBehavior<\n\tJumper2DBehaviorOptions,\n\t{\n\t\tgetState: () => Jumper2DState;\n\t\tisJumping: () => boolean;\n\t\tgetJumpsUsed: () => number;\n\t\tgetJumpsRemaining: () => number;\n\t},\n\tJumper2DEntity\n>({\n\tname: 'jumper-2d',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew Jumper2DBehaviorSystem(ctx.world, ctx.scene, ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n\tcreateHandle: (ref) => ({\n\t\tgetState: () =>\n\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.getState() ??\n\t\t\tJumper2DState.Grounded,\n\t\tisJumping: () =>\n\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.isJumping() ?? false,\n\t\tgetJumpsUsed: () =>\n\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.getJumpsUsed() ?? 0,\n\t\tgetJumpsRemaining: () => {\n\t\t\tconst maxJumps = ref.options.maxJumps ?? 1;\n\t\t\tconst used =\n\t\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.getJumpsUsed() ?? 0;\n\t\t\treturn maxJumps - used;\n\t\t},\n\t}),\n});\n"],"mappings":"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","names":["Jumper2DTickEvent","Jumper2DState","Jumper2DEvent","input"]}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import {
|
|
2
|
+
angleFromDirection2D,
|
|
3
|
+
directionFromAngle2D,
|
|
4
|
+
getRotationAngle2D,
|
|
5
|
+
normalizeDirection2D,
|
|
6
|
+
rotateLocalOffset2D
|
|
7
|
+
} from "./chunk-ID5QJYF5.js";
|
|
8
|
+
import {
|
|
9
|
+
normalizeVec3
|
|
10
|
+
} from "./chunk-WWVD5DR5.js";
|
|
11
|
+
import {
|
|
12
|
+
defineBehavior
|
|
13
|
+
} from "./chunk-EZNCCO4L.js";
|
|
14
|
+
|
|
15
|
+
// src/lib/behaviors/shooter-2d/components.ts
|
|
16
|
+
function createShooter2DStateComponent() {
|
|
17
|
+
return {
|
|
18
|
+
cooldownRemainingMs: 0
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/lib/behaviors/shooter-2d/shooter-2d.descriptor.ts
|
|
23
|
+
var defaultOptions = {
|
|
24
|
+
projectileFactory: () => {
|
|
25
|
+
throw new Error("Shooter2DBehavior requires a projectileFactory.");
|
|
26
|
+
},
|
|
27
|
+
projectileSpeed: 12,
|
|
28
|
+
cooldownMs: 0,
|
|
29
|
+
spawnOffset: { x: 0, y: 1 },
|
|
30
|
+
rotateProjectile: true
|
|
31
|
+
};
|
|
32
|
+
var SHOOTER_2D_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for("zylem:behavior:shooter-2d");
|
|
33
|
+
function ensureShooterState(entity) {
|
|
34
|
+
if (!entity.shooter2dState) {
|
|
35
|
+
entity.shooter2dState = createShooter2DStateComponent();
|
|
36
|
+
}
|
|
37
|
+
return entity.shooter2dState;
|
|
38
|
+
}
|
|
39
|
+
function getEntityPosition(entity) {
|
|
40
|
+
if (entity.body?.translation) {
|
|
41
|
+
return entity.body.translation();
|
|
42
|
+
}
|
|
43
|
+
const position = entity.options?.position;
|
|
44
|
+
if (!position) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return normalizeVec3(position);
|
|
48
|
+
}
|
|
49
|
+
function getEntityFacingAngle(entity) {
|
|
50
|
+
if (entity.topDownMovementState) {
|
|
51
|
+
return entity.topDownMovementState.facingAngle;
|
|
52
|
+
}
|
|
53
|
+
if (entity.body?.rotation) {
|
|
54
|
+
return getRotationAngle2D(entity.body.rotation());
|
|
55
|
+
}
|
|
56
|
+
return entity._rotation2DAngle ?? 0;
|
|
57
|
+
}
|
|
58
|
+
function createShooter2DHandle(ref) {
|
|
59
|
+
return {
|
|
60
|
+
isReady: (source) => ensureShooterState(source).cooldownRemainingMs <= 0,
|
|
61
|
+
fire: async ({
|
|
62
|
+
source,
|
|
63
|
+
stage,
|
|
64
|
+
target
|
|
65
|
+
}) => {
|
|
66
|
+
const state = ensureShooterState(source);
|
|
67
|
+
if (state.cooldownRemainingMs > 0) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const sourcePosition = getEntityPosition(source);
|
|
71
|
+
if (!sourcePosition) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const options = ref.options;
|
|
75
|
+
const aimDirection = normalizeDirection2D(
|
|
76
|
+
target.x - sourcePosition.x,
|
|
77
|
+
target.y - sourcePosition.y
|
|
78
|
+
);
|
|
79
|
+
const angle = aimDirection ? angleFromDirection2D(aimDirection) : getEntityFacingAngle(source);
|
|
80
|
+
const direction = aimDirection ?? directionFromAngle2D(angle);
|
|
81
|
+
const offset = rotateLocalOffset2D(
|
|
82
|
+
options.spawnOffset ?? defaultOptions.spawnOffset,
|
|
83
|
+
angle
|
|
84
|
+
);
|
|
85
|
+
const spawnPosition = {
|
|
86
|
+
x: sourcePosition.x + offset.x,
|
|
87
|
+
y: sourcePosition.y + offset.y,
|
|
88
|
+
z: sourcePosition.z
|
|
89
|
+
};
|
|
90
|
+
const projectile = await Promise.resolve(options.projectileFactory());
|
|
91
|
+
projectile.prependSetup(({ me }) => {
|
|
92
|
+
me.setPosition(spawnPosition.x, spawnPosition.y, spawnPosition.z);
|
|
93
|
+
if (options.rotateProjectile ?? true) {
|
|
94
|
+
me.setRotationZ(angle);
|
|
95
|
+
}
|
|
96
|
+
me.transformStore.velocity.x = direction.x * options.projectileSpeed;
|
|
97
|
+
me.transformStore.velocity.y = direction.y * options.projectileSpeed;
|
|
98
|
+
me.transformStore.velocity.z = 0;
|
|
99
|
+
me.transformStore.dirty.velocity = true;
|
|
100
|
+
});
|
|
101
|
+
stage.add(projectile);
|
|
102
|
+
state.cooldownRemainingMs = Math.max(0, options.cooldownMs ?? 0);
|
|
103
|
+
return projectile;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
var Shooter2DBehaviorSystem = class {
|
|
108
|
+
constructor(wasmStage, getBehaviorLinks) {
|
|
109
|
+
this.wasmStage = wasmStage;
|
|
110
|
+
this.getBehaviorLinks = getBehaviorLinks;
|
|
111
|
+
}
|
|
112
|
+
wasmStage;
|
|
113
|
+
getBehaviorLinks;
|
|
114
|
+
attachedRuntimeSlots = /* @__PURE__ */ new Set();
|
|
115
|
+
update(_ecs, delta) {
|
|
116
|
+
const links = this.getBehaviorLinks?.(SHOOTER_2D_BEHAVIOR_KEY);
|
|
117
|
+
if (!links) return;
|
|
118
|
+
for (const link of links) {
|
|
119
|
+
const entity = link.entity;
|
|
120
|
+
const ref = link.ref;
|
|
121
|
+
const state = ensureShooterState(entity);
|
|
122
|
+
state.cooldownRemainingMs = Math.max(
|
|
123
|
+
0,
|
|
124
|
+
state.cooldownRemainingMs - delta * 1e3
|
|
125
|
+
);
|
|
126
|
+
ref.__entity = entity;
|
|
127
|
+
const handle = entity.runtimeHandle ?? -1;
|
|
128
|
+
if (this.wasmStage && handle >= 0) {
|
|
129
|
+
this.ensureWasmAttached(handle, ref.options);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
ensureWasmAttached(handle, options) {
|
|
134
|
+
if (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;
|
|
135
|
+
const offset = options.spawnOffset ?? defaultOptions.spawnOffset;
|
|
136
|
+
const fireRateHz = options.cooldownMs && options.cooldownMs > 0 ? 1e3 / options.cooldownMs : 0;
|
|
137
|
+
this.wasmStage.attachShooter2D(handle, {
|
|
138
|
+
fireRateHz,
|
|
139
|
+
muzzleOffsetX: offset.x,
|
|
140
|
+
muzzleOffsetY: offset.y,
|
|
141
|
+
muzzleSpeed: options.projectileSpeed
|
|
142
|
+
});
|
|
143
|
+
this.attachedRuntimeSlots.add(handle);
|
|
144
|
+
}
|
|
145
|
+
destroy(_ecs) {
|
|
146
|
+
this.attachedRuntimeSlots.clear();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
var Shooter2DBehavior = defineBehavior({
|
|
150
|
+
name: "shooter-2d",
|
|
151
|
+
defaultOptions,
|
|
152
|
+
systemFactory: (ctx) => new Shooter2DBehaviorSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),
|
|
153
|
+
createHandle: createShooter2DHandle
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
export {
|
|
157
|
+
createShooter2DStateComponent,
|
|
158
|
+
Shooter2DBehavior
|
|
159
|
+
};
|
|
160
|
+
//# sourceMappingURL=chunk-STCCNLPC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/shooter-2d/components.ts","../src/lib/behaviors/shooter-2d/shooter-2d.descriptor.ts"],"sourcesContent":["export interface Shooter2DStateComponent {\n\tcooldownRemainingMs: number;\n}\n\nexport function createShooter2DStateComponent(): Shooter2DStateComponent {\n\treturn {\n\t\tcooldownRemainingMs: 0,\n\t};\n}\n","import { defineBehavior, type BehaviorRef } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { normalizeVec3, type Vec3Input } from '../../core/vector';\nimport type { WasmStageRuntime } from '../../runtime/wasm-stage-runtime';\nimport {\n\tangleFromDirection2D,\n\tdirectionFromAngle2D,\n\tgetRotationAngle2D,\n\tnormalizeDirection2D,\n\trotateLocalOffset2D,\n} from '../shared/direction-2d';\nimport {\n\tcreateShooter2DStateComponent,\n\ttype Shooter2DStateComponent,\n} from './components';\n\nexport interface Shooter2DTarget {\n\tx: number;\n\ty: number;\n}\n\nexport interface Shooter2DStageLike {\n\tadd(...inputs: any[]): void;\n}\n\nexport interface Shooter2DProjectileEntity {\n\ttransformStore: {\n\t\tvelocity: { x: number; y: number; z: number };\n\t\tdirty: { velocity: boolean };\n\t};\n\tprependSetup(\n\t\tcallback: (params: { me: Shooter2DProjectileEntity }) => void,\n\t): unknown;\n\tsetPosition(x: number, y: number, z: number): void;\n\tsetRotationZ(angle: number): void;\n}\n\nexport type Shooter2DProjectileFactory = () =>\n\t| Shooter2DProjectileEntity\n\t| Promise<Shooter2DProjectileEntity>;\n\nexport interface Shooter2DBehaviorOptions {\n\tprojectileFactory: Shooter2DProjectileFactory;\n\tprojectileSpeed: number;\n\tcooldownMs?: number;\n\tspawnOffset?: Shooter2DTarget;\n\trotateProjectile?: boolean;\n}\n\nexport interface Shooter2DSourceEntity {\n\tbody?: {\n\t\ttranslation(): { x: number; y: number; z: number };\n\t\trotation?: () => { x: number; y: number; z: number; w: number };\n\t} | null;\n\toptions?: {\n\t\tposition?: Vec3Input;\n\t};\n\ttopDownMovementState?: {\n\t\tfacingAngle: number;\n\t};\n\tshooter2dState?: Shooter2DStateComponent;\n\t_rotation2DAngle?: number;\n}\n\nexport interface Shooter2DFireArgs {\n\tsource: Shooter2DSourceEntity;\n\tstage: Shooter2DStageLike;\n\ttarget: Shooter2DTarget;\n}\n\nexport interface Shooter2DHandle {\n\tisReady(source: Shooter2DSourceEntity): boolean;\n\tfire(args: Shooter2DFireArgs): Promise<Shooter2DProjectileEntity | null>;\n}\n\nconst defaultOptions: Shooter2DBehaviorOptions = {\n\tprojectileFactory: () => {\n\t\tthrow new Error('Shooter2DBehavior requires a projectileFactory.');\n\t},\n\tprojectileSpeed: 12,\n\tcooldownMs: 0,\n\tspawnOffset: { x: 0, y: 1 },\n\trotateProjectile: true,\n};\n\nconst SHOOTER_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:shooter-2d');\n\nfunction ensureShooterState(entity: Shooter2DSourceEntity): Shooter2DStateComponent {\n\tif (!entity.shooter2dState) {\n\t\tentity.shooter2dState = createShooter2DStateComponent();\n\t}\n\treturn entity.shooter2dState;\n}\n\nfunction getEntityPosition(\n\tentity: Shooter2DSourceEntity,\n): { x: number; y: number; z: number } | null {\n\tif (entity.body?.translation) {\n\t\treturn entity.body.translation();\n\t}\n\n\tconst position = entity.options?.position;\n\tif (!position) {\n\t\treturn null;\n\t}\n\n\treturn normalizeVec3(position);\n}\n\nfunction getEntityFacingAngle(entity: Shooter2DSourceEntity): number {\n\tif (entity.topDownMovementState) {\n\t\treturn entity.topDownMovementState.facingAngle;\n\t}\n\n\tif (entity.body?.rotation) {\n\t\treturn getRotationAngle2D(entity.body.rotation());\n\t}\n\n\treturn entity._rotation2DAngle ?? 0;\n}\n\nfunction createShooter2DHandle(\n\tref: BehaviorRef<Shooter2DBehaviorOptions>,\n): Shooter2DHandle {\n\treturn {\n\t\tisReady: (source: Shooter2DSourceEntity) =>\n\t\t\tensureShooterState(source).cooldownRemainingMs <= 0,\n\t\tfire: async ({\n\t\t\tsource,\n\t\t\tstage,\n\t\t\ttarget,\n\t\t}: Shooter2DFireArgs): Promise<Shooter2DProjectileEntity | null> => {\n\t\t\tconst state = ensureShooterState(source);\n\t\t\tif (state.cooldownRemainingMs > 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst sourcePosition = getEntityPosition(source);\n\t\t\tif (!sourcePosition) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst options = ref.options;\n\t\t\tconst aimDirection = normalizeDirection2D(\n\t\t\t\ttarget.x - sourcePosition.x,\n\t\t\t\ttarget.y - sourcePosition.y,\n\t\t\t);\n\t\t\tconst angle = aimDirection\n\t\t\t\t? angleFromDirection2D(aimDirection)\n\t\t\t\t: getEntityFacingAngle(source);\n\t\t\tconst direction = aimDirection ?? directionFromAngle2D(angle);\n\t\t\tconst offset = rotateLocalOffset2D(\n\t\t\t\toptions.spawnOffset ?? defaultOptions.spawnOffset!,\n\t\t\t\tangle,\n\t\t\t);\n\t\t\tconst spawnPosition = {\n\t\t\t\tx: sourcePosition.x + offset.x,\n\t\t\t\ty: sourcePosition.y + offset.y,\n\t\t\t\tz: sourcePosition.z,\n\t\t\t};\n\t\t\tconst projectile = await Promise.resolve(options.projectileFactory());\n\t\t\tprojectile.prependSetup(({ me }) => {\n\t\t\t\tme.setPosition(spawnPosition.x, spawnPosition.y, spawnPosition.z);\n\t\t\t\tif (options.rotateProjectile ?? true) {\n\t\t\t\t\tme.setRotationZ(angle);\n\t\t\t\t}\n\t\t\t\tme.transformStore.velocity.x = direction.x * options.projectileSpeed;\n\t\t\t\tme.transformStore.velocity.y = direction.y * options.projectileSpeed;\n\t\t\t\tme.transformStore.velocity.z = 0;\n\t\t\t\tme.transformStore.dirty.velocity = true;\n\t\t\t});\n\n\t\t\tstage.add(projectile);\n\t\t\tstate.cooldownRemainingMs = Math.max(0, options.cooldownMs ?? 0);\n\t\t\treturn projectile;\n\t\t},\n\t};\n}\n\nclass Shooter2DBehaviorSystem implements BehaviorSystem {\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate wasmStage: WasmStageRuntime | null,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {}\n\n\tupdate(_ecs: unknown, delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(SHOOTER_2D_BEHAVIOR_KEY);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst entity = link.entity as Shooter2DSourceEntity & { runtimeHandle?: number };\n\t\t\tconst ref = link.ref as any;\n\t\t\tconst state = ensureShooterState(entity);\n\t\t\tstate.cooldownRemainingMs = Math.max(\n\t\t\t\t0,\n\t\t\t\tstate.cooldownRemainingMs - delta * 1000,\n\t\t\t);\n\t\t\tref.__entity = entity;\n\n\t\t\tconst handle = (entity.runtimeHandle ?? -1) as number;\n\t\t\tif (this.wasmStage && handle >= 0) {\n\t\t\t\tthis.ensureWasmAttached(handle, ref.options as Shooter2DBehaviorOptions);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: Shooter2DBehaviorOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tconst offset = options.spawnOffset ?? defaultOptions.spawnOffset!;\n\t\tconst fireRateHz = options.cooldownMs && options.cooldownMs > 0\n\t\t\t? 1000 / options.cooldownMs\n\t\t\t: 0;\n\t\tthis.wasmStage.attachShooter2D(handle, {\n\t\t\tfireRateHz,\n\t\t\tmuzzleOffsetX: offset.x,\n\t\t\tmuzzleOffsetY: offset.y,\n\t\t\tmuzzleSpeed: options.projectileSpeed,\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\nexport const Shooter2DBehavior = defineBehavior<\n\tShooter2DBehaviorOptions,\n\tShooter2DHandle,\n\tShooter2DSourceEntity\n>({\n\tname: 'shooter-2d',\n\tdefaultOptions,\n\tsystemFactory: (ctx) => new Shooter2DBehaviorSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n\tcreateHandle: createShooter2DHandle,\n});\n"],"mappings":"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","names":[]}
|