@zylem/behaviors 0.4.1 → 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-y8SGrGWy.d.ts → behavior-system-CeJXzNvr.d.ts} +305 -17
- 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-A4CA35DQ.js → chunk-5EBIIYZD.js} +25 -45
- package/dist/chunk-5EBIIYZD.js.map +1 -0
- package/dist/{chunk-4L36OPY2.js → chunk-5NJGASUJ.js} +81 -135
- package/dist/chunk-5NJGASUJ.js.map +1 -0
- package/dist/{chunk-27UPCP5B.js → chunk-5UMCWV5A.js} +22 -13
- 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-Z72F2ENM.js → chunk-AEBDZWCP.js} +17 -26
- 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-VMQHNJJI.js → chunk-F6ESSHQK.js} +17 -23
- 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-QDCJLJUV.js → chunk-KOWGILCN.js} +22 -13
- 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 +480 -13
- 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 -8
- 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 -9
- package/dist/jumper-3d.d.ts +5 -39
- package/dist/jumper-3d.js +5 -10
- package/dist/{moveable-Cl9h-_w7.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 -5
- package/dist/platformer-3d.d.ts +13 -78
- package/dist/platformer-3d.js +4 -5
- 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 +2 -3
- package/dist/chunk-27UPCP5B.js.map +0 -1
- package/dist/chunk-4L36OPY2.js.map +0 -1
- package/dist/chunk-4URF65BR.js +0 -44
- package/dist/chunk-4URF65BR.js.map +0 -1
- package/dist/chunk-5XZWTFGF.js.map +0 -1
- package/dist/chunk-67XLJ26X.js +0 -536
- package/dist/chunk-67XLJ26X.js.map +0 -1
- package/dist/chunk-75FJIUIG.js +0 -240
- package/dist/chunk-75FJIUIG.js.map +0 -1
- package/dist/chunk-A4CA35DQ.js.map +0 -1
- package/dist/chunk-BXP4K7RF.js.map +0 -1
- package/dist/chunk-F72WX4MH.js +0 -422
- package/dist/chunk-F72WX4MH.js.map +0 -1
- package/dist/chunk-GFARAJV2.js.map +0 -1
- package/dist/chunk-JXMF4NUI.js +0 -309
- package/dist/chunk-JXMF4NUI.js.map +0 -1
- package/dist/chunk-OTLSUYQQ.js +0 -29
- package/dist/chunk-OTLSUYQQ.js.map +0 -1
- package/dist/chunk-Q75LKHDF.js +0 -56
- package/dist/chunk-Q75LKHDF.js.map +0 -1
- package/dist/chunk-QDCJLJUV.js.map +0 -1
- package/dist/chunk-RDHSHEZM.js +0 -479
- package/dist/chunk-RDHSHEZM.js.map +0 -1
- package/dist/chunk-UIG7MWS2.js +0 -518
- package/dist/chunk-UIG7MWS2.js.map +0 -1
- package/dist/chunk-UL6Q5HDP.js.map +0 -1
- package/dist/chunk-VMQHNJJI.js.map +0 -1
- package/dist/chunk-WWVD5DR5.js.map +0 -1
- package/dist/chunk-Z72F2ENM.js.map +0 -1
- package/dist/components-BWG1GkZA.d.ts +0 -20
- package/dist/use-behavior-B85d5u7-.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 +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":[]}
|
|
@@ -6,18 +6,15 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
VEC3_ZERO,
|
|
8
8
|
toThreeVector3
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import {
|
|
11
|
-
setVelocityIntent
|
|
12
|
-
} from "./chunk-OTLSUYQQ.js";
|
|
9
|
+
} from "./chunk-M3QDKKDF.js";
|
|
13
10
|
import {
|
|
14
11
|
SyncStateMachine,
|
|
15
|
-
|
|
16
|
-
} from "./chunk-
|
|
12
|
+
import_typescript_fsm
|
|
13
|
+
} from "./chunk-AS3HR7AS.js";
|
|
17
14
|
import {
|
|
18
15
|
STAGE_INPUT_BUTTON_RUN,
|
|
19
16
|
readBehaviorSnapshot
|
|
20
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-E4X4YJZB.js";
|
|
21
18
|
import {
|
|
22
19
|
defineBehavior
|
|
23
20
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -42,17 +39,17 @@ var FirstPersonFSM = class {
|
|
|
42
39
|
"idle" /* Idle */,
|
|
43
40
|
[
|
|
44
41
|
// Idle transitions
|
|
45
|
-
t("idle" /* Idle */, "walk" /* Walk */, "walking" /* Walking */),
|
|
46
|
-
t("idle" /* Idle */, "run" /* Run */, "running" /* Running */),
|
|
47
|
-
t("idle" /* Idle */, "stop" /* Stop */, "idle" /* Idle */),
|
|
42
|
+
(0, import_typescript_fsm.t)("idle" /* Idle */, "walk" /* Walk */, "walking" /* Walking */),
|
|
43
|
+
(0, import_typescript_fsm.t)("idle" /* Idle */, "run" /* Run */, "running" /* Running */),
|
|
44
|
+
(0, import_typescript_fsm.t)("idle" /* Idle */, "stop" /* Stop */, "idle" /* Idle */),
|
|
48
45
|
// Walking transitions
|
|
49
|
-
t("walking" /* Walking */, "run" /* Run */, "running" /* Running */),
|
|
50
|
-
t("walking" /* Walking */, "stop" /* Stop */, "idle" /* Idle */),
|
|
51
|
-
t("walking" /* Walking */, "walk" /* Walk */, "walking" /* Walking */),
|
|
46
|
+
(0, import_typescript_fsm.t)("walking" /* Walking */, "run" /* Run */, "running" /* Running */),
|
|
47
|
+
(0, import_typescript_fsm.t)("walking" /* Walking */, "stop" /* Stop */, "idle" /* Idle */),
|
|
48
|
+
(0, import_typescript_fsm.t)("walking" /* Walking */, "walk" /* Walk */, "walking" /* Walking */),
|
|
52
49
|
// Running transitions
|
|
53
|
-
t("running" /* Running */, "walk" /* Walk */, "walking" /* Walking */),
|
|
54
|
-
t("running" /* Running */, "stop" /* Stop */, "idle" /* Idle */),
|
|
55
|
-
t("running" /* Running */, "run" /* Run */, "running" /* Running */)
|
|
50
|
+
(0, import_typescript_fsm.t)("running" /* Running */, "walk" /* Walk */, "walking" /* Walking */),
|
|
51
|
+
(0, import_typescript_fsm.t)("running" /* Running */, "stop" /* Stop */, "idle" /* Idle */),
|
|
52
|
+
(0, import_typescript_fsm.t)("running" /* Running */, "run" /* Run */, "running" /* Running */)
|
|
56
53
|
]
|
|
57
54
|
);
|
|
58
55
|
}
|
|
@@ -97,20 +94,15 @@ var FirstPersonFSM = class {
|
|
|
97
94
|
|
|
98
95
|
// src/lib/behaviors/first-person/first-person.system.ts
|
|
99
96
|
import { Vector3, Quaternion, Euler } from "three";
|
|
100
|
-
var _forward = new Vector3();
|
|
101
|
-
var _right = new Vector3();
|
|
102
|
-
var _up = new Vector3(0, 1, 0);
|
|
103
97
|
var _viewmodelQuat = new Quaternion();
|
|
104
98
|
var _viewmodelLocalQuat = new Quaternion();
|
|
105
99
|
var _viewmodelEuler = new Euler();
|
|
106
100
|
var _offset = new Vector3();
|
|
107
|
-
var
|
|
108
|
-
|
|
101
|
+
var _pose = { position: [0, 0, 0], rotation: [0, 0, 0, 1] };
|
|
102
|
+
var _snapshot = {};
|
|
103
|
+
var FirstPersonPresentation = class {
|
|
109
104
|
perspectives = /* @__PURE__ */ new Map();
|
|
110
105
|
viewmodels = /* @__PURE__ */ new Map();
|
|
111
|
-
constructor(world) {
|
|
112
|
-
this.world = world;
|
|
113
|
-
}
|
|
114
106
|
/**
|
|
115
107
|
* Associate a FirstPersonPerspective with an entity (by uuid).
|
|
116
108
|
* Called once by the descriptor system when the behavior is initialized.
|
|
@@ -132,78 +124,36 @@ var FirstPersonSystem = class {
|
|
|
132
124
|
return this.viewmodels.has(entityUuid);
|
|
133
125
|
}
|
|
134
126
|
/**
|
|
135
|
-
*
|
|
127
|
+
* Sync camera + viewmodel for one entity from the runtime state.
|
|
136
128
|
*/
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
129
|
+
syncEntity(entityUuid, runtime, handle, movement, state) {
|
|
130
|
+
const perspective = this.perspectives.get(entityUuid);
|
|
131
|
+
const pose = runtime.getPose(handle, _pose);
|
|
132
|
+
const snapshot = runtime.readSnapshot(handle, _snapshot);
|
|
133
|
+
if (perspective && snapshot) {
|
|
134
|
+
perspective.setLook?.(snapshot.yaw, snapshot.pitch);
|
|
135
|
+
if (state) {
|
|
136
|
+
state.yaw = snapshot.yaw;
|
|
137
|
+
state.pitch = snapshot.pitch;
|
|
138
|
+
state.currentSpeed = snapshot.speed;
|
|
139
|
+
}
|
|
141
140
|
}
|
|
142
|
-
|
|
143
|
-
const movement = fpEntity.firstPerson;
|
|
144
|
-
const state = fpEntity.firstPersonState;
|
|
145
|
-
const perspective = this.perspectives.get(fpEntity.uuid);
|
|
146
|
-
if (perspective?.initialPosition && fpEntity.body) {
|
|
147
|
-
const pos = fpEntity.body.translation();
|
|
141
|
+
if (perspective?.initialPosition && pose) {
|
|
148
142
|
perspective.initialPosition.set(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
if (perspective) {
|
|
155
|
-
perspective.look(
|
|
156
|
-
-input.lookX * movement.lookSensitivity,
|
|
157
|
-
-input.lookY * movement.lookSensitivity
|
|
143
|
+
pose.position[0],
|
|
144
|
+
pose.position[1] + movement.eyeHeight,
|
|
145
|
+
pose.position[2]
|
|
158
146
|
);
|
|
159
|
-
state.yaw = perspective.yaw;
|
|
160
|
-
state.pitch = perspective.pitch;
|
|
161
|
-
}
|
|
162
|
-
const speed = input.sprint ? movement.runSpeed : movement.walkSpeed;
|
|
163
|
-
state.currentSpeed = speed;
|
|
164
|
-
const hasMovement = Math.abs(input.moveX) > 0.1 || Math.abs(input.moveZ) > 0.1;
|
|
165
|
-
if (fpEntity.transformStore) {
|
|
166
|
-
if (hasMovement) {
|
|
167
|
-
_forward.set(0, 0, -1).applyAxisAngle(_up, state.yaw);
|
|
168
|
-
_right.set(1, 0, 0).applyAxisAngle(_up, state.yaw);
|
|
169
|
-
const vx = _right.x * input.moveX * speed + _forward.x * -input.moveZ * speed;
|
|
170
|
-
const vz = _right.z * input.moveX * speed + _forward.z * -input.moveZ * speed;
|
|
171
|
-
setVelocityIntent(
|
|
172
|
-
fpEntity.transformStore,
|
|
173
|
-
"first-person",
|
|
174
|
-
{ x: vx, z: vz },
|
|
175
|
-
{ mode: "replace", priority: 10 }
|
|
176
|
-
);
|
|
177
|
-
} else {
|
|
178
|
-
setVelocityIntent(
|
|
179
|
-
fpEntity.transformStore,
|
|
180
|
-
"first-person",
|
|
181
|
-
{ x: 0, z: 0 },
|
|
182
|
-
{ mode: "replace", priority: 10 }
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const vm = this.viewmodels.get(fpEntity.uuid);
|
|
187
|
-
if (vm && perspective?.initialPosition) {
|
|
188
|
-
this.positionViewmodel(vm, perspective, state);
|
|
189
147
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
*/
|
|
194
|
-
update(delta) {
|
|
195
|
-
if (!this.world?.collisionMap) return;
|
|
196
|
-
for (const [, entity] of this.world.collisionMap) {
|
|
197
|
-
this.updateEntity(entity, delta);
|
|
148
|
+
const vm = this.viewmodels.get(entityUuid);
|
|
149
|
+
if (vm && perspective?.initialPosition && state) {
|
|
150
|
+
this.positionViewmodel(vm, perspective, state, runtime);
|
|
198
151
|
}
|
|
199
152
|
}
|
|
200
153
|
/**
|
|
201
154
|
* Position a viewmodel entity relative to the camera's eye position and rotation.
|
|
202
|
-
*
|
|
203
|
-
* The physics transform system overwrites group.position from the rigid body
|
|
204
|
-
* each frame, so we must also move the body to keep them in sync.
|
|
205
155
|
*/
|
|
206
|
-
positionViewmodel(vm, perspective, state) {
|
|
156
|
+
positionViewmodel(vm, perspective, state, runtime) {
|
|
207
157
|
const eyePos = perspective.initialPosition;
|
|
208
158
|
if (!eyePos) return;
|
|
209
159
|
_viewmodelQuat.setFromEuler(
|
|
@@ -218,11 +168,15 @@ var FirstPersonSystem = class {
|
|
|
218
168
|
const wy = eyePos.y + _offset.y;
|
|
219
169
|
const wz = eyePos.z + _offset.z;
|
|
220
170
|
const entity = vm.entity;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
171
|
+
const handle = entity?.runtimeHandle ?? -1;
|
|
172
|
+
if (handle >= 0) {
|
|
173
|
+
runtime.setPosition(handle, wx, wy, wz);
|
|
174
|
+
runtime.setRotation(
|
|
175
|
+
handle,
|
|
176
|
+
_viewmodelQuat.x,
|
|
177
|
+
_viewmodelQuat.y,
|
|
178
|
+
_viewmodelQuat.z,
|
|
179
|
+
_viewmodelQuat.w
|
|
226
180
|
);
|
|
227
181
|
}
|
|
228
182
|
if (entity?.group) {
|
|
@@ -248,35 +202,21 @@ var FIRST_PERSON_BEHAVIOR_KEY = /* @__PURE__ */ Symbol.for(
|
|
|
248
202
|
"zylem:behavior:first-person-controller"
|
|
249
203
|
);
|
|
250
204
|
var FirstPersonBehaviorSystem = class {
|
|
251
|
-
constructor(
|
|
205
|
+
constructor(wasmStage, getBehaviorLinks) {
|
|
252
206
|
this.wasmStage = wasmStage;
|
|
253
207
|
this.getBehaviorLinks = getBehaviorLinks;
|
|
254
|
-
this.behavior = new FirstPersonSystem(world);
|
|
255
208
|
}
|
|
256
209
|
wasmStage;
|
|
257
210
|
getBehaviorLinks;
|
|
258
|
-
|
|
211
|
+
presentation = new FirstPersonPresentation();
|
|
259
212
|
attachedRuntimeSlots = /* @__PURE__ */ new Set();
|
|
260
|
-
update(_ecs,
|
|
213
|
+
update(_ecs, _delta) {
|
|
261
214
|
const links = this.getBehaviorLinks?.(FIRST_PERSON_BEHAVIOR_KEY);
|
|
262
215
|
if (!links) return;
|
|
263
216
|
for (const link of links) {
|
|
264
217
|
const gameEntity = link.entity;
|
|
265
218
|
const fpsRef = link.ref;
|
|
266
219
|
const options = fpsRef.options;
|
|
267
|
-
const handle = gameEntity.runtimeHandle ?? -1;
|
|
268
|
-
if (this.wasmStage && handle >= 0) {
|
|
269
|
-
this.ensureWasmAttached(handle, options);
|
|
270
|
-
fpsRef.__wasmStage = this.wasmStage;
|
|
271
|
-
fpsRef.__entity = gameEntity;
|
|
272
|
-
const input = gameEntity.$fps;
|
|
273
|
-
if (input) {
|
|
274
|
-
this.wasmStage.writeInputAxes(handle, input.moveX ?? 0, input.moveZ ?? 0);
|
|
275
|
-
this.wasmStage.writeInputLook(handle, input.lookX ?? 0, input.lookY ?? 0);
|
|
276
|
-
this.wasmStage.writeInputButton(handle, STAGE_INPUT_BUTTON_RUN, !!input.sprint);
|
|
277
|
-
}
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
220
|
if (!gameEntity.firstPerson) {
|
|
281
221
|
gameEntity.firstPerson = createFirstPersonMovementComponent(options);
|
|
282
222
|
}
|
|
@@ -286,25 +226,33 @@ var FirstPersonBehaviorSystem = class {
|
|
|
286
226
|
if (!gameEntity.firstPersonState) {
|
|
287
227
|
gameEntity.firstPersonState = createFirstPersonStateComponent();
|
|
288
228
|
}
|
|
289
|
-
if (options.perspective && !this.
|
|
290
|
-
this.
|
|
229
|
+
if (options.perspective && !this.presentation.hasPerspective(gameEntity.uuid)) {
|
|
230
|
+
this.presentation.setPerspective(gameEntity.uuid, options.perspective);
|
|
291
231
|
}
|
|
292
|
-
if (options.viewmodel && !this.
|
|
293
|
-
this.
|
|
232
|
+
if (options.viewmodel && !this.presentation.hasViewmodel(gameEntity.uuid)) {
|
|
233
|
+
this.presentation.setViewmodel(gameEntity.uuid, {
|
|
294
234
|
...options.viewmodel,
|
|
295
235
|
offset: toThreeVector3(options.viewmodel.offset, VEC3_ZERO)
|
|
296
236
|
});
|
|
297
237
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (
|
|
305
|
-
|
|
238
|
+
const handle = gameEntity.runtimeHandle ?? -1;
|
|
239
|
+
if (!this.wasmStage || handle < 0) continue;
|
|
240
|
+
this.ensureWasmAttached(handle, options);
|
|
241
|
+
fpsRef.__wasmStage = this.wasmStage;
|
|
242
|
+
fpsRef.__entity = gameEntity;
|
|
243
|
+
const input = gameEntity.$fps;
|
|
244
|
+
if (input) {
|
|
245
|
+
this.wasmStage.writeInputAxes(handle, input.moveX ?? 0, input.moveZ ?? 0);
|
|
246
|
+
this.wasmStage.writeInputLook(handle, input.lookX ?? 0, input.lookY ?? 0);
|
|
247
|
+
this.wasmStage.writeInputButton(handle, STAGE_INPUT_BUTTON_RUN, !!input.sprint);
|
|
306
248
|
}
|
|
307
|
-
this.
|
|
249
|
+
this.presentation.syncEntity(
|
|
250
|
+
gameEntity.uuid,
|
|
251
|
+
this.wasmStage,
|
|
252
|
+
handle,
|
|
253
|
+
gameEntity.firstPerson,
|
|
254
|
+
gameEntity.firstPersonState
|
|
255
|
+
);
|
|
308
256
|
}
|
|
309
257
|
}
|
|
310
258
|
ensureWasmAttached(handle, options) {
|
|
@@ -318,28 +266,26 @@ var FirstPersonBehaviorSystem = class {
|
|
|
318
266
|
this.attachedRuntimeSlots.add(handle);
|
|
319
267
|
}
|
|
320
268
|
destroy(_ecs) {
|
|
321
|
-
this.
|
|
269
|
+
this.presentation.destroy();
|
|
322
270
|
this.attachedRuntimeSlots.clear();
|
|
323
271
|
}
|
|
324
272
|
};
|
|
325
273
|
var FirstPersonBehavior = defineBehavior({
|
|
326
274
|
name: "first-person-controller",
|
|
327
275
|
defaultOptions,
|
|
328
|
-
systemFactory: (ctx) => new FirstPersonBehaviorSystem(ctx.
|
|
329
|
-
//
|
|
330
|
-
//
|
|
276
|
+
systemFactory: (ctx) => new FirstPersonBehaviorSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),
|
|
277
|
+
// Handles read the runtime snapshot buffer (previous-step values). The
|
|
278
|
+
// Rust behavior is the single source of truth.
|
|
331
279
|
createHandle: (ref) => ({
|
|
332
280
|
getState: () => {
|
|
333
281
|
const snapshot = readBehaviorSnapshot(ref);
|
|
334
|
-
if (snapshot)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
return ref.fsm?.getState() ?? "idle" /* Idle */;
|
|
282
|
+
if (!snapshot) return "idle" /* Idle */;
|
|
283
|
+
if (snapshot.speed <= 0.01) return "idle" /* Idle */;
|
|
284
|
+
const walkSpeed = ref.options.walkSpeed ?? defaultOptions.walkSpeed;
|
|
285
|
+
return snapshot.speed > walkSpeed ? "running" /* Running */ : "walking" /* Walking */;
|
|
340
286
|
},
|
|
341
|
-
getYaw: () => readBehaviorSnapshot(ref)?.yaw ??
|
|
342
|
-
getPitch: () => readBehaviorSnapshot(ref)?.pitch ??
|
|
287
|
+
getYaw: () => readBehaviorSnapshot(ref)?.yaw ?? 0,
|
|
288
|
+
getPitch: () => readBehaviorSnapshot(ref)?.pitch ?? 0,
|
|
343
289
|
attachViewmodel: (entity, offset) => {
|
|
344
290
|
if (ref.options) {
|
|
345
291
|
ref.options.viewmodel = { entity, offset };
|
|
@@ -352,7 +298,7 @@ export {
|
|
|
352
298
|
FirstPersonState,
|
|
353
299
|
FirstPersonEvent,
|
|
354
300
|
FirstPersonFSM,
|
|
355
|
-
|
|
301
|
+
FirstPersonPresentation,
|
|
356
302
|
FirstPersonBehavior
|
|
357
303
|
};
|
|
358
|
-
//# sourceMappingURL=chunk-
|
|
304
|
+
//# sourceMappingURL=chunk-5NJGASUJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/behaviors/first-person/first-person-fsm.ts","../src/lib/behaviors/first-person/first-person.system.ts","../src/lib/behaviors/first-person/first-person.descriptor.ts"],"sourcesContent":["/**\n * First Person Controller Finite State Machine\n *\n * Manages state transitions for first-person movement:\n * - Idle: Standing still\n * - Walking: Moving at walk speed\n * - Running: Moving at run/sprint speed\n */\n\nimport { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport type { FirstPersonInputComponent, FirstPersonStateComponent } from './components';\n\n/**\n * First-person movement states\n */\nexport enum FirstPersonState {\n\tIdle = 'idle',\n\tWalking = 'walking',\n\tRunning = 'running',\n}\n\n/**\n * Events that trigger state transitions\n */\nexport enum FirstPersonEvent {\n\tWalk = 'walk',\n\tRun = 'run',\n\tStop = 'stop',\n}\n\n/**\n * Context for the FSM\n */\nexport interface FirstPersonContext {\n\tinput: FirstPersonInputComponent;\n\tstate: FirstPersonStateComponent;\n}\n\n/**\n * First Person Controller FSM\n */\nexport class FirstPersonFSM {\n\tmachine: SyncStateMachine<FirstPersonState, FirstPersonEvent, never>;\n\n\tconstructor(private ctx: FirstPersonContext) {\n\t\tthis.machine = new SyncStateMachine<FirstPersonState, FirstPersonEvent, never>(\n\t\t\tFirstPersonState.Idle,\n\t\t\t[\n\t\t\t\t// Idle transitions\n\t\t\t\tt(FirstPersonState.Idle, FirstPersonEvent.Walk, FirstPersonState.Walking),\n\t\t\t\tt(FirstPersonState.Idle, FirstPersonEvent.Run, FirstPersonState.Running),\n\t\t\t\tt(FirstPersonState.Idle, FirstPersonEvent.Stop, FirstPersonState.Idle),\n\n\t\t\t\t// Walking transitions\n\t\t\t\tt(FirstPersonState.Walking, FirstPersonEvent.Run, FirstPersonState.Running),\n\t\t\t\tt(FirstPersonState.Walking, FirstPersonEvent.Stop, FirstPersonState.Idle),\n\t\t\t\tt(FirstPersonState.Walking, FirstPersonEvent.Walk, FirstPersonState.Walking),\n\n\t\t\t\t// Running transitions\n\t\t\t\tt(FirstPersonState.Running, FirstPersonEvent.Walk, FirstPersonState.Walking),\n\t\t\t\tt(FirstPersonState.Running, FirstPersonEvent.Stop, FirstPersonState.Idle),\n\t\t\t\tt(FirstPersonState.Running, FirstPersonEvent.Run, FirstPersonState.Running),\n\t\t\t],\n\t\t);\n\t}\n\n\t/** Get the current state */\n\tgetState(): FirstPersonState {\n\t\treturn this.machine.getState();\n\t}\n\n\t/** Dispatch an event to the FSM */\n\tdispatch(event: FirstPersonEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n\n\t/** Get the current yaw from context */\n\tgetYaw(): number {\n\t\treturn this.ctx.state.yaw;\n\t}\n\n\t/** Get the current pitch from context */\n\tgetPitch(): number {\n\t\treturn this.ctx.state.pitch;\n\t}\n\n\t/**\n\t * Update FSM based on current input and state.\n\t */\n\tupdate(input: FirstPersonInputComponent, state: FirstPersonStateComponent): void {\n\t\tthis.ctx.input = input;\n\t\tthis.ctx.state = state;\n\n\t\tconst hasMovement = Math.abs(input.moveX) > 0.1 || Math.abs(input.moveZ) > 0.1;\n\n\t\tif (hasMovement) {\n\t\t\tif (input.sprint) {\n\t\t\t\tthis.dispatch(FirstPersonEvent.Run);\n\t\t\t} else {\n\t\t\t\tthis.dispatch(FirstPersonEvent.Walk);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.dispatch(FirstPersonEvent.Stop);\n\t\t}\n\t}\n}\n","/**\n * First Person Presentation System\n *\n * Presentation-only companion to the wasm `first_person` Stage behavior:\n * - Syncs the FirstPersonPerspective eye position from the runtime pose\n * - Applies the runtime's yaw/pitch (from the behavior snapshot) to the\n * perspective so the camera matches the simulated look state\n * - Positions an optional viewmodel entity relative to the camera\n *\n * All movement/look simulation happens in the wasm runtime; this system only\n * reads poses and snapshots.\n */\n\nimport { Vector3, Quaternion, Euler } from 'three';\nimport type { FirstPersonPerspective } from '../../camera/perspectives/first-person-perspective';\nimport type {\n\tBehaviorRuntime,\n\tStagePose,\n\tStageBehaviorSnapshot,\n} from '../../runtime/wasm-stage-runtime';\nimport type {\n\tFirstPersonMovementComponent,\n\tFirstPersonInputComponent,\n\tFirstPersonStateComponent,\n} from './components';\nimport type { TransformState } from '../../capabilities/transform-store';\n\n/**\n * Entity interface for the first-person controller.\n * Entities with this behavior have these components attached.\n */\nexport interface FirstPersonEntity {\n\tuuid: string;\n\ttransformStore: TransformState;\n\tfirstPerson: FirstPersonMovementComponent;\n\t$fps: FirstPersonInputComponent;\n\tfirstPersonState: FirstPersonStateComponent;\n}\n\n/**\n * Viewmodel configuration for an entity that follows the camera.\n */\nexport interface ViewmodelConfig {\n\t/** The entity whose visual group should be positioned relative to the camera. */\n\tentity: any;\n\t/** Offset from the eye position in camera-local space (right, down, forward). */\n\toffset: Vector3;\n\t/** Additional rotation applied to the viewmodel in local space (Euler angles in radians). */\n\trotation?: Euler;\n}\n\n// Reusable temporaries (avoid per-frame allocations)\nconst _viewmodelQuat = new Quaternion();\nconst _viewmodelLocalQuat = new Quaternion();\nconst _viewmodelEuler = new Euler();\nconst _offset = new Vector3();\nconst _pose: StagePose = { position: [0, 0, 0], rotation: [0, 0, 0, 1] };\nconst _snapshot = {} as StageBehaviorSnapshot;\n\n/**\n * Presentation system driven by runtime pose + snapshot reads.\n */\nexport class FirstPersonPresentation {\n\tprivate perspectives = new Map<string, FirstPersonPerspective>();\n\tprivate viewmodels = new Map<string, ViewmodelConfig>();\n\n\t/**\n\t * Associate a FirstPersonPerspective with an entity (by uuid).\n\t * Called once by the descriptor system when the behavior is initialized.\n\t */\n\tsetPerspective(entityUuid: string, perspective: FirstPersonPerspective): void {\n\t\tthis.perspectives.set(entityUuid, perspective);\n\t}\n\n\thasPerspective(entityUuid: string): boolean {\n\t\treturn this.perspectives.has(entityUuid);\n\t}\n\n\t/**\n\t * Attach a viewmodel (weapon/item) to an entity.\n\t * The viewmodel entity's group will be positioned relative to the camera each frame.\n\t */\n\tsetViewmodel(entityUuid: string, config: ViewmodelConfig): void {\n\t\tthis.viewmodels.set(entityUuid, config);\n\t}\n\n\thasViewmodel(entityUuid: string): boolean {\n\t\treturn this.viewmodels.has(entityUuid);\n\t}\n\n\t/**\n\t * Sync camera + viewmodel for one entity from the runtime state.\n\t */\n\tsyncEntity(\n\t\tentityUuid: string,\n\t\truntime: BehaviorRuntime,\n\t\thandle: number,\n\t\tmovement: FirstPersonMovementComponent,\n\t\tstate: FirstPersonStateComponent | undefined,\n\t): void {\n\t\tconst perspective = this.perspectives.get(entityUuid);\n\t\tconst pose = runtime.getPose(handle, _pose);\n\t\tconst snapshot = runtime.readSnapshot(handle, _snapshot);\n\n\t\tif (perspective && snapshot) {\n\t\t\tperspective.setLook?.(snapshot.yaw, snapshot.pitch);\n\t\t\tif (state) {\n\t\t\t\tstate.yaw = snapshot.yaw;\n\t\t\t\tstate.pitch = snapshot.pitch;\n\t\t\t\tstate.currentSpeed = snapshot.speed;\n\t\t\t}\n\t\t}\n\n\t\tif (perspective?.initialPosition && pose) {\n\t\t\tperspective.initialPosition.set(\n\t\t\t\tpose.position[0],\n\t\t\t\tpose.position[1] + movement.eyeHeight,\n\t\t\t\tpose.position[2],\n\t\t\t);\n\t\t}\n\n\t\tconst vm = this.viewmodels.get(entityUuid);\n\t\tif (vm && perspective?.initialPosition && state) {\n\t\t\tthis.positionViewmodel(vm, perspective, state, runtime);\n\t\t}\n\t}\n\n\t/**\n\t * Position a viewmodel entity relative to the camera's eye position and rotation.\n\t */\n\tprivate positionViewmodel(\n\t\tvm: ViewmodelConfig,\n\t\tperspective: FirstPersonPerspective,\n\t\tstate: FirstPersonStateComponent,\n\t\truntime: BehaviorRuntime,\n\t): void {\n\t\tconst eyePos = perspective.initialPosition;\n\t\tif (!eyePos) return;\n\n\t\t// Build camera rotation quaternion\n\t\t_viewmodelQuat.setFromEuler(\n\t\t\t_viewmodelEuler.set(state.pitch, state.yaw, 0, 'YXZ'),\n\t\t);\n\n\t\t// Compose with the viewmodel's local rotation (model orientation fix)\n\t\tif (vm.rotation) {\n\t\t\t_viewmodelLocalQuat.setFromEuler(vm.rotation);\n\t\t\t_viewmodelQuat.multiply(_viewmodelLocalQuat);\n\t\t}\n\n\t\t// Transform the local offset into world space\n\t\t_offset.copy(vm.offset).applyQuaternion(_viewmodelQuat);\n\n\t\tconst wx = eyePos.x + _offset.x;\n\t\tconst wy = eyePos.y + _offset.y;\n\t\tconst wz = eyePos.z + _offset.z;\n\n\t\tconst entity = vm.entity;\n\n\t\t// Move the runtime body (if registered) so physics stays in sync\n\t\tconst handle = (entity?.runtimeHandle ?? -1) as number;\n\t\tif (handle >= 0) {\n\t\t\truntime.setPosition(handle, wx, wy, wz);\n\t\t\truntime.setRotation(\n\t\t\t\thandle,\n\t\t\t\t_viewmodelQuat.x, _viewmodelQuat.y, _viewmodelQuat.z, _viewmodelQuat.w,\n\t\t\t);\n\t\t}\n\n\t\t// Also set the group directly for immediate visual update\n\t\tif (entity?.group) {\n\t\t\tentity.group.position.set(wx, wy, wz);\n\t\t\tentity.group.quaternion.copy(_viewmodelQuat);\n\t\t}\n\t}\n\n\t/** Cleanup */\n\tdestroy(): void {\n\t\tthis.perspectives.clear();\n\t\tthis.viewmodels.clear();\n\t}\n}\n","/**\n * First Person Controller Behavior Descriptor\n *\n * Type-safe descriptor for the first-person controller behavior system.\n * Provides entity.use() API for FPS movement and camera control.\n */\n\nimport { Euler } from 'three';\nimport { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport type { FirstPersonPerspective } from '../../camera/perspectives/first-person-perspective';\nimport { Vec3Input, VEC3_ZERO, toThreeVector3 } from '../../core/vector';\nimport {\n\tFirstPersonPresentation,\n\ttype FirstPersonEntity,\n\ttype ViewmodelConfig,\n} from './first-person.system';\nimport { FirstPersonState } from './first-person-fsm';\nimport {\n\tcreateFirstPersonMovementComponent,\n\tcreateFirstPersonInputComponent,\n\tcreateFirstPersonStateComponent,\n} from './components';\nimport {\n\tSTAGE_INPUT_BUTTON_RUN,\n\treadBehaviorSnapshot,\n\ttype BehaviorRuntime,\n} from '../../runtime/wasm-stage-runtime';\n\n/**\n * First-person controller behavior options (typed for entity.use() autocomplete).\n */\nexport interface FirstPersonBehaviorOptions {\n\t/** Base walking speed (default: 8) */\n\twalkSpeed?: number;\n\t/** Sprint/run speed (default: 16) */\n\trunSpeed?: number;\n\t/** Look sensitivity multiplier (default: 2) */\n\tlookSensitivity?: number;\n\t/** Eye height offset above entity position (default: 1.7) */\n\teyeHeight?: number;\n\t/** The FirstPersonPerspective to drive (from camera.getPerspective()) */\n\tperspective?: FirstPersonPerspective;\n\t/** Optional viewmodel (weapon/item) to position relative to the camera */\n\tviewmodel?: { entity: any; offset: Vec3Input; rotation?: Euler };\n}\n\nconst defaultOptions: FirstPersonBehaviorOptions = {\n\twalkSpeed: 8,\n\trunSpeed: 16,\n\tlookSensitivity: 2,\n\teyeHeight: 1.7,\n};\n\nconst FIRST_PERSON_BEHAVIOR_KEY = Symbol.for(\n\t'zylem:behavior:first-person-controller',\n);\n\n/**\n * Forwards look/move input into the wasm runtime and syncs the camera\n * perspective + optional viewmodel from the runtime's pose/snapshot\n * (presentation only — the Rust `first_person` behavior owns simulation).\n */\nclass FirstPersonBehaviorSystem implements BehaviorSystem {\n\tprivate presentation = new FirstPersonPresentation();\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?.(FIRST_PERSON_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 fpsRef = link.ref as any;\n\n\t\t\tconst options = fpsRef.options as FirstPersonBehaviorOptions;\n\n\t\t\t// Initialize components (once)\n\t\t\tif (!gameEntity.firstPerson) {\n\t\t\t\tgameEntity.firstPerson = createFirstPersonMovementComponent(options);\n\t\t\t}\n\t\t\tif (!gameEntity.$fps) {\n\t\t\t\tgameEntity.$fps = createFirstPersonInputComponent();\n\t\t\t}\n\t\t\tif (!gameEntity.firstPersonState) {\n\t\t\t\tgameEntity.firstPersonState = createFirstPersonStateComponent();\n\t\t\t}\n\n\t\t\t// Wire up perspective (once)\n\t\t\tif (options.perspective && !this.presentation.hasPerspective(gameEntity.uuid)) {\n\t\t\t\tthis.presentation.setPerspective(gameEntity.uuid, options.perspective);\n\t\t\t}\n\n\t\t\t// Wire up viewmodel (once)\n\t\t\tif (options.viewmodel && !this.presentation.hasViewmodel(gameEntity.uuid)) {\n\t\t\t\tthis.presentation.setViewmodel(gameEntity.uuid, {\n\t\t\t\t\t...options.viewmodel,\n\t\t\t\t\toffset: toThreeVector3(options.viewmodel.offset, VEC3_ZERO),\n\t\t\t\t} as ViewmodelConfig);\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\tfpsRef.__wasmStage = this.wasmStage;\n\t\t\tfpsRef.__entity = gameEntity;\n\t\t\tconst input = gameEntity.$fps;\n\t\t\tif (input) {\n\t\t\t\tthis.wasmStage.writeInputAxes(handle, input.moveX ?? 0, input.moveZ ?? 0);\n\t\t\t\tthis.wasmStage.writeInputLook(handle, input.lookX ?? 0, input.lookY ?? 0);\n\t\t\t\tthis.wasmStage.writeInputButton(handle, STAGE_INPUT_BUTTON_RUN, !!input.sprint);\n\t\t\t}\n\n\t\t\tthis.presentation.syncEntity(\n\t\t\t\tgameEntity.uuid,\n\t\t\t\tthis.wasmStage,\n\t\t\t\thandle,\n\t\t\t\tgameEntity.firstPerson,\n\t\t\t\tgameEntity.firstPersonState,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate ensureWasmAttached(handle: number, options: FirstPersonBehaviorOptions): void {\n\t\tif (!this.wasmStage || this.attachedRuntimeSlots.has(handle)) return;\n\t\tthis.wasmStage.attachFirstPerson(handle, {\n\t\t\twalkSpeed: options.walkSpeed ?? defaultOptions.walkSpeed!,\n\t\t\trunSpeed: options.runSpeed ?? defaultOptions.runSpeed!,\n\t\t\teyeHeight: options.eyeHeight ?? defaultOptions.eyeHeight!,\n\t\t\tlookSensitivity: options.lookSensitivity ?? defaultOptions.lookSensitivity!,\n\t\t});\n\t\tthis.attachedRuntimeSlots.add(handle);\n\t}\n\n\tdestroy(_ecs: unknown): void {\n\t\tthis.presentation.destroy();\n\t\tthis.attachedRuntimeSlots.clear();\n\t}\n}\n\n/**\n * FirstPersonBehavior - typed descriptor for first-person movement and camera control.\n *\n * Provides complete first-person controller including:\n * - WASD movement relative to camera yaw\n * - Mouse look driving a FirstPersonPerspective\n * - Optional viewmodel positioning (weapon/item following camera)\n * - Walk/run state tracking via FSM\n *\n * @example\n * ```typescript\n * import { FirstPersonBehavior } from \"@zylem/game-lib/behavior\";\n * import { createCamera, Perspectives, FirstPersonPerspective } from \"@zylem/game-lib/core\";\n * import { createActor } from \"@zylem/game-lib/entity\";\n *\n * const fpsCamera = createCamera({ perspective: Perspectives.FirstPerson, ... });\n * const fps = fpsCamera.getPerspective<FirstPersonPerspective>();\n *\n * const player = createActor({ name: 'player', ... });\n * const controller = player.use(FirstPersonBehavior, {\n * perspective: fps,\n * walkSpeed: 8,\n * runSpeed: 16,\n * lookSensitivity: 2,\n * });\n *\n * // In update loop - write input, behavior handles the rest\n * player.onUpdate(({ inputs }) => {\n * player.$fps.moveX = inputs.p1.axes.Horizontal.value;\n * player.$fps.moveZ = inputs.p1.axes.Vertical.value;\n * player.$fps.lookX = inputs.p1.axes.SecondaryHorizontal.value;\n * player.$fps.lookY = inputs.p1.axes.SecondaryVertical.value;\n * player.$fps.sprint = inputs.p1.shoulders.LTrigger.held > 0;\n * });\n * ```\n */\nexport const FirstPersonBehavior = defineBehavior<\n\tFirstPersonBehaviorOptions,\n\t{\n\t\tgetState: () => FirstPersonState;\n\t\tgetYaw: () => number;\n\t\tgetPitch: () => number;\n\t\tattachViewmodel: (entity: any, offset: Vec3Input) => void;\n\t},\n\tFirstPersonEntity\n>({\n\tname: 'first-person-controller',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew FirstPersonBehaviorSystem(ctx.wasmStage ?? null, ctx.getBehaviorLinks),\n\t// Handles read the runtime snapshot buffer (previous-step values). The\n\t// Rust behavior is the single source of truth.\n\tcreateHandle: (ref) => ({\n\t\tgetState: () => {\n\t\t\tconst snapshot = readBehaviorSnapshot(ref);\n\t\t\tif (!snapshot) return FirstPersonState.Idle;\n\t\t\tif (snapshot.speed <= 0.01) return FirstPersonState.Idle;\n\t\t\tconst walkSpeed = ref.options.walkSpeed ?? defaultOptions.walkSpeed!;\n\t\t\treturn snapshot.speed > walkSpeed\n\t\t\t\t? FirstPersonState.Running\n\t\t\t\t: FirstPersonState.Walking;\n\t\t},\n\t\tgetYaw: () => readBehaviorSnapshot(ref)?.yaw ?? 0,\n\t\tgetPitch: () => readBehaviorSnapshot(ref)?.pitch ?? 0,\n\t\tattachViewmodel: (entity: any, offset: Vec3Input) => {\n\t\t\tif (ref.options) {\n\t\t\t\tref.options.viewmodel = { entity, offset };\n\t\t\t}\n\t\t},\n\t}),\n});\n"],"mappings":"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","names":["FirstPersonState","FirstPersonEvent"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SyncStateMachine,
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
import_typescript_fsm
|
|
4
|
+
} from "./chunk-AS3HR7AS.js";
|
|
5
5
|
import {
|
|
6
6
|
StageRicochetDim,
|
|
7
7
|
StageRicochetReflection
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-E4X4YJZB.js";
|
|
9
9
|
import {
|
|
10
10
|
defineBehavior
|
|
11
11
|
} from "./chunk-EZNCCO4L.js";
|
|
@@ -21,6 +21,13 @@ var Ricochet3DEvent = /* @__PURE__ */ ((Ricochet3DEvent2) => {
|
|
|
21
21
|
Ricochet3DEvent2["EndRicochet"] = "end-ricochet";
|
|
22
22
|
return Ricochet3DEvent2;
|
|
23
23
|
})(Ricochet3DEvent || {});
|
|
24
|
+
function bodyOf(entity) {
|
|
25
|
+
const body = entity?.body;
|
|
26
|
+
if (body && typeof body.linvel === "function" && typeof body.translation === "function") {
|
|
27
|
+
return body;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
24
31
|
function clamp(value, min, max) {
|
|
25
32
|
return Math.max(min, Math.min(max, value));
|
|
26
33
|
}
|
|
@@ -37,10 +44,10 @@ var Ricochet3DFSM = class {
|
|
|
37
44
|
this.machine = new SyncStateMachine(
|
|
38
45
|
"idle" /* Idle */,
|
|
39
46
|
[
|
|
40
|
-
t("idle" /* Idle */, "start-ricochet" /* StartRicochet */, "ricocheting" /* Ricocheting */),
|
|
41
|
-
t("ricocheting" /* Ricocheting */, "end-ricochet" /* EndRicochet */, "idle" /* Idle */),
|
|
42
|
-
t("idle" /* Idle */, "end-ricochet" /* EndRicochet */, "idle" /* Idle */),
|
|
43
|
-
t("ricocheting" /* Ricocheting */, "start-ricochet" /* StartRicochet */, "ricocheting" /* Ricocheting */)
|
|
47
|
+
(0, import_typescript_fsm.t)("idle" /* Idle */, "start-ricochet" /* StartRicochet */, "ricocheting" /* Ricocheting */),
|
|
48
|
+
(0, import_typescript_fsm.t)("ricocheting" /* Ricocheting */, "end-ricochet" /* EndRicochet */, "idle" /* Idle */),
|
|
49
|
+
(0, import_typescript_fsm.t)("idle" /* Idle */, "end-ricochet" /* EndRicochet */, "idle" /* Idle */),
|
|
50
|
+
(0, import_typescript_fsm.t)("ricocheting" /* Ricocheting */, "start-ricochet" /* StartRicochet */, "ricocheting" /* Ricocheting */)
|
|
44
51
|
]
|
|
45
52
|
);
|
|
46
53
|
}
|
|
@@ -146,14 +153,16 @@ var Ricochet3DFSM = class {
|
|
|
146
153
|
let selfPosition = ctx.selfPosition;
|
|
147
154
|
let otherPosition = ctx.otherPosition;
|
|
148
155
|
let otherSize = ctx.otherSize;
|
|
149
|
-
|
|
150
|
-
|
|
156
|
+
const selfBody = bodyOf(ctx.entity);
|
|
157
|
+
if (selfBody) {
|
|
158
|
+
const velocity = selfBody.linvel();
|
|
151
159
|
selfVelocity = selfVelocity ?? { x: velocity.x, y: velocity.y, z: velocity.z };
|
|
152
|
-
const position =
|
|
160
|
+
const position = selfBody.translation();
|
|
153
161
|
selfPosition = selfPosition ?? { x: position.x, y: position.y, z: position.z };
|
|
154
162
|
}
|
|
155
|
-
|
|
156
|
-
|
|
163
|
+
const otherBody = bodyOf(ctx.otherEntity);
|
|
164
|
+
if (otherBody) {
|
|
165
|
+
const position = otherBody.translation();
|
|
157
166
|
otherPosition = otherPosition ?? { x: position.x, y: position.y, z: position.z };
|
|
158
167
|
}
|
|
159
168
|
if (ctx.otherEntity && "size" in ctx.otherEntity) {
|
|
@@ -428,4 +437,4 @@ export {
|
|
|
428
437
|
Ricochet3DFSM,
|
|
429
438
|
Ricochet3DBehavior
|
|
430
439
|
};
|
|
431
|
-
//# sourceMappingURL=chunk-
|
|
440
|
+
//# sourceMappingURL=chunk-5UMCWV5A.js.map
|