@zylem/game-lib 0.3.14 → 0.3.16
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 +17 -14
- package/dist/.vite/manifest.json +595 -2
- package/dist/actions.d.ts +4 -0
- package/dist/actions.js +10 -0
- package/dist/behaviors.d.ts +3 -0
- package/dist/behaviors.js +8 -0
- package/dist/camera.d.ts +3 -0
- package/dist/camera.js +6 -0
- package/dist/core.d.ts +5 -0
- package/dist/core.js +11 -0
- package/dist/entities.d.ts +8 -0
- package/dist/entities.js +19 -0
- package/dist/lib/actions/behaviors/actions.js +35 -0
- package/dist/lib/actions/behaviors/boundaries/boundary.d.ts +1 -1
- package/dist/lib/actions/behaviors/boundaries/boundary.js +40 -0
- package/dist/lib/actions/behaviors/ricochet/ricochet-2d-collision.js +100 -0
- package/dist/lib/actions/behaviors/ricochet/ricochet-2d-in-bounds.js +37 -0
- package/dist/lib/actions/behaviors/ricochet/ricochet.d.ts +2 -0
- package/dist/lib/actions/behaviors/ricochet/ricochet.js +6 -0
- package/dist/lib/actions/capabilities/moveable.js +108 -0
- package/dist/lib/actions/capabilities/rotatable.js +82 -0
- package/dist/lib/actions/capabilities/transformable.js +9 -0
- package/dist/lib/actions/global-change.d.ts +10 -0
- package/dist/lib/actions/global-change.js +40 -0
- package/dist/lib/camera/camera.js +19 -0
- package/dist/lib/camera/fixed-2d.js +30 -0
- package/dist/lib/camera/perspective.js +10 -0
- package/dist/lib/camera/third-person.js +42 -0
- package/dist/lib/camera/zylem-camera.js +145 -0
- package/dist/lib/collision/collision-builder.d.ts +0 -2
- package/dist/lib/collision/collision-builder.js +46 -0
- package/dist/lib/collision/collision-delegate.js +6 -0
- package/dist/lib/collision/collision-group.d.ts +0 -17
- package/dist/lib/collision/utils.js +24 -0
- package/dist/lib/collision/world.js +77 -0
- package/dist/lib/core/base-node.js +58 -0
- package/dist/lib/core/entity-asset-loader.js +57 -0
- package/dist/lib/core/lazy-loader.d.ts +0 -2
- package/dist/lib/core/lifecycle-base.js +20 -0
- package/dist/lib/core/preset-shader.d.ts +2 -1
- package/dist/lib/core/preset-shader.js +30 -0
- package/dist/lib/core/three-addons/Timer.js +103 -0
- package/dist/lib/core/utility.js +20 -0
- package/dist/lib/core/vessel.js +23 -0
- package/dist/lib/debug/console/console-state.js +11 -0
- package/dist/lib/debug/debug-state.js +40 -0
- package/dist/lib/entities/actor.js +125 -0
- package/dist/lib/entities/box.js +68 -0
- package/dist/lib/entities/builder.js +79 -0
- package/dist/lib/entities/create.js +31 -0
- package/dist/lib/entities/delegates/animation.js +58 -0
- package/dist/lib/entities/delegates/debug.js +72 -0
- package/dist/lib/entities/delegates/loader.js +19 -0
- package/dist/lib/entities/destroy.js +15 -0
- package/dist/lib/entities/entity.d.ts +0 -2
- package/dist/lib/entities/entity.js +116 -0
- package/dist/lib/entities/plane.js +81 -0
- package/dist/lib/entities/rect.js +160 -0
- package/dist/lib/entities/sphere.js +68 -0
- package/dist/lib/entities/sprite.js +118 -0
- package/dist/lib/entities/text.js +111 -0
- package/dist/lib/entities/zone.js +103 -0
- package/dist/lib/game/game-state.js +17 -0
- package/dist/lib/game/game.js +157 -0
- package/dist/lib/game/zylem-game.d.ts +2 -0
- package/dist/lib/game/zylem-game.js +107 -0
- package/dist/lib/graphics/geometries/XZPlaneGeometry.js +34 -0
- package/dist/lib/graphics/material.js +64 -0
- package/dist/lib/graphics/mesh.js +14 -0
- package/dist/lib/graphics/render-pass.js +56 -0
- package/dist/lib/graphics/shaders/fragment/debug.glsl.js +23 -0
- package/dist/lib/graphics/shaders/fragment/fire.glsl.js +52 -0
- package/dist/lib/graphics/shaders/fragment/standard.glsl.js +11 -0
- package/dist/lib/graphics/shaders/fragment/stars.glsl.js +44 -0
- package/dist/lib/graphics/shaders/vertex/debug.glsl.js +15 -0
- package/dist/lib/graphics/shaders/vertex/object-shader.glsl.js +11 -0
- package/dist/lib/graphics/shaders/vertex/standard.glsl.js +9 -0
- package/dist/lib/graphics/zylem-scene.d.ts +2 -2
- package/dist/lib/graphics/zylem-scene.js +89 -0
- package/dist/lib/input/gamepad-provider.js +58 -0
- package/dist/lib/input/input-manager.js +70 -0
- package/dist/lib/input/keyboard-provider.js +120 -0
- package/dist/lib/stage/debug-entity-cursor.js +53 -0
- package/dist/lib/stage/entity-spawner.js +27 -0
- package/dist/lib/stage/stage-debug-delegate.js +100 -0
- package/dist/lib/stage/stage-state.d.ts +5 -1
- package/dist/lib/stage/stage-state.js +36 -0
- package/dist/lib/stage/stage.d.ts +0 -1
- package/dist/lib/stage/stage.js +58 -0
- package/dist/lib/stage/zylem-stage.d.ts +1 -3
- package/dist/lib/stage/zylem-stage.js +279 -0
- package/dist/lib/systems/transformable.system.js +43 -0
- package/dist/main.d.ts +5 -15
- package/dist/main.js +54 -35581
- package/dist/stage.d.ts +3 -0
- package/dist/stage.js +6 -0
- package/package.json +51 -17
- package/dist/assets/bounce.wav +0 -0
- package/dist/assets/coin-sound.mp3 +0 -0
- package/dist/lib/actions/behaviors/index.d.ts +0 -1
- package/dist/lib/collision/physics.d.ts +0 -4
- package/dist/lib/entities/object.d.ts +0 -1
- package/dist/lib/interfaces/game.d.ts +0 -19
- package/dist/main.cjs +0 -3980
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { proxy as s } from "valtio/vanilla";
|
|
2
|
+
import { printToConsole as t } from "./console/console-state.js";
|
|
3
|
+
const n = {
|
|
4
|
+
NONE: "NONE",
|
|
5
|
+
SELECT: "SELECT",
|
|
6
|
+
DELETE: "DELETE"
|
|
7
|
+
}, o = s({
|
|
8
|
+
on: !1,
|
|
9
|
+
paused: !1,
|
|
10
|
+
configuration: {
|
|
11
|
+
showCollisionBounds: !1,
|
|
12
|
+
showModelBounds: !1,
|
|
13
|
+
showSpriteBounds: !1
|
|
14
|
+
},
|
|
15
|
+
hovered: null,
|
|
16
|
+
selected: [],
|
|
17
|
+
tool: n.NONE
|
|
18
|
+
}), r = (e = !1) => {
|
|
19
|
+
o.on = e;
|
|
20
|
+
}, u = (e) => {
|
|
21
|
+
o.selected.push(e);
|
|
22
|
+
}, E = () => o.tool, a = (e) => {
|
|
23
|
+
o.hovered = e;
|
|
24
|
+
}, c = () => {
|
|
25
|
+
o.hovered = null;
|
|
26
|
+
}, i = () => o.hovered, f = (e) => {
|
|
27
|
+
o.paused = e, t(e ? "Paused" : "Resumed");
|
|
28
|
+
}, p = () => o.paused;
|
|
29
|
+
export {
|
|
30
|
+
n as DebugTools,
|
|
31
|
+
o as debugState,
|
|
32
|
+
E as getDebugTool,
|
|
33
|
+
i as getHoveredEntity,
|
|
34
|
+
p as isPaused,
|
|
35
|
+
c as resetHoveredEntity,
|
|
36
|
+
r as setDebugFlag,
|
|
37
|
+
a as setHoveredEntity,
|
|
38
|
+
f as setPaused,
|
|
39
|
+
u as setSelectedEntity
|
|
40
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { ColliderDesc as l, ActiveCollisionTypes as m } from "@dimforge/rapier3d-compat";
|
|
2
|
+
import { Vector3 as r, Group as d, SkinnedMesh as u } from "three";
|
|
3
|
+
import { GameEntity as p } from "./entity.js";
|
|
4
|
+
import { createEntity as g } from "./create.js";
|
|
5
|
+
import { EntityAssetLoader as y } from "../core/entity-asset-loader.js";
|
|
6
|
+
import { AnimationDelegate as f } from "./delegates/animation.js";
|
|
7
|
+
import { EntityCollisionBuilder as b, EntityBuilder as _ } from "./builder.js";
|
|
8
|
+
const c = {
|
|
9
|
+
position: { x: 0, y: 0, z: 0 },
|
|
10
|
+
collision: {
|
|
11
|
+
static: !1,
|
|
12
|
+
size: new r(0.5, 0.5, 0.5),
|
|
13
|
+
position: new r(0, 0, 0)
|
|
14
|
+
},
|
|
15
|
+
material: {
|
|
16
|
+
shader: "standard"
|
|
17
|
+
},
|
|
18
|
+
animations: [],
|
|
19
|
+
models: []
|
|
20
|
+
};
|
|
21
|
+
class j extends b {
|
|
22
|
+
height = 1;
|
|
23
|
+
objectModel = null;
|
|
24
|
+
constructor(t) {
|
|
25
|
+
super(), this.objectModel = t.objectModel;
|
|
26
|
+
}
|
|
27
|
+
createColliderFromObjectModel(t) {
|
|
28
|
+
if (!t)
|
|
29
|
+
return l.capsule(1, 1);
|
|
30
|
+
const e = t.children.find((s) => s instanceof u).geometry;
|
|
31
|
+
if (e && (e.computeBoundingBox(), e.boundingBox)) {
|
|
32
|
+
const s = e.boundingBox.max.y, h = e.boundingBox.min.y;
|
|
33
|
+
this.height = s - h;
|
|
34
|
+
}
|
|
35
|
+
this.height = 1;
|
|
36
|
+
let o = l.capsule(this.height / 2, 1);
|
|
37
|
+
return o.setSensor(!1), o.setTranslation(0, this.height + 0.5, 0), o.activeCollisionTypes = m.DEFAULT, o;
|
|
38
|
+
}
|
|
39
|
+
collider(t) {
|
|
40
|
+
return this.createColliderFromObjectModel(this.objectModel);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
class C extends _ {
|
|
44
|
+
createEntity(t) {
|
|
45
|
+
return new a(t);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const D = Symbol("Actor");
|
|
49
|
+
class a extends p {
|
|
50
|
+
static type = D;
|
|
51
|
+
_object = null;
|
|
52
|
+
_animationDelegate = null;
|
|
53
|
+
_modelFileNames = [];
|
|
54
|
+
_assetLoader = new y();
|
|
55
|
+
controlledRotation = !1;
|
|
56
|
+
constructor(t) {
|
|
57
|
+
super(), this.options = { ...c, ...t }, this.lifeCycleDelegate = {
|
|
58
|
+
update: [this.actorUpdate.bind(this)]
|
|
59
|
+
}, this.controlledRotation = !0;
|
|
60
|
+
}
|
|
61
|
+
async load() {
|
|
62
|
+
this._modelFileNames = this.options.models || [], await this.loadModels(), this._object && (this._animationDelegate = new f(this._object), await this._animationDelegate.loadAnimations(this.options.animations || []));
|
|
63
|
+
}
|
|
64
|
+
async data() {
|
|
65
|
+
return {
|
|
66
|
+
animations: this._animationDelegate?.animations,
|
|
67
|
+
objectModel: this._object
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async actorUpdate(t) {
|
|
71
|
+
this._animationDelegate?.update(t.delta);
|
|
72
|
+
}
|
|
73
|
+
async loadModels() {
|
|
74
|
+
if (this._modelFileNames.length === 0)
|
|
75
|
+
return;
|
|
76
|
+
const t = this._modelFileNames.map((e) => this._assetLoader.loadFile(e)), i = await Promise.all(t);
|
|
77
|
+
i[0]?.object && (this._object = i[0].object), this._object && (this.group = new d(), this.group.attach(this._object), this.group.scale.set(this.options.scale?.x || 1, this.options.scale?.y || 1, this.options.scale?.z || 1));
|
|
78
|
+
}
|
|
79
|
+
playAnimation(t) {
|
|
80
|
+
this._animationDelegate?.playAnimation(t);
|
|
81
|
+
}
|
|
82
|
+
get object() {
|
|
83
|
+
return this._object;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Provide custom debug information for the actor
|
|
87
|
+
* This will be merged with the default debug information
|
|
88
|
+
*/
|
|
89
|
+
getDebugInfo() {
|
|
90
|
+
const t = {
|
|
91
|
+
type: "Actor",
|
|
92
|
+
models: this._modelFileNames.length > 0 ? this._modelFileNames : "none",
|
|
93
|
+
modelLoaded: !!this._object,
|
|
94
|
+
scale: this.options.scale ? `${this.options.scale.x}, ${this.options.scale.y}, ${this.options.scale.z}` : "1, 1, 1"
|
|
95
|
+
};
|
|
96
|
+
if (this._animationDelegate && (t.currentAnimation = this._animationDelegate.currentAnimationKey || "none", t.animationsCount = this.options.animations?.length || 0), this._object) {
|
|
97
|
+
let i = 0, e = 0;
|
|
98
|
+
this._object.traverse((o) => {
|
|
99
|
+
if (o.isMesh) {
|
|
100
|
+
i++;
|
|
101
|
+
const s = o.geometry;
|
|
102
|
+
s && s.attributes.position && (e += s.attributes.position.count);
|
|
103
|
+
}
|
|
104
|
+
}), t.meshCount = i, t.vertexCount = e;
|
|
105
|
+
}
|
|
106
|
+
return t;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function T(...n) {
|
|
110
|
+
return await g({
|
|
111
|
+
args: n,
|
|
112
|
+
defaultConfig: c,
|
|
113
|
+
EntityClass: a,
|
|
114
|
+
BuilderClass: C,
|
|
115
|
+
CollisionBuilderClass: j,
|
|
116
|
+
entityType: a.type
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
export {
|
|
120
|
+
D as ACTOR_TYPE,
|
|
121
|
+
C as ActorBuilder,
|
|
122
|
+
j as ActorCollisionBuilder,
|
|
123
|
+
a as ZylemActor,
|
|
124
|
+
T as actor
|
|
125
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ColliderDesc as a } from "@dimforge/rapier3d-compat";
|
|
2
|
+
import { Color as d, Vector3 as n, BoxGeometry as u } from "three";
|
|
3
|
+
import { GameEntity as y } from "./entity.js";
|
|
4
|
+
import { EntityCollisionBuilder as f, EntityBuilder as x, EntityMeshBuilder as m } from "./builder.js";
|
|
5
|
+
import { DebugDelegate as p } from "./delegates/debug.js";
|
|
6
|
+
import { createEntity as z } from "./create.js";
|
|
7
|
+
const l = {
|
|
8
|
+
size: new n(1, 1, 1),
|
|
9
|
+
position: new n(0, 0, 0),
|
|
10
|
+
collision: {
|
|
11
|
+
static: !1
|
|
12
|
+
},
|
|
13
|
+
material: {
|
|
14
|
+
color: new d("#ffffff"),
|
|
15
|
+
shader: "standard"
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
class B extends f {
|
|
19
|
+
collider(t) {
|
|
20
|
+
const e = t.size || new n(1, 1, 1), s = { x: e.x / 2, y: e.y / 2, z: e.z / 2 };
|
|
21
|
+
return a.cuboid(s.x, s.y, s.z);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
class b extends m {
|
|
25
|
+
build(t) {
|
|
26
|
+
const e = t.size ?? new n(1, 1, 1);
|
|
27
|
+
return new u(e.x, e.y, e.z);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
class C extends x {
|
|
31
|
+
createEntity(t) {
|
|
32
|
+
return new i(t);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const h = Symbol("Box");
|
|
36
|
+
class i extends y {
|
|
37
|
+
static type = h;
|
|
38
|
+
constructor(t) {
|
|
39
|
+
super(), this.options = { ...l, ...t };
|
|
40
|
+
}
|
|
41
|
+
buildInfo() {
|
|
42
|
+
const e = new p(this).buildDebugInfo(), { x: s, y: r, z: c } = this.options.size ?? { x: 1, y: 1, z: 1 };
|
|
43
|
+
return {
|
|
44
|
+
...e,
|
|
45
|
+
type: String(i.type),
|
|
46
|
+
size: `${s}, ${r}, ${c}`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function $(...o) {
|
|
51
|
+
return z({
|
|
52
|
+
args: o,
|
|
53
|
+
defaultConfig: l,
|
|
54
|
+
EntityClass: i,
|
|
55
|
+
BuilderClass: C,
|
|
56
|
+
MeshBuilderClass: b,
|
|
57
|
+
CollisionBuilderClass: B,
|
|
58
|
+
entityType: i.type
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
h as BOX_TYPE,
|
|
63
|
+
C as BoxBuilder,
|
|
64
|
+
B as BoxCollisionBuilder,
|
|
65
|
+
b as BoxMeshBuilder,
|
|
66
|
+
i as ZylemBox,
|
|
67
|
+
$ as box
|
|
68
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Mesh as l, Color as n, BufferGeometry as u } from "three";
|
|
2
|
+
import { CollisionBuilder as h } from "../collision/collision-builder.js";
|
|
3
|
+
import { MeshBuilder as m } from "../graphics/mesh.js";
|
|
4
|
+
import { MaterialBuilder as d } from "../graphics/material.js";
|
|
5
|
+
class y extends h {
|
|
6
|
+
}
|
|
7
|
+
class b extends m {
|
|
8
|
+
build(i) {
|
|
9
|
+
return new u();
|
|
10
|
+
}
|
|
11
|
+
postBuild() {
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
class M {
|
|
15
|
+
meshBuilder;
|
|
16
|
+
collisionBuilder;
|
|
17
|
+
materialBuilder;
|
|
18
|
+
options;
|
|
19
|
+
entity;
|
|
20
|
+
constructor(i, s, t, e) {
|
|
21
|
+
this.options = i, this.entity = s, this.meshBuilder = t, this.collisionBuilder = e, this.materialBuilder = new d();
|
|
22
|
+
const o = {
|
|
23
|
+
meshBuilder: this.meshBuilder,
|
|
24
|
+
collisionBuilder: this.collisionBuilder,
|
|
25
|
+
materialBuilder: this.materialBuilder
|
|
26
|
+
};
|
|
27
|
+
this.options._builders = o;
|
|
28
|
+
}
|
|
29
|
+
withPosition(i) {
|
|
30
|
+
return this.options.position = i, this;
|
|
31
|
+
}
|
|
32
|
+
async withMaterial(i, s) {
|
|
33
|
+
return this.materialBuilder && await this.materialBuilder.build(i, s), this;
|
|
34
|
+
}
|
|
35
|
+
applyMaterialToGroup(i, s) {
|
|
36
|
+
i.traverse((t) => {
|
|
37
|
+
t instanceof l && t.type === "SkinnedMesh" && s[0] && !t.material.map && (t.material = s[0]), t.castShadow = !0, t.receiveShadow = !0;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async build() {
|
|
41
|
+
const i = this.entity;
|
|
42
|
+
if (this.materialBuilder && (i.materials = this.materialBuilder.materials), this.meshBuilder && i.materials) {
|
|
43
|
+
const s = this.meshBuilder.build(this.options);
|
|
44
|
+
i.mesh = this.meshBuilder._build(this.options, s, i.materials), this.meshBuilder.postBuild();
|
|
45
|
+
}
|
|
46
|
+
if (i.group && i.materials && this.applyMaterialToGroup(i.group, i.materials), this.collisionBuilder) {
|
|
47
|
+
this.collisionBuilder.withCollision(this.options?.collision || {});
|
|
48
|
+
const [s, t] = this.collisionBuilder.build(this.options);
|
|
49
|
+
i.bodyDesc = s, i.colliderDesc = t;
|
|
50
|
+
const { x: e, y: o, z: a } = this.options.position || { x: 0, y: 0, z: 0 };
|
|
51
|
+
i.bodyDesc.setTranslation(e, o, a);
|
|
52
|
+
}
|
|
53
|
+
if (this.options.collisionType && (i.collisionType = this.options.collisionType), this.options.color instanceof n) {
|
|
54
|
+
const s = (t) => {
|
|
55
|
+
const e = t;
|
|
56
|
+
e && e.color && e.color.set && e.color.set(this.options.color);
|
|
57
|
+
};
|
|
58
|
+
if (i.materials?.length)
|
|
59
|
+
for (const t of i.materials)
|
|
60
|
+
s(t);
|
|
61
|
+
if (i.mesh && i.mesh.material) {
|
|
62
|
+
const t = i.mesh.material;
|
|
63
|
+
Array.isArray(t) ? t.forEach(s) : s(t);
|
|
64
|
+
}
|
|
65
|
+
i.group && i.group.traverse((t) => {
|
|
66
|
+
if (t instanceof l && t.material) {
|
|
67
|
+
const e = t.material;
|
|
68
|
+
Array.isArray(e) ? e.forEach(s) : s(e);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return i;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
M as EntityBuilder,
|
|
77
|
+
y as EntityCollisionBuilder,
|
|
78
|
+
b as EntityMeshBuilder
|
|
79
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BaseNode as s } from "../core/base-node.js";
|
|
2
|
+
import { isLoadable as p, EntityLoader as C } from "./delegates/loader.js";
|
|
3
|
+
async function E(w) {
|
|
4
|
+
const { args: n, defaultConfig: l, EntityClass: g, BuilderClass: y, entityType: c, MeshBuilderClass: f, CollisionBuilderClass: d } = w;
|
|
5
|
+
let e = null, r;
|
|
6
|
+
const u = n.findIndex((i) => !(i instanceof s));
|
|
7
|
+
u !== -1 && (r = n.splice(u, 1).find((t) => !(t instanceof s)));
|
|
8
|
+
const m = r ? { ...l, ...r } : l;
|
|
9
|
+
n.push(m);
|
|
10
|
+
for (const i of n) {
|
|
11
|
+
if (i instanceof s)
|
|
12
|
+
continue;
|
|
13
|
+
let t = null;
|
|
14
|
+
const a = new g(i);
|
|
15
|
+
try {
|
|
16
|
+
if (p(a)) {
|
|
17
|
+
const o = new C(a);
|
|
18
|
+
await o.load(), t = await o.data();
|
|
19
|
+
}
|
|
20
|
+
} catch (o) {
|
|
21
|
+
console.error("Error creating entity with loader:", o);
|
|
22
|
+
}
|
|
23
|
+
e = new y(i, a, f ? new f(t) : null, d ? new d(t) : null), i.material && await e.withMaterial(i.material, c);
|
|
24
|
+
}
|
|
25
|
+
if (!e)
|
|
26
|
+
throw new Error(`missing options for ${String(c)}, builder is not initialized.`);
|
|
27
|
+
return await e.build();
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
E as createEntity
|
|
31
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AnimationMixer as u, LoopOnce as c, LoopRepeat as h } from "three";
|
|
2
|
+
import { EntityAssetLoader as _ } from "../../core/entity-asset-loader.js";
|
|
3
|
+
class d {
|
|
4
|
+
target;
|
|
5
|
+
_mixer = null;
|
|
6
|
+
_actions = {};
|
|
7
|
+
_animations = [];
|
|
8
|
+
_currentAction = null;
|
|
9
|
+
_pauseAtPercentage = 0;
|
|
10
|
+
_isPaused = !1;
|
|
11
|
+
_queuedKey = null;
|
|
12
|
+
_fadeDuration = 0.5;
|
|
13
|
+
_currentKey = "";
|
|
14
|
+
_assetLoader = new _();
|
|
15
|
+
constructor(e) {
|
|
16
|
+
this.target = e;
|
|
17
|
+
}
|
|
18
|
+
async loadAnimations(e) {
|
|
19
|
+
if (!e.length)
|
|
20
|
+
return;
|
|
21
|
+
const i = await Promise.all(e.map((t) => this._assetLoader.loadFile(t.path)));
|
|
22
|
+
this._animations = i.filter((t) => !!t.animation).map((t) => t.animation), this._animations.length && (this._mixer = new u(this.target), this._animations.forEach((t, n) => {
|
|
23
|
+
const a = e[n].key || n.toString();
|
|
24
|
+
this._actions[a] = this._mixer.clipAction(t);
|
|
25
|
+
}), this.playAnimation({ key: Object.keys(this._actions)[0] }));
|
|
26
|
+
}
|
|
27
|
+
update(e) {
|
|
28
|
+
if (!this._mixer || !this._currentAction)
|
|
29
|
+
return;
|
|
30
|
+
this._mixer.update(e);
|
|
31
|
+
const i = this._currentAction.getClip().duration * (this._pauseAtPercentage / 100);
|
|
32
|
+
if (!this._isPaused && this._pauseAtPercentage > 0 && this._currentAction.time >= i && (this._currentAction.time = i, this._currentAction.paused = !0, this._isPaused = !0, this._queuedKey !== null)) {
|
|
33
|
+
const t = this._actions[this._queuedKey];
|
|
34
|
+
t.reset().play(), this._currentAction.crossFadeTo(t, this._fadeDuration, !1), this._currentAction = t, this._currentKey = this._queuedKey, this._queuedKey = null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
playAnimation(e) {
|
|
38
|
+
if (!this._mixer)
|
|
39
|
+
return;
|
|
40
|
+
const { key: i, pauseAtPercentage: t = 0, pauseAtEnd: n = !1, fadeToKey: a, fadeDuration: o = 0.5 } = e;
|
|
41
|
+
if (i === this._currentKey)
|
|
42
|
+
return;
|
|
43
|
+
this._queuedKey = a || null, this._fadeDuration = o, this._pauseAtPercentage = n ? 100 : t, this._isPaused = !1;
|
|
44
|
+
const r = this._currentAction;
|
|
45
|
+
r && r.stop();
|
|
46
|
+
const s = this._actions[i];
|
|
47
|
+
s && (this._pauseAtPercentage > 0 ? (s.setLoop(c, 1 / 0), s.clampWhenFinished = !0) : (s.setLoop(h, 1 / 0), s.clampWhenFinished = !1), r && r.crossFadeTo(s, o, !1), s.reset().play(), this._currentAction = s, this._currentKey = i);
|
|
48
|
+
}
|
|
49
|
+
get currentAnimationKey() {
|
|
50
|
+
return this._currentKey;
|
|
51
|
+
}
|
|
52
|
+
get animations() {
|
|
53
|
+
return this._animations;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
d as AnimationDelegate
|
|
58
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { MeshStandardMaterial as c, MeshBasicMaterial as u, MeshPhongMaterial as f } from "three";
|
|
2
|
+
function g(o) {
|
|
3
|
+
return o && typeof o.getDebugInfo == "function";
|
|
4
|
+
}
|
|
5
|
+
class d {
|
|
6
|
+
entity;
|
|
7
|
+
constructor(t) {
|
|
8
|
+
this.entity = t;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get formatted position string
|
|
12
|
+
*/
|
|
13
|
+
getPositionString() {
|
|
14
|
+
if (this.entity.mesh) {
|
|
15
|
+
const { x: n, y: s, z: r } = this.entity.mesh.position;
|
|
16
|
+
return `${n.toFixed(2)}, ${s.toFixed(2)}, ${r.toFixed(2)}`;
|
|
17
|
+
}
|
|
18
|
+
const { x: t, y: i, z: e } = this.entity.options.position || { x: 0, y: 0, z: 0 };
|
|
19
|
+
return `${t.toFixed(2)}, ${i.toFixed(2)}, ${e.toFixed(2)}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get formatted rotation string (in degrees)
|
|
23
|
+
*/
|
|
24
|
+
getRotationString() {
|
|
25
|
+
if (this.entity.mesh) {
|
|
26
|
+
const { x: s, y: r, z: y } = this.entity.mesh.rotation, a = (h) => (h * 180 / Math.PI).toFixed(1);
|
|
27
|
+
return `${a(s)}°, ${a(r)}°, ${a(y)}°`;
|
|
28
|
+
}
|
|
29
|
+
const { x: t, y: i, z: e } = this.entity.options.rotation || { x: 0, y: 0, z: 0 }, n = (s) => (s * 180 / Math.PI).toFixed(1);
|
|
30
|
+
return `${n(t)}°, ${n(i)}°, ${n(e)}°`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get material information
|
|
34
|
+
*/
|
|
35
|
+
getMaterialInfo() {
|
|
36
|
+
if (!this.entity.mesh || !this.entity.mesh.material)
|
|
37
|
+
return { type: "none" };
|
|
38
|
+
const t = Array.isArray(this.entity.mesh.material) ? this.entity.mesh.material[0] : this.entity.mesh.material, i = {
|
|
39
|
+
type: t.type
|
|
40
|
+
};
|
|
41
|
+
return (t instanceof c || t instanceof u || t instanceof f) && (i.color = `#${t.color.getHexString()}`, i.opacity = t.opacity, i.transparent = t.transparent), "roughness" in t && (i.roughness = t.roughness), "metalness" in t && (i.metalness = t.metalness), i;
|
|
42
|
+
}
|
|
43
|
+
getPhysicsInfo() {
|
|
44
|
+
if (!this.entity.body)
|
|
45
|
+
return null;
|
|
46
|
+
const t = {
|
|
47
|
+
type: this.entity.body.bodyType(),
|
|
48
|
+
mass: this.entity.body.mass(),
|
|
49
|
+
isEnabled: this.entity.body.isEnabled(),
|
|
50
|
+
isSleeping: this.entity.body.isSleeping()
|
|
51
|
+
}, i = this.entity.body.linvel();
|
|
52
|
+
return t.velocity = `${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z.toFixed(2)}`, t;
|
|
53
|
+
}
|
|
54
|
+
buildDebugInfo() {
|
|
55
|
+
const t = {
|
|
56
|
+
name: this.entity.name || this.entity.uuid,
|
|
57
|
+
uuid: this.entity.uuid,
|
|
58
|
+
position: this.getPositionString(),
|
|
59
|
+
rotation: this.getRotationString(),
|
|
60
|
+
material: this.getMaterialInfo()
|
|
61
|
+
}, i = this.getPhysicsInfo();
|
|
62
|
+
if (i && (t.physics = i), this.entity.behaviors.length > 0 && (t.behaviors = this.entity.behaviors.map((e) => e.constructor.name)), g(this.entity)) {
|
|
63
|
+
const e = this.entity.getDebugInfo();
|
|
64
|
+
return { ...t, ...e };
|
|
65
|
+
}
|
|
66
|
+
return t;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
d as DebugDelegate,
|
|
71
|
+
g as hasDebugInfo
|
|
72
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function n(e) {
|
|
2
|
+
return typeof e?.load == "function" && typeof e?.data == "function";
|
|
3
|
+
}
|
|
4
|
+
class a {
|
|
5
|
+
entityReference;
|
|
6
|
+
constructor(t) {
|
|
7
|
+
this.entityReference = t;
|
|
8
|
+
}
|
|
9
|
+
async load() {
|
|
10
|
+
this.entityReference.load && await this.entityReference.load();
|
|
11
|
+
}
|
|
12
|
+
async data() {
|
|
13
|
+
return this.entityReference.data ? this.entityReference.data() : null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
a as EntityLoader,
|
|
18
|
+
n as isLoadable
|
|
19
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getGlobalState as n } from "../game/game-state.js";
|
|
2
|
+
function r(o, t, e) {
|
|
3
|
+
e({
|
|
4
|
+
me: o,
|
|
5
|
+
globals: t
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
function d(o, t) {
|
|
9
|
+
const e = t ?? n();
|
|
10
|
+
r(o, e, o.nodeDestroy.bind(o));
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
d as destroy,
|
|
14
|
+
r as destroyEntity
|
|
15
|
+
};
|
|
@@ -2,7 +2,6 @@ import { Mesh, Material, ShaderMaterial, Group, Color } from "three";
|
|
|
2
2
|
import { Collider, ColliderDesc, RigidBody, RigidBodyDesc } from "@dimforge/rapier3d-compat";
|
|
3
3
|
import { Vec3 } from "../core/vector";
|
|
4
4
|
import { MaterialBuilder, MaterialOptions } from "../graphics/material";
|
|
5
|
-
import { PhysicsOptions } from "../collision/physics";
|
|
6
5
|
import { CollisionOptions } from "../collision/collision";
|
|
7
6
|
import { BaseNode } from "../core/base-node";
|
|
8
7
|
import { DestroyContext, SetupContext, UpdateContext } from "../core/base-node-life-cycle";
|
|
@@ -39,7 +38,6 @@ export type GameEntityOptions = {
|
|
|
39
38
|
position?: Vec3;
|
|
40
39
|
batched?: boolean;
|
|
41
40
|
collision?: Partial<CollisionOptions>;
|
|
42
|
-
physics?: Partial<PhysicsOptions>;
|
|
43
41
|
material?: Partial<MaterialOptions>;
|
|
44
42
|
custom?: {
|
|
45
43
|
[key: string]: any;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { ShaderMaterial as s } from "three";
|
|
2
|
+
import { position as o, scale as a, rotation as n } from "../systems/transformable.system.js";
|
|
3
|
+
import { BaseNode as c } from "../core/base-node.js";
|
|
4
|
+
class d extends c {
|
|
5
|
+
group;
|
|
6
|
+
mesh;
|
|
7
|
+
materials;
|
|
8
|
+
bodyDesc = null;
|
|
9
|
+
body = null;
|
|
10
|
+
colliderDesc;
|
|
11
|
+
collider;
|
|
12
|
+
custom = {};
|
|
13
|
+
debugInfo = {};
|
|
14
|
+
debugMaterial;
|
|
15
|
+
lifeCycleDelegate = {
|
|
16
|
+
setup: [],
|
|
17
|
+
update: [],
|
|
18
|
+
destroy: []
|
|
19
|
+
};
|
|
20
|
+
collisionDelegate = {
|
|
21
|
+
collision: []
|
|
22
|
+
};
|
|
23
|
+
collisionType;
|
|
24
|
+
behaviorCallbackMap = {
|
|
25
|
+
setup: [],
|
|
26
|
+
update: [],
|
|
27
|
+
destroy: [],
|
|
28
|
+
collision: []
|
|
29
|
+
};
|
|
30
|
+
constructor() {
|
|
31
|
+
super();
|
|
32
|
+
}
|
|
33
|
+
create() {
|
|
34
|
+
const { position: e } = this.options, { x: t, y: i, z: l } = e || { x: 0, y: 0, z: 0 };
|
|
35
|
+
return this.behaviors = [
|
|
36
|
+
{ component: o, values: { x: t, y: i, z: l } },
|
|
37
|
+
{ component: a, values: { x: 0, y: 0, z: 0 } },
|
|
38
|
+
{ component: n, values: { x: 0, y: 0, z: 0, w: 0 } }
|
|
39
|
+
], this.name = this.options.name || "", this;
|
|
40
|
+
}
|
|
41
|
+
onSetup(...e) {
|
|
42
|
+
const t = [...this.lifeCycleDelegate.setup ?? [], ...e];
|
|
43
|
+
return this.lifeCycleDelegate = {
|
|
44
|
+
...this.lifeCycleDelegate,
|
|
45
|
+
setup: t
|
|
46
|
+
}, this;
|
|
47
|
+
}
|
|
48
|
+
onUpdate(...e) {
|
|
49
|
+
const t = [...this.lifeCycleDelegate.update ?? [], ...e];
|
|
50
|
+
return this.lifeCycleDelegate = {
|
|
51
|
+
...this.lifeCycleDelegate,
|
|
52
|
+
update: t
|
|
53
|
+
}, this;
|
|
54
|
+
}
|
|
55
|
+
onDestroy(...e) {
|
|
56
|
+
return this.lifeCycleDelegate = {
|
|
57
|
+
...this.lifeCycleDelegate,
|
|
58
|
+
destroy: e.length > 0 ? e : void 0
|
|
59
|
+
}, this;
|
|
60
|
+
}
|
|
61
|
+
onCollision(...e) {
|
|
62
|
+
return this.collisionDelegate = {
|
|
63
|
+
collision: e.length > 0 ? e : void 0
|
|
64
|
+
}, this;
|
|
65
|
+
}
|
|
66
|
+
_setup(e) {
|
|
67
|
+
this.behaviorCallbackMap.setup.forEach((t) => {
|
|
68
|
+
t({ ...e, me: this });
|
|
69
|
+
}), this.lifeCycleDelegate.setup?.length && this.lifeCycleDelegate.setup.forEach((i) => {
|
|
70
|
+
i({ ...e, me: this });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
_update(e) {
|
|
74
|
+
this.updateMaterials(e), this.lifeCycleDelegate.update?.length && this.lifeCycleDelegate.update.forEach((i) => {
|
|
75
|
+
i({ ...e, me: this });
|
|
76
|
+
}), this.behaviorCallbackMap.update.forEach((t) => {
|
|
77
|
+
t({ ...e, me: this });
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
_destroy(e) {
|
|
81
|
+
this.lifeCycleDelegate.destroy?.length && this.lifeCycleDelegate.destroy.forEach((i) => {
|
|
82
|
+
i({ ...e, me: this });
|
|
83
|
+
}), this.behaviorCallbackMap.destroy.forEach((t) => {
|
|
84
|
+
t({ ...e, me: this });
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
_collision(e, t) {
|
|
88
|
+
this.collisionDelegate.collision?.length && this.collisionDelegate.collision.forEach((l) => {
|
|
89
|
+
l({ entity: this, other: e, globals: t });
|
|
90
|
+
}), this.behaviorCallbackMap.collision.forEach((i) => {
|
|
91
|
+
i({ entity: this, other: e, globals: t });
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
addBehavior(e) {
|
|
95
|
+
const t = e.handler;
|
|
96
|
+
return t && this.behaviorCallbackMap[e.type].push(t), this;
|
|
97
|
+
}
|
|
98
|
+
addBehaviors(e) {
|
|
99
|
+
return e.forEach((t) => {
|
|
100
|
+
const i = t.handler;
|
|
101
|
+
i && this.behaviorCallbackMap[t.type].push(i);
|
|
102
|
+
}), this;
|
|
103
|
+
}
|
|
104
|
+
updateMaterials(e) {
|
|
105
|
+
if (this.materials?.length)
|
|
106
|
+
for (const t of this.materials)
|
|
107
|
+
t instanceof s && t.uniforms && t.uniforms.iTime && (t.uniforms.iTime.value += e.delta);
|
|
108
|
+
}
|
|
109
|
+
buildInfo() {
|
|
110
|
+
const e = {};
|
|
111
|
+
return e.name = this.name, e.uuid = this.uuid, e.eid = this.eid.toString(), e;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export {
|
|
115
|
+
d as GameEntity
|
|
116
|
+
};
|