@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
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createBounds2DRect
|
|
3
|
-
|
|
4
|
-
} from "./chunk-KDY5N6J4.js";
|
|
2
|
+
createBounds2DRect
|
|
3
|
+
} from "./chunk-OPZ2LVS2.js";
|
|
5
4
|
import {
|
|
6
5
|
SyncStateMachine,
|
|
7
|
-
|
|
8
|
-
} from "./chunk-
|
|
6
|
+
import_typescript_fsm
|
|
7
|
+
} from "./chunk-AS3HR7AS.js";
|
|
9
8
|
import {
|
|
10
9
|
defineBehavior
|
|
11
10
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -36,33 +35,33 @@ var ScreenWrapFSM = class {
|
|
|
36
35
|
"center" /* Center */,
|
|
37
36
|
[
|
|
38
37
|
// From Center
|
|
39
|
-
t("center" /* Center */, "approach-left" /* ApproachLeft */, "near-edge-left" /* NearEdgeLeft */),
|
|
40
|
-
t("center" /* Center */, "approach-right" /* ApproachRight */, "near-edge-right" /* NearEdgeRight */),
|
|
41
|
-
t("center" /* Center */, "approach-top" /* ApproachTop */, "near-edge-top" /* NearEdgeTop */),
|
|
42
|
-
t("center" /* Center */, "approach-bottom" /* ApproachBottom */, "near-edge-bottom" /* NearEdgeBottom */),
|
|
38
|
+
(0, import_typescript_fsm.t)("center" /* Center */, "approach-left" /* ApproachLeft */, "near-edge-left" /* NearEdgeLeft */),
|
|
39
|
+
(0, import_typescript_fsm.t)("center" /* Center */, "approach-right" /* ApproachRight */, "near-edge-right" /* NearEdgeRight */),
|
|
40
|
+
(0, import_typescript_fsm.t)("center" /* Center */, "approach-top" /* ApproachTop */, "near-edge-top" /* NearEdgeTop */),
|
|
41
|
+
(0, import_typescript_fsm.t)("center" /* Center */, "approach-bottom" /* ApproachBottom */, "near-edge-bottom" /* NearEdgeBottom */),
|
|
43
42
|
// From NearEdge to Wrapped
|
|
44
|
-
t("near-edge-left" /* NearEdgeLeft */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
45
|
-
t("near-edge-right" /* NearEdgeRight */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
46
|
-
t("near-edge-top" /* NearEdgeTop */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
47
|
-
t("near-edge-bottom" /* NearEdgeBottom */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
43
|
+
(0, import_typescript_fsm.t)("near-edge-left" /* NearEdgeLeft */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
44
|
+
(0, import_typescript_fsm.t)("near-edge-right" /* NearEdgeRight */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
45
|
+
(0, import_typescript_fsm.t)("near-edge-top" /* NearEdgeTop */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
46
|
+
(0, import_typescript_fsm.t)("near-edge-bottom" /* NearEdgeBottom */, "wrap" /* Wrap */, "wrapped" /* Wrapped */),
|
|
48
47
|
// From NearEdge back to Center
|
|
49
|
-
t("near-edge-left" /* NearEdgeLeft */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
50
|
-
t("near-edge-right" /* NearEdgeRight */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
51
|
-
t("near-edge-top" /* NearEdgeTop */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
52
|
-
t("near-edge-bottom" /* NearEdgeBottom */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
48
|
+
(0, import_typescript_fsm.t)("near-edge-left" /* NearEdgeLeft */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
49
|
+
(0, import_typescript_fsm.t)("near-edge-right" /* NearEdgeRight */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
50
|
+
(0, import_typescript_fsm.t)("near-edge-top" /* NearEdgeTop */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
51
|
+
(0, import_typescript_fsm.t)("near-edge-bottom" /* NearEdgeBottom */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
53
52
|
// From Wrapped back to Center
|
|
54
|
-
t("wrapped" /* Wrapped */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
53
|
+
(0, import_typescript_fsm.t)("wrapped" /* Wrapped */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
55
54
|
// From Wrapped to NearEdge (landed near opposite edge)
|
|
56
|
-
t("wrapped" /* Wrapped */, "approach-left" /* ApproachLeft */, "near-edge-left" /* NearEdgeLeft */),
|
|
57
|
-
t("wrapped" /* Wrapped */, "approach-right" /* ApproachRight */, "near-edge-right" /* NearEdgeRight */),
|
|
58
|
-
t("wrapped" /* Wrapped */, "approach-top" /* ApproachTop */, "near-edge-top" /* NearEdgeTop */),
|
|
59
|
-
t("wrapped" /* Wrapped */, "approach-bottom" /* ApproachBottom */, "near-edge-bottom" /* NearEdgeBottom */),
|
|
55
|
+
(0, import_typescript_fsm.t)("wrapped" /* Wrapped */, "approach-left" /* ApproachLeft */, "near-edge-left" /* NearEdgeLeft */),
|
|
56
|
+
(0, import_typescript_fsm.t)("wrapped" /* Wrapped */, "approach-right" /* ApproachRight */, "near-edge-right" /* NearEdgeRight */),
|
|
57
|
+
(0, import_typescript_fsm.t)("wrapped" /* Wrapped */, "approach-top" /* ApproachTop */, "near-edge-top" /* NearEdgeTop */),
|
|
58
|
+
(0, import_typescript_fsm.t)("wrapped" /* Wrapped */, "approach-bottom" /* ApproachBottom */, "near-edge-bottom" /* NearEdgeBottom */),
|
|
60
59
|
// Self-transitions (no-ops for redundant events)
|
|
61
|
-
t("center" /* Center */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
62
|
-
t("near-edge-left" /* NearEdgeLeft */, "approach-left" /* ApproachLeft */, "near-edge-left" /* NearEdgeLeft */),
|
|
63
|
-
t("near-edge-right" /* NearEdgeRight */, "approach-right" /* ApproachRight */, "near-edge-right" /* NearEdgeRight */),
|
|
64
|
-
t("near-edge-top" /* NearEdgeTop */, "approach-top" /* ApproachTop */, "near-edge-top" /* NearEdgeTop */),
|
|
65
|
-
t("near-edge-bottom" /* NearEdgeBottom */, "approach-bottom" /* ApproachBottom */, "near-edge-bottom" /* NearEdgeBottom */)
|
|
60
|
+
(0, import_typescript_fsm.t)("center" /* Center */, "enter-center" /* EnterCenter */, "center" /* Center */),
|
|
61
|
+
(0, import_typescript_fsm.t)("near-edge-left" /* NearEdgeLeft */, "approach-left" /* ApproachLeft */, "near-edge-left" /* NearEdgeLeft */),
|
|
62
|
+
(0, import_typescript_fsm.t)("near-edge-right" /* NearEdgeRight */, "approach-right" /* ApproachRight */, "near-edge-right" /* NearEdgeRight */),
|
|
63
|
+
(0, import_typescript_fsm.t)("near-edge-top" /* NearEdgeTop */, "approach-top" /* ApproachTop */, "near-edge-top" /* NearEdgeTop */),
|
|
64
|
+
(0, import_typescript_fsm.t)("near-edge-bottom" /* NearEdgeBottom */, "approach-bottom" /* ApproachBottom */, "near-edge-bottom" /* NearEdgeBottom */)
|
|
66
65
|
]
|
|
67
66
|
);
|
|
68
67
|
}
|
|
@@ -130,41 +129,24 @@ var ScreenWrapSystem = class {
|
|
|
130
129
|
wrapRef.fsm = new ScreenWrapFSM();
|
|
131
130
|
}
|
|
132
131
|
const handle = gameEntity.runtimeHandle ?? -1;
|
|
133
|
-
if (this.wasmStage
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
132
|
+
if (!this.wasmStage || handle < 0) continue;
|
|
133
|
+
this.ensureWasmAttached(handle, options);
|
|
134
|
+
const pose = this.wasmStage.getPose(handle);
|
|
135
|
+
const query = this.wasmStage.queryScreenWrap(handle);
|
|
136
|
+
if (pose && query) {
|
|
137
|
+
const bounds = createBounds2DRect(options);
|
|
138
|
+
wrapRef.fsm.update(
|
|
139
|
+
{ x: pose.position[0], y: pose.position[1] },
|
|
140
|
+
{
|
|
141
|
+
minX: bounds.minX,
|
|
142
|
+
maxX: bounds.maxX,
|
|
143
|
+
minY: bounds.minY,
|
|
144
|
+
maxY: bounds.maxY,
|
|
145
|
+
edgeThreshold: options.edgeThreshold
|
|
146
|
+
},
|
|
147
|
+
query.lastWrappedAxes !== 0
|
|
148
|
+
);
|
|
152
149
|
}
|
|
153
|
-
if (!gameEntity.body) continue;
|
|
154
|
-
const wrapped = this.wrapEntity(gameEntity, options);
|
|
155
|
-
const pos = gameEntity.body.translation();
|
|
156
|
-
const bounds = createBounds2DRect(options);
|
|
157
|
-
wrapRef.fsm.update(
|
|
158
|
-
{ x: pos.x, y: pos.y },
|
|
159
|
-
{
|
|
160
|
-
minX: bounds.minX,
|
|
161
|
-
maxX: bounds.maxX,
|
|
162
|
-
minY: bounds.minY,
|
|
163
|
-
maxY: bounds.maxY,
|
|
164
|
-
edgeThreshold: options.edgeThreshold
|
|
165
|
-
},
|
|
166
|
-
wrapped
|
|
167
|
-
);
|
|
168
150
|
}
|
|
169
151
|
}
|
|
170
152
|
ensureWasmAttached(handle, options) {
|
|
@@ -178,17 +160,6 @@ var ScreenWrapSystem = class {
|
|
|
178
160
|
});
|
|
179
161
|
this.attachedRuntimeSlots.add(handle);
|
|
180
162
|
}
|
|
181
|
-
wrapEntity(entity, options) {
|
|
182
|
-
const body = entity.body;
|
|
183
|
-
if (!body) return false;
|
|
184
|
-
const pos = body.translation();
|
|
185
|
-
const bounds = createBounds2DRect(options);
|
|
186
|
-
const result = wrapPoint2D({ x: pos.x, y: pos.y }, bounds);
|
|
187
|
-
if (result.wrapped) {
|
|
188
|
-
body.setTranslation({ x: result.x, y: result.y, z: pos.z }, true);
|
|
189
|
-
}
|
|
190
|
-
return result.wrapped;
|
|
191
|
-
}
|
|
192
163
|
destroy(_ecs) {
|
|
193
164
|
this.attachedRuntimeSlots.clear();
|
|
194
165
|
}
|
|
@@ -205,4 +176,4 @@ export {
|
|
|
205
176
|
ScreenWrapFSM,
|
|
206
177
|
ScreenWrapBehavior
|
|
207
178
|
};
|
|
208
|
-
//# sourceMappingURL=chunk-
|
|
179
|
+
//# sourceMappingURL=chunk-2PAHQZZD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/screen-wrap/screen-wrap-fsm.ts","../src/lib/behaviors/screen-wrap/screen-wrap.descriptor.ts"],"sourcesContent":["/**\n * ScreenWrapFSM\n * \n * State machine for screen wrap behavior.\n * Reports position relative to bounds edges.\n */\n\nimport { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM State Model\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ScreenWrapState {\n\tCenter = 'center',\n\tNearEdgeLeft = 'near-edge-left',\n\tNearEdgeRight = 'near-edge-right',\n\tNearEdgeTop = 'near-edge-top',\n\tNearEdgeBottom = 'near-edge-bottom',\n\tWrapped = 'wrapped',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// FSM Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport enum ScreenWrapEvent {\n\tEnterCenter = 'enter-center',\n\tApproachLeft = 'approach-left',\n\tApproachRight = 'approach-right',\n\tApproachTop = 'approach-top',\n\tApproachBottom = 'approach-bottom',\n\tWrap = 'wrap',\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ScreenWrapFSM\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class ScreenWrapFSM {\n\tmachine: SyncStateMachine<ScreenWrapState, ScreenWrapEvent, never>;\n\n\tconstructor() {\n\t\tthis.machine = new SyncStateMachine<ScreenWrapState, ScreenWrapEvent, never>(\n\t\t\tScreenWrapState.Center,\n\t\t\t[\n\t\t\t\t// From Center\n\t\t\t\tt(ScreenWrapState.Center, ScreenWrapEvent.ApproachLeft, ScreenWrapState.NearEdgeLeft),\n\t\t\t\tt(ScreenWrapState.Center, ScreenWrapEvent.ApproachRight, ScreenWrapState.NearEdgeRight),\n\t\t\t\tt(ScreenWrapState.Center, ScreenWrapEvent.ApproachTop, ScreenWrapState.NearEdgeTop),\n\t\t\t\tt(ScreenWrapState.Center, ScreenWrapEvent.ApproachBottom, ScreenWrapState.NearEdgeBottom),\n\t\t\t\t\n\t\t\t\t// From NearEdge to Wrapped\n\t\t\t\tt(ScreenWrapState.NearEdgeLeft, ScreenWrapEvent.Wrap, ScreenWrapState.Wrapped),\n\t\t\t\tt(ScreenWrapState.NearEdgeRight, ScreenWrapEvent.Wrap, ScreenWrapState.Wrapped),\n\t\t\t\tt(ScreenWrapState.NearEdgeTop, ScreenWrapEvent.Wrap, ScreenWrapState.Wrapped),\n\t\t\t\tt(ScreenWrapState.NearEdgeBottom, ScreenWrapEvent.Wrap, ScreenWrapState.Wrapped),\n\n\t\t\t\t// From NearEdge back to Center\n\t\t\t\tt(ScreenWrapState.NearEdgeLeft, ScreenWrapEvent.EnterCenter, ScreenWrapState.Center),\n\t\t\t\tt(ScreenWrapState.NearEdgeRight, ScreenWrapEvent.EnterCenter, ScreenWrapState.Center),\n\t\t\t\tt(ScreenWrapState.NearEdgeTop, ScreenWrapEvent.EnterCenter, ScreenWrapState.Center),\n\t\t\t\tt(ScreenWrapState.NearEdgeBottom, ScreenWrapEvent.EnterCenter, ScreenWrapState.Center),\n\n\t\t\t\t// From Wrapped back to Center\n\t\t\t\tt(ScreenWrapState.Wrapped, ScreenWrapEvent.EnterCenter, ScreenWrapState.Center),\n\n\t\t\t\t// From Wrapped to NearEdge (landed near opposite edge)\n\t\t\t\tt(ScreenWrapState.Wrapped, ScreenWrapEvent.ApproachLeft, ScreenWrapState.NearEdgeLeft),\n\t\t\t\tt(ScreenWrapState.Wrapped, ScreenWrapEvent.ApproachRight, ScreenWrapState.NearEdgeRight),\n\t\t\t\tt(ScreenWrapState.Wrapped, ScreenWrapEvent.ApproachTop, ScreenWrapState.NearEdgeTop),\n\t\t\t\tt(ScreenWrapState.Wrapped, ScreenWrapEvent.ApproachBottom, ScreenWrapState.NearEdgeBottom),\n\n\t\t\t\t// Self-transitions (no-ops for redundant events)\n\t\t\t\tt(ScreenWrapState.Center, ScreenWrapEvent.EnterCenter, ScreenWrapState.Center),\n\t\t\t\tt(ScreenWrapState.NearEdgeLeft, ScreenWrapEvent.ApproachLeft, ScreenWrapState.NearEdgeLeft),\n\t\t\t\tt(ScreenWrapState.NearEdgeRight, ScreenWrapEvent.ApproachRight, ScreenWrapState.NearEdgeRight),\n\t\t\t\tt(ScreenWrapState.NearEdgeTop, ScreenWrapEvent.ApproachTop, ScreenWrapState.NearEdgeTop),\n\t\t\t\tt(ScreenWrapState.NearEdgeBottom, ScreenWrapEvent.ApproachBottom, ScreenWrapState.NearEdgeBottom),\n\t\t\t]\n\t\t);\n\t}\n\n\tgetState(): ScreenWrapState {\n\t\treturn this.machine.getState();\n\t}\n\n\tdispatch(event: ScreenWrapEvent): 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 based on entity position relative to bounds\n\t */\n\tupdate(position: { x: number; y: number }, bounds: {\n\t\tminX: number; maxX: number; minY: number; maxY: number;\n\t\tedgeThreshold: number;\n\t}, wrapped: boolean): void {\n\t\tconst { x, y } = position;\n\t\tconst { minX, maxX, minY, maxY, edgeThreshold } = bounds;\n\n\t\tif (wrapped) {\n\t\t\tthis.dispatch(ScreenWrapEvent.Wrap);\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if near edges\n\t\tconst nearLeft = x < minX + edgeThreshold;\n\t\tconst nearRight = x > maxX - edgeThreshold;\n\t\tconst nearBottom = y < minY + edgeThreshold;\n\t\tconst nearTop = y > maxY - edgeThreshold;\n\n\t\tif (nearLeft) {\n\t\t\tthis.dispatch(ScreenWrapEvent.ApproachLeft);\n\t\t} else if (nearRight) {\n\t\t\tthis.dispatch(ScreenWrapEvent.ApproachRight);\n\t\t} else if (nearTop) {\n\t\t\tthis.dispatch(ScreenWrapEvent.ApproachTop);\n\t\t} else if (nearBottom) {\n\t\t\tthis.dispatch(ScreenWrapEvent.ApproachBottom);\n\t\t} else {\n\t\t\tthis.dispatch(ScreenWrapEvent.EnterCenter);\n\t\t}\n\t}\n}\n","/**\n * ScreenWrapBehavior\n * \n * When an entity exits the defined 2D bounds, it wraps around to the opposite edge.\n * Asteroids-style screen wrapping with FSM for edge detection.\n */\n\nimport { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { ScreenWrapFSM } from './screen-wrap-fsm';\nimport { createBounds2DRect } from '../shared/bounds-2d';\nimport type { BehaviorRuntime } from '../../runtime/wasm-stage-runtime';\n\n/**\n * Screen wrap options (typed for entity.use() autocomplete)\n */\nexport interface ScreenWrapOptions {\n\t/** Width of the wrapping area (default: 20) */\n\twidth: number;\n\t/** Height of the wrapping area (default: 15) */\n\theight: number;\n\t/** Center X position (default: 0) */\n\tcenterX: number;\n\t/** Center Y position (default: 0) */\n\tcenterY: number;\n\t/** Distance from edge to trigger NearEdge state (default: 2) */\n\tedgeThreshold: number;\n}\n\nconst defaultOptions: ScreenWrapOptions = {\n\twidth: 20,\n\theight: 15,\n\tcenterX: 0,\n\tcenterY: 0,\n\tedgeThreshold: 2,\n};\n\nconst SCREEN_WRAP_BEHAVIOR_KEY = Symbol.for('zylem:behavior:screen-wrap');\n\n/**\n * ScreenWrapSystem - Wraps entities around 2D bounds\n *\n * The Rust `screen_wrap` Stage behavior owns the wrap; this system attaches\n * it and mirrors the queried state into the local FSM so handles can observe\n * edge/wrap states.\n */\nclass ScreenWrapSystem implements BehaviorSystem {\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate wasmStage: BehaviorRuntime | 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?.(SCREEN_WRAP_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 wrapRef = link.ref as any;\n\t\t\tconst options = wrapRef.options as ScreenWrapOptions;\n\n\t\t\tif (!wrapRef.fsm) {\n\t\t\t\twrapRef.fsm = new ScreenWrapFSM();\n\t\t\t}\n\n\t\t\tconst handle = (gameEntity.runtimeHandle ?? -1) as number;\n\t\t\tif (!this.wasmStage || handle < 0) continue;\n\n\t\t\tthis.ensureWasmAttached(handle, options);\n\t\t\tconst pose = this.wasmStage.getPose(handle);\n\t\t\tconst query = this.wasmStage.queryScreenWrap(handle);\n\t\t\tif (pose && query) {\n\t\t\t\tconst bounds = createBounds2DRect(options);\n\t\t\t\twrapRef.fsm.update(\n\t\t\t\t\t{ x: pose.position[0], y: pose.position[1] },\n\t\t\t\t\t{\n\t\t\t\t\t\tminX: bounds.minX,\n\t\t\t\t\t\tmaxX: bounds.maxX,\n\t\t\t\t\t\tminY: bounds.minY,\n\t\t\t\t\t\tmaxY: bounds.maxY,\n\t\t\t\t\t\tedgeThreshold: options.edgeThreshold,\n\t\t\t\t\t},\n\t\t\t\t\tquery.lastWrappedAxes !== 0,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: ScreenWrapOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tthis.wasmStage.attachScreenWrap(handle, {\n\t\t\twidth: options.width,\n\t\t\theight: options.height,\n\t\t\tcenterX: options.centerX,\n\t\t\tcenterY: options.centerY,\n\t\t\tedgeThreshold: options.edgeThreshold,\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 * ScreenWrapBehavior - Wraps entities around 2D bounds\n * \n * @example\n * ```typescript\n * import { ScreenWrapBehavior } from \"@zylem/game-lib/behavior\";\n * \n * const ship = createSprite({ ... });\n * const wrapRef = ship.use(ScreenWrapBehavior, { width: 20, height: 15 });\n * \n * // Access FSM to observe edge state\n * const fsm = wrapRef.getFSM();\n * console.log(fsm?.getState()); // 'center', 'near-edge-left', 'wrapped', etc.\n * ```\n */\nexport const ScreenWrapBehavior = defineBehavior({\n\tname: 'screen-wrap',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew ScreenWrapSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n});\n"],"mappings":"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","names":["ScreenWrapState","ScreenWrapEvent"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getEntityFacingAngle2D,
|
|
3
|
+
resolveAim2D
|
|
4
|
+
} from "./chunk-TBUKJKY6.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/coordinators/shared/shooter-fire.ts
|
|
7
|
+
function fireShooter2DIfRequested(entity, shooter, stage, input, aim) {
|
|
8
|
+
if (!input.shootPressed && !input.shootHeld) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const sourcePosition = entity.body?.translation();
|
|
12
|
+
if (!sourcePosition) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const resolved = aim ?? resolveAim2D(input.aimX, input.aimY, getEntityFacingAngle2D(entity));
|
|
16
|
+
void shooter.fire({
|
|
17
|
+
source: entity,
|
|
18
|
+
stage,
|
|
19
|
+
target: {
|
|
20
|
+
x: sourcePosition.x + resolved.direction.x,
|
|
21
|
+
y: sourcePosition.y + resolved.direction.y
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
fireShooter2DIfRequested
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=chunk-52FJIDGL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/coordinators/shared/shooter-fire.ts"],"sourcesContent":["import type {\n\tShooter2DHandle,\n\tShooter2DSourceEntity,\n\tShooter2DStageLike,\n} from '../../behaviors/shooter-2d/shooter-2d.descriptor';\nimport {\n\tgetEntityFacingAngle2D,\n\tresolveAim2D,\n\ttype ResolvedAim2D,\n} from './top-down-aim';\n\n/**\n * Aim + fire input fields shared by the 2D shooter coordinators\n * (top-down-shooter, multidirectional-space-shooter).\n */\nexport interface Shooter2DAimFireInput {\n\taimX: number;\n\taimY: number;\n\tshootPressed: boolean;\n\tshootHeld: boolean;\n}\n\n/**\n * Fire the entity's Shooter2D behavior when the input requests it.\n *\n * Resolves the 2D aim (explicit aim axes, falling back to the entity's\n * current facing) and fires toward a point one unit along the aim direction.\n * Pass a pre-resolved `aim` to avoid recomputing when the coordinator already\n * resolved it for rotation.\n *\n * @returns true when a fire attempt was issued\n */\nexport function fireShooter2DIfRequested(\n\tentity: Shooter2DSourceEntity,\n\tshooter: Shooter2DHandle,\n\tstage: Shooter2DStageLike,\n\tinput: Shooter2DAimFireInput,\n\taim?: ResolvedAim2D,\n): boolean {\n\tif (!input.shootPressed && !input.shootHeld) {\n\t\treturn false;\n\t}\n\n\tconst sourcePosition = entity.body?.translation();\n\tif (!sourcePosition) {\n\t\treturn false;\n\t}\n\n\tconst resolved =\n\t\taim ?? resolveAim2D(input.aimX, input.aimY, getEntityFacingAngle2D(entity));\n\n\tvoid shooter.fire({\n\t\tsource: entity,\n\t\tstage,\n\t\ttarget: {\n\t\t\tx: sourcePosition.x + resolved.direction.x,\n\t\t\ty: sourcePosition.y + resolved.direction.y,\n\t\t},\n\t});\n\treturn true;\n}\n"],"mappings":";;;;;;AAgCO,SAAS,yBACf,QACA,SACA,OACA,OACA,KACU;AACV,MAAI,CAAC,MAAM,gBAAgB,CAAC,MAAM,WAAW;AAC5C,WAAO;AAAA,EACR;AAEA,QAAM,iBAAiB,OAAO,MAAM,YAAY;AAChD,MAAI,CAAC,gBAAgB;AACpB,WAAO;AAAA,EACR;AAEA,QAAM,WACL,OAAO,aAAa,MAAM,MAAM,MAAM,MAAM,uBAAuB,MAAM,CAAC;AAE3E,OAAK,QAAQ,KAAK;AAAA,IACjB,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ;AAAA,MACP,GAAG,eAAe,IAAI,SAAS,UAAU;AAAA,MACzC,GAAG,eAAe,IAAI,SAAS,UAAU;AAAA,IAC1C;AAAA,EACD,CAAC;AACD,SAAO;AACR;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/behaviors/use-behavior.ts","../src/lib/behaviors/components.ts"],"sourcesContent":["import { GameEntity } from '../entities/entity';\nimport { BehaviorDescriptor } from './behavior-descriptor';\n\n/**\n * Type-safe helper to apply a behavior to an entity and return the entity cast to the behavior's interface.\n * \n * @param entity The entity to apply the behavior to\n * @param descriptor The behavior descriptor\n * @param options Behavior options\n * @returns The entity, cast to E & I (where I is the behavior's interface)\n */\nexport function useBehavior<\n E extends GameEntity<any>,\n O extends Record<string, any>,\n H extends Record<string, any>,\n I // Entity Interface\n>(\n entity: E,\n descriptor: BehaviorDescriptor<O, H, I>,\n options?: Partial<O>\n): E & I {\n entity.use(descriptor, options);\n return entity as unknown as E & I;\n}\n","/**\n * Core behavior helper types\n *\n * Plain data interfaces shared by movement behaviors and coordinators.\n */\n\nimport
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/use-behavior.ts","../src/lib/behaviors/components.ts"],"sourcesContent":["import { GameEntity } from '../entities/entity';\nimport { BehaviorDescriptor } from './behavior-descriptor';\n\n/**\n * Type-safe helper to apply a behavior to an entity and return the entity cast to the behavior's interface.\n * \n * @param entity The entity to apply the behavior to\n * @param descriptor The behavior descriptor\n * @param options Behavior options\n * @returns The entity, cast to E & I (where I is the behavior's interface)\n */\nexport function useBehavior<\n E extends GameEntity<any>,\n O extends Record<string, any>,\n H extends Record<string, any>,\n I // Entity Interface\n>(\n entity: E,\n descriptor: BehaviorDescriptor<O, H, I>,\n options?: Partial<O>\n): E & I {\n entity.use(descriptor, options);\n return entity as unknown as E & I;\n}\n","/**\n * Core behavior helper types\n *\n * Plain data interfaces shared by movement behaviors and coordinators.\n */\n\nimport { Vector3, Quaternion } from 'three';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// TransformComponent (render-facing)\n// Written only by PhysicsSyncBehavior, read by rendering/animation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface TransformComponent {\n\tposition: Vector3;\n\trotation: Quaternion;\n}\n\nexport function createTransformComponent(): TransformComponent {\n\treturn {\n\t\tposition: new Vector3(),\n\t\trotation: new Quaternion(),\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// PhysicsBodyComponent (bridge to the host physics reference, not state)\n// ECS does not store velocity, mass, etc. — the wasm runtime owns all\n// physical truth; `body` is an opaque host-owned reference.\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PhysicsBodyComponent {\n\tbody: unknown;\n}\n\nexport function createPhysicsBodyComponent(body: unknown): PhysicsBodyComponent {\n\treturn { body };\n}\n"],"mappings":";AAWO,SAAS,YAMZ,QACA,YACA,SACK;AACL,SAAO,IAAI,YAAY,OAAO;AAC9B,SAAO;AACX;;;ACjBA,SAAS,SAAS,kBAAkB;AAY7B,SAAS,2BAA+C;AAC9D,SAAO;AAAA,IACN,UAAU,IAAI,QAAQ;AAAA,IACtB,UAAU,IAAI,WAAW;AAAA,EAC1B;AACD;AAYO,SAAS,2BAA2B,MAAqC;AAC/E,SAAO,EAAE,KAAK;AACf;","names":[]}
|
|
@@ -4,46 +4,19 @@ import {
|
|
|
4
4
|
createTopDownMovementStateComponent
|
|
5
5
|
} from "./chunk-EIWQM6U3.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./chunk-Y7YIAWPW.js";
|
|
7
|
+
resolveAim2D
|
|
8
|
+
} from "./chunk-TBUKJKY6.js";
|
|
10
9
|
import {
|
|
11
10
|
StageTopDownPlane
|
|
12
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-E4X4YJZB.js";
|
|
13
12
|
import {
|
|
14
13
|
defineBehavior
|
|
15
14
|
} from "./chunk-EZNCCO4L.js";
|
|
16
15
|
|
|
17
|
-
// src/lib/behaviors/top-down-movement/top-down-movement.system.ts
|
|
18
|
-
var _moveDirection = { x: 0, y: 0 };
|
|
19
|
-
var _facingDirection = { x: 0, y: 0 };
|
|
20
|
-
var TopDownMovementSystem = class {
|
|
21
|
-
updateEntity(entity, _delta) {
|
|
22
|
-
if (!entity.body || !entity.transformStore || !entity.topDownMovement || !entity.$topDownMovement || !entity.topDownMovementState) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const movement = entity.topDownMovement;
|
|
26
|
-
const input = entity.$topDownMovement;
|
|
27
|
-
const state = entity.topDownMovementState;
|
|
28
|
-
const isMoving = normalizeDirection2DInto(input.moveX, input.moveY, _moveDirection);
|
|
29
|
-
const velocity = entity.body.linvel();
|
|
30
|
-
state.moving = isMoving;
|
|
31
|
-
entity.transformStore.velocity.x = isMoving ? _moveDirection.x * movement.moveSpeed : 0;
|
|
32
|
-
entity.transformStore.velocity.y = isMoving ? _moveDirection.y * movement.moveSpeed : 0;
|
|
33
|
-
entity.transformStore.velocity.z = velocity.z;
|
|
34
|
-
entity.transformStore.dirty.velocityX = true;
|
|
35
|
-
entity.transformStore.dirty.velocityY = true;
|
|
36
|
-
entity.transformStore.dirty.velocityZ = true;
|
|
37
|
-
if (normalizeDirection2DInto(input.faceX, input.faceY, _facingDirection)) {
|
|
38
|
-
state.facingAngle = angleFromDirection2D(_facingDirection);
|
|
39
|
-
}
|
|
40
|
-
entity.setRotationZ?.(state.facingAngle);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
16
|
// src/lib/behaviors/top-down-movement/top-down-movement.descriptor.ts
|
|
45
17
|
var defaultOptions = {
|
|
46
|
-
moveSpeed: 8
|
|
18
|
+
moveSpeed: 8,
|
|
19
|
+
faceMovement: false
|
|
47
20
|
};
|
|
48
21
|
var TOP_DOWN_MOVEMENT_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for(
|
|
49
22
|
"zylem:behavior:top-down-movement"
|
|
@@ -60,9 +33,8 @@ var TopDownMovementBehaviorSystem = class {
|
|
|
60
33
|
}
|
|
61
34
|
wasmStage;
|
|
62
35
|
getBehaviorLinks;
|
|
63
|
-
behavior = new TopDownMovementSystem();
|
|
64
36
|
attachedRuntimeSlots = /* @__PURE__ */ new Set();
|
|
65
|
-
update(_ecs,
|
|
37
|
+
update(_ecs, _delta) {
|
|
66
38
|
const links = this.getBehaviorLinks?.(TOP_DOWN_MOVEMENT_BEHAVIOR_KEY);
|
|
67
39
|
if (!links) return;
|
|
68
40
|
for (const link of links) {
|
|
@@ -79,16 +51,25 @@ var TopDownMovementBehaviorSystem = class {
|
|
|
79
51
|
}
|
|
80
52
|
ref.__entity = entity;
|
|
81
53
|
const handle = entity.runtimeHandle ?? -1;
|
|
82
|
-
if (this.wasmStage
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
54
|
+
if (!this.wasmStage || handle < 0) continue;
|
|
55
|
+
this.ensureWasmAttached(handle, ref.options);
|
|
56
|
+
const input = entity.$topDownMovement;
|
|
57
|
+
const state = entity.topDownMovementState;
|
|
58
|
+
if (input) {
|
|
59
|
+
const moveX = input.moveX ?? 0;
|
|
60
|
+
const moveY = input.moveY ?? input.moveZ ?? 0;
|
|
61
|
+
this.wasmStage.writeInputAxes(handle, moveX, moveY);
|
|
62
|
+
state.moving = Math.hypot(moveX, moveY) > 1e-3;
|
|
63
|
+
const aim = resolveAim2D(
|
|
64
|
+
input.faceX ?? 0,
|
|
65
|
+
input.faceY ?? 0,
|
|
66
|
+
state.facingAngle
|
|
67
|
+
);
|
|
68
|
+
if (aim.hasAimInput) {
|
|
69
|
+
state.facingAngle = aim.angle;
|
|
70
|
+
entity.setRotationZ?.(aim.angle);
|
|
87
71
|
}
|
|
88
|
-
continue;
|
|
89
72
|
}
|
|
90
|
-
if (!entity.body || !entity.transformStore) continue;
|
|
91
|
-
this.behavior.updateEntity(entity, delta);
|
|
92
73
|
}
|
|
93
74
|
}
|
|
94
75
|
ensureWasmAttached(handle, options) {
|
|
@@ -96,7 +77,7 @@ var TopDownMovementBehaviorSystem = class {
|
|
|
96
77
|
this.wasmStage.attachTopDown(handle, {
|
|
97
78
|
plane: StageTopDownPlane.Xy,
|
|
98
79
|
speed: options.moveSpeed ?? defaultOptions.moveSpeed,
|
|
99
|
-
faceMovement:
|
|
80
|
+
faceMovement: options.faceMovement ?? defaultOptions.faceMovement
|
|
100
81
|
});
|
|
101
82
|
this.attachedRuntimeSlots.add(handle);
|
|
102
83
|
}
|
|
@@ -112,7 +93,6 @@ var TopDownMovementBehavior = defineBehavior({
|
|
|
112
93
|
});
|
|
113
94
|
|
|
114
95
|
export {
|
|
115
|
-
TopDownMovementSystem,
|
|
116
96
|
TopDownMovementBehavior
|
|
117
97
|
};
|
|
118
|
-
//# sourceMappingURL=chunk-
|
|
98
|
+
//# sourceMappingURL=chunk-5EBIIYZD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/top-down-movement/top-down-movement.descriptor.ts"],"sourcesContent":["import { defineBehavior, type BehaviorRef } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport {\n\tcreateTopDownMovementComponent,\n\tcreateTopDownMovementInputComponent,\n\tcreateTopDownMovementStateComponent,\n} from './components';\nimport type {\n\tTopDownMovementComponent,\n\tTopDownMovementInputComponent,\n\tTopDownMovementStateComponent,\n} from './components';\nimport {\n\tStageTopDownPlane,\n\ttype BehaviorRuntime,\n} from '../../runtime/wasm-stage-runtime';\nimport { resolveAim2D } from '../../coordinators/shared/top-down-aim';\n\n/**\n * Entity with top-down movement components (input written by the game,\n * simulation owned by the wasm runtime).\n */\nexport interface TopDownMovementEntity {\n\ttopDownMovement: TopDownMovementComponent;\n\t$topDownMovement: TopDownMovementInputComponent;\n\ttopDownMovementState: TopDownMovementStateComponent;\n}\n\nexport interface TopDownMovementBehaviorOptions {\n\tmoveSpeed?: number;\n\t/** When true, WASM rotates toward velocity; default false for twin-stick face axes. */\n\tfaceMovement?: boolean;\n}\n\nexport interface TopDownMovementHandle {\n\tgetFacingAngle(): number;\n}\n\nconst defaultOptions: TopDownMovementBehaviorOptions = {\n\tmoveSpeed: 8,\n\tfaceMovement: false,\n};\n\nconst TOP_DOWN_MOVEMENT_BEHAVIOR_KEY = Symbol.for(\n\t'zylem:behavior:top-down-movement',\n);\n\nfunction createTopDownMovementHandle(\n\tref: BehaviorRef<TopDownMovementBehaviorOptions>,\n): TopDownMovementHandle {\n\treturn {\n\t\tgetFacingAngle: () =>\n\t\t\t(ref as any).__entity?.topDownMovementState?.facingAngle ?? 0,\n\t};\n}\n\nclass TopDownMovementBehaviorSystem implements BehaviorSystem {\n\tprivate attachedRuntimeSlots = new Set<number>();\n\n\tconstructor(\n\t\tprivate wasmStage: BehaviorRuntime | 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?.(TOP_DOWN_MOVEMENT_BEHAVIOR_KEY);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst entity = link.entity as any;\n\t\t\tconst ref = link.ref as any;\n\n\t\t\tif (!entity.topDownMovement) {\n\t\t\t\tentity.topDownMovement = createTopDownMovementComponent(ref.options);\n\t\t\t}\n\t\t\tif (!entity.$topDownMovement) {\n\t\t\t\tentity.$topDownMovement = createTopDownMovementInputComponent();\n\t\t\t}\n\t\t\tif (!entity.topDownMovementState) {\n\t\t\t\tentity.topDownMovementState = createTopDownMovementStateComponent();\n\t\t\t}\n\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) continue;\n\n\t\t\tthis.ensureWasmAttached(handle, ref.options as TopDownMovementBehaviorOptions);\n\t\t\tconst input = entity.$topDownMovement;\n\t\t\tconst state = entity.topDownMovementState;\n\t\t\tif (input) {\n\t\t\t\tconst moveX = input.moveX ?? 0;\n\t\t\t\tconst moveY = input.moveY ?? input.moveZ ?? 0;\n\t\t\t\tthis.wasmStage.writeInputAxes(handle, moveX, moveY);\n\t\t\t\tstate.moving = Math.hypot(moveX, moveY) > 0.001;\n\n\t\t\t\tconst aim = resolveAim2D(\n\t\t\t\t\tinput.faceX ?? 0,\n\t\t\t\t\tinput.faceY ?? 0,\n\t\t\t\t\tstate.facingAngle,\n\t\t\t\t);\n\t\t\t\tif (aim.hasAimInput) {\n\t\t\t\t\tstate.facingAngle = aim.angle;\n\t\t\t\t\tentity.setRotationZ?.(aim.angle);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: TopDownMovementBehaviorOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tthis.wasmStage.attachTopDown(handle, {\n\t\t\tplane: StageTopDownPlane.Xy,\n\t\t\tspeed: options.moveSpeed ?? defaultOptions.moveSpeed!,\n\t\t\tfaceMovement: options.faceMovement ?? defaultOptions.faceMovement!,\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 TopDownMovementBehavior = defineBehavior<\n\tTopDownMovementBehaviorOptions,\n\tTopDownMovementHandle,\n\tTopDownMovementEntity\n>({\n\tname: 'top-down-movement',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew TopDownMovementBehaviorSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n\tcreateHandle: createTopDownMovementHandle,\n});\n"],"mappings":";;;;;;;;;;;;;;;;AAsCA,IAAM,iBAAiD;AAAA,EACtD,WAAW;AAAA,EACX,cAAc;AACf;AAEA,IAAM,iCAAiC,uBAAO;AAAA,EAC7C;AACD;AAEA,SAAS,4BACR,KACwB;AACxB,SAAO;AAAA,IACN,gBAAgB,MACd,IAAY,UAAU,sBAAsB,eAAe;AAAA,EAC9D;AACD;AAEA,IAAM,gCAAN,MAA8D;AAAA,EAG7D,YACS,WACA,kBACP;AAFO;AACA;AAAA,EACN;AAAA,EAFM;AAAA,EACA;AAAA,EAJD,uBAAuB,oBAAI,IAAY;AAAA,EAO/C,OAAO,MAAe,QAAsB;AAC3C,UAAM,QAAQ,KAAK,mBAAmB,8BAA8B;AACpE,QAAI,CAAC,MAAO;AAEZ,eAAW,QAAQ,OAAO;AACzB,YAAM,SAAS,KAAK;AACpB,YAAM,MAAM,KAAK;AAEjB,UAAI,CAAC,OAAO,iBAAiB;AAC5B,eAAO,kBAAkB,+BAA+B,IAAI,OAAO;AAAA,MACpE;AACA,UAAI,CAAC,OAAO,kBAAkB;AAC7B,eAAO,mBAAmB,oCAAoC;AAAA,MAC/D;AACA,UAAI,CAAC,OAAO,sBAAsB;AACjC,eAAO,uBAAuB,oCAAoC;AAAA,MACnE;AAEA,UAAI,WAAW;AAEf,YAAM,SAAU,OAAO,iBAAiB;AACxC,UAAI,CAAC,KAAK,aAAa,SAAS,EAAG;AAEnC,WAAK,mBAAmB,QAAQ,IAAI,OAAyC;AAC7E,YAAM,QAAQ,OAAO;AACrB,YAAM,QAAQ,OAAO;AACrB,UAAI,OAAO;AACV,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,QAAQ,MAAM,SAAS,MAAM,SAAS;AAC5C,aAAK,UAAU,eAAe,QAAQ,OAAO,KAAK;AAClD,cAAM,SAAS,KAAK,MAAM,OAAO,KAAK,IAAI;AAE1C,cAAM,MAAM;AAAA,UACX,MAAM,SAAS;AAAA,UACf,MAAM,SAAS;AAAA,UACf,MAAM;AAAA,QACP;AACA,YAAI,IAAI,aAAa;AACpB,gBAAM,cAAc,IAAI;AACxB,iBAAO,eAAe,IAAI,KAAK;AAAA,QAChC;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,mBAAmB,QAAgB,SAA+C;AACzF,QAAI,CAAC,KAAK,aAAa,KAAK,qBAAqB,IAAI,MAAM,EAAG;AAC9D,SAAK,UAAU,cAAc,QAAQ;AAAA,MACpC,OAAO,kBAAkB;AAAA,MACzB,OAAO,QAAQ,aAAa,eAAe;AAAA,MAC3C,cAAc,QAAQ,gBAAgB,eAAe;AAAA,IACtD,CAAC;AACD,SAAK,qBAAqB,IAAI,MAAM;AAAA,EACrC;AAAA,EAEA,QAAQ,MAAqB;AAC5B,SAAK,qBAAqB,MAAM;AAAA,EACjC;AACD;AAEO,IAAM,0BAA0B,eAIrC;AAAA,EACD,MAAM;AAAA,EACN;AAAA,EACA,eAAe,CAAC,QACf,IAAI,8BAA8B,IAAI,aAAa,MAAM,IAAI,gBAAgB;AAAA,EAC9E,cAAc;AACf,CAAC;","names":[]}
|