emeraldengine 2.2.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2198 -968
- package/dist/types/index.d.ts +75 -32
- package/dist/types/src/Animator.d.ts +50 -0
- package/dist/types/{BitmapText.d.ts → src/BitmapText.d.ts} +19 -21
- package/dist/types/src/Camera.d.ts +122 -0
- package/dist/types/src/CameraController.d.ts +107 -0
- package/dist/types/src/CanvasText.d.ts +91 -0
- package/dist/types/src/CollisionLayers.d.ts +58 -0
- package/dist/types/{Color.d.ts → src/Color.d.ts} +6 -6
- package/dist/types/src/Coroutine.d.ts +111 -0
- package/dist/types/src/DebugOverlay.d.ts +86 -0
- package/dist/types/src/Drawable.d.ts +271 -0
- package/dist/types/src/Easing.d.ts +22 -0
- package/dist/types/src/Emerald.d.ts +420 -0
- package/dist/types/src/EmeraldDB.d.ts +159 -0
- package/dist/types/{FPSCounter.d.ts → src/FPSCounter.d.ts} +1 -3
- package/dist/types/src/GLUtils.d.ts +4 -0
- package/dist/types/{Instance.d.ts → src/Instance.d.ts} +37 -15
- package/dist/types/{InstancedTexture.d.ts → src/InstancedTexture.d.ts} +75 -23
- package/dist/types/src/Interpolator.d.ts +66 -0
- package/dist/types/src/Material.d.ts +87 -0
- package/dist/types/src/MathUtils.d.ts +81 -0
- package/dist/types/src/ParticleEmitter.d.ts +131 -0
- package/dist/types/src/Physics.d.ts +337 -0
- package/dist/types/src/Pool.d.ts +53 -0
- package/dist/types/src/PostEffects.d.ts +68 -0
- package/dist/types/src/PostProcessor.d.ts +124 -0
- package/dist/types/src/RenderTarget.d.ts +56 -0
- package/dist/types/src/Scene.d.ts +62 -0
- package/dist/types/src/ScreenEffects.d.ts +111 -0
- package/dist/types/src/Serializer.d.ts +86 -0
- package/dist/types/src/Shaders.d.ts +2 -0
- package/dist/types/{Shapes.d.ts → src/Shapes.d.ts} +4 -6
- package/dist/types/src/SpatialGrid.d.ts +50 -0
- package/dist/types/src/SpriteBatch.d.ts +89 -0
- package/dist/types/src/StateMachine.d.ts +59 -0
- package/dist/types/src/Storage.d.ts +89 -0
- package/dist/types/{Texture.d.ts → src/Texture.d.ts} +3 -4
- package/dist/types/src/TextureAtlas.d.ts +55 -0
- package/dist/types/src/Tilemap.d.ts +91 -0
- package/dist/types/src/Time.d.ts +53 -0
- package/dist/types/src/Timer.d.ts +54 -0
- package/dist/types/src/Transform.d.ts +94 -0
- package/dist/types/src/Tween.d.ts +81 -0
- package/dist/types/src/UI.d.ts +121 -0
- package/dist/types/src/components/Behaviour.d.ts +71 -0
- package/dist/types/{components → src/components}/BoxCollider.d.ts +14 -14
- package/dist/types/src/components/BoxColliderDebug.d.ts +15 -0
- package/dist/types/{components → src/components}/CircleCollider.d.ts +14 -12
- package/dist/types/src/components/CircleColliderDebug.d.ts +15 -0
- package/dist/types/src/components/Collider.d.ts +102 -0
- package/dist/types/src/components/GameObject.d.ts +135 -0
- package/dist/types/src/components/PolygonCollider.d.ts +33 -0
- package/dist/types/src/components/RigidBody.d.ts +456 -0
- package/dist/types/src/importers/Aseprite.d.ts +79 -0
- package/dist/types/src/importers/ForgeLevel.d.ts +97 -0
- package/dist/types/src/importers/TiledMap.d.ts +62 -0
- package/dist/types/{lights → src/lights}/DirectionalLight.d.ts +7 -9
- package/dist/types/{lights → src/lights}/PointLight.d.ts +6 -9
- package/dist/types/src/managers/AssetManager.d.ts +116 -0
- package/dist/types/src/managers/AudioManager.d.ts +259 -0
- package/dist/types/{managers → src/managers}/CameraManager.d.ts +8 -8
- package/dist/types/{managers → src/managers}/EventManager.d.ts +46 -32
- package/dist/types/src/managers/GLManager.d.ts +84 -0
- package/dist/types/src/managers/GLState.d.ts +37 -0
- package/dist/types/src/managers/Gamepad.d.ts +102 -0
- package/dist/types/src/managers/IDManager.d.ts +31 -0
- package/dist/types/src/managers/InputManager.d.ts +381 -0
- package/dist/types/src/managers/NetworkManager.d.ts +93 -0
- package/dist/types/src/managers/RenderStats.d.ts +34 -0
- package/dist/types/src/managers/SceneManager.d.ts +44 -0
- package/dist/types/src/managers/ShaderManager.d.ts +55 -0
- package/dist/types/src/managers/TextureManager.d.ts +102 -0
- package/dist/types/src/particlesystem/Particle.d.ts +64 -0
- package/dist/types/{particlesystem → src/particlesystem}/ParticleSettings.d.ts +32 -24
- package/dist/types/{particlesystem → src/particlesystem}/Particles.d.ts +20 -12
- package/dist/types/src/physics/AABB.d.ts +92 -0
- package/dist/types/src/physics/Body.d.ts +435 -0
- package/dist/types/src/physics/BodyType.d.ts +6 -0
- package/dist/types/src/physics/BroadPhase.d.ts +210 -0
- package/dist/types/src/physics/Collision.d.ts +102 -0
- package/dist/types/src/physics/Contact.d.ts +206 -0
- package/dist/types/src/physics/ContactSolver.d.ts +108 -0
- package/dist/types/src/physics/Distance.d.ts +54 -0
- package/dist/types/src/physics/DistanceJoint.d.ts +90 -0
- package/dist/types/src/physics/Fixture.d.ts +221 -0
- package/dist/types/src/physics/Island.d.ts +52 -0
- package/dist/types/src/physics/Joint.d.ts +59 -0
- package/dist/types/src/physics/Math2D.d.ts +371 -0
- package/dist/types/src/physics/RevoluteJoint.d.ts +119 -0
- package/dist/types/src/physics/Settings.d.ts +22 -0
- package/dist/types/src/physics/Shapes.d.ts +207 -0
- package/dist/types/src/physics/TimeOfImpact.d.ts +22 -0
- package/dist/types/src/physics/World.d.ts +274 -0
- package/dist/types/src/physics/index.d.ts +34 -0
- package/index.js +78 -0
- package/package.json +73 -60
- package/src/Animator.js +95 -0
- package/src/BitmapText.js +6 -5
- package/src/Camera.js +183 -0
- package/src/CameraController.js +192 -0
- package/src/CanvasText.js +281 -0
- package/src/CollisionLayers.js +86 -0
- package/src/Color.js +26 -18
- package/src/Coroutine.js +259 -0
- package/src/DebugOverlay.js +246 -0
- package/src/Drawable.js +842 -582
- package/src/Easing.js +57 -0
- package/src/Emerald.js +1150 -459
- package/src/EmeraldDB.js +328 -0
- package/src/FPSCounter.js +43 -43
- package/src/GLUtils.js +60 -67
- package/src/Instance.js +41 -5
- package/src/InstancedTexture.js +308 -127
- package/src/Interpolator.js +124 -0
- package/src/Material.js +202 -0
- package/src/MathUtils.js +134 -0
- package/src/ParticleEmitter.js +284 -0
- package/src/Physics.js +431 -40
- package/src/Pool.js +85 -0
- package/src/PostEffects.js +296 -0
- package/src/PostProcessor.js +304 -0
- package/src/RenderTarget.js +134 -0
- package/src/Scene.js +115 -83
- package/src/ScreenEffects.js +266 -0
- package/src/Serializer.js +131 -0
- package/src/Shaders.js +150 -165
- package/src/Shapes.js +118 -129
- package/src/SpatialGrid.js +111 -0
- package/src/SpriteBatch.js +299 -0
- package/src/StateMachine.js +82 -0
- package/src/Storage.js +175 -47
- package/src/Texture.js +58 -67
- package/src/TextureAtlas.js +96 -0
- package/src/Tilemap.js +274 -0
- package/src/Time.js +51 -6
- package/src/Timer.js +99 -0
- package/src/Transform.js +100 -7
- package/src/Tween.js +160 -0
- package/src/UI.js +394 -0
- package/src/components/Behaviour.js +90 -0
- package/src/components/BoxCollider.js +29 -12
- package/src/components/BoxColliderDebug.js +3 -4
- package/src/components/CircleCollider.js +26 -12
- package/src/components/CircleColliderDebug.js +25 -24
- package/src/components/Collider.js +150 -34
- package/src/components/GameObject.js +130 -21
- package/src/components/PolygonCollider.js +55 -0
- package/src/components/RigidBody.js +556 -8
- package/src/importers/Aseprite.js +142 -0
- package/src/importers/ForgeLevel.js +581 -0
- package/src/importers/TiledMap.js +158 -0
- package/src/lights/DirectionalLight.js +6 -15
- package/src/lights/PointLight.js +4 -4
- package/src/managers/AssetManager.js +239 -0
- package/src/managers/AudioManager.js +565 -146
- package/src/managers/EventManager.js +488 -477
- package/src/managers/GLManager.js +57 -0
- package/src/managers/GLState.js +70 -0
- package/src/managers/Gamepad.js +126 -0
- package/src/managers/IDManager.js +24 -2
- package/src/managers/InputManager.js +905 -0
- package/src/managers/NetworkManager.js +178 -0
- package/src/managers/RenderStats.js +34 -0
- package/src/managers/SceneManager.js +30 -0
- package/src/managers/ShaderManager.js +0 -2
- package/src/managers/TextureManager.js +218 -0
- package/src/particlesystem/Particle.js +82 -7
- package/src/particlesystem/ParticleSettings.js +21 -3
- package/src/particlesystem/Particles.js +80 -31
- package/src/physics/AABB.js +207 -0
- package/src/physics/Body.js +862 -0
- package/src/physics/BodyType.js +16 -0
- package/src/physics/BroadPhase.js +641 -0
- package/src/physics/Collision.js +534 -0
- package/src/physics/Contact.js +500 -0
- package/src/physics/ContactSolver.js +526 -0
- package/src/physics/Distance.js +403 -0
- package/src/physics/DistanceJoint.js +227 -0
- package/src/physics/Fixture.js +346 -0
- package/src/physics/Island.js +203 -0
- package/src/physics/Joint.js +78 -0
- package/src/physics/Math2D.js +573 -0
- package/src/physics/RevoluteJoint.js +278 -0
- package/src/physics/Settings.js +78 -0
- package/src/physics/Shapes.js +549 -0
- package/src/physics/TimeOfImpact.js +87 -0
- package/src/physics/World.js +731 -0
- package/src/physics/index.js +79 -0
- package/dist/types/Drawable.d.ts +0 -157
- package/dist/types/Emerald.d.ts +0 -73
- package/dist/types/GLUtils.d.ts +0 -6
- package/dist/types/Physics.d.ts +0 -139
- package/dist/types/Scene.d.ts +0 -39
- package/dist/types/Shaders.d.ts +0 -4
- package/dist/types/Storage.d.ts +0 -46
- package/dist/types/Time.d.ts +0 -22
- package/dist/types/Transform.d.ts +0 -41
- package/dist/types/components/BoxColliderDebug.d.ts +0 -19
- package/dist/types/components/CircleColliderDebug.d.ts +0 -19
- package/dist/types/components/Collider.d.ts +0 -53
- package/dist/types/components/GameObject.d.ts +0 -72
- package/dist/types/components/RigidBody.d.ts +0 -104
- package/dist/types/managers/AudioManager.d.ts +0 -60
- package/dist/types/managers/GLManager.d.ts +0 -47
- package/dist/types/managers/IDManager.d.ts +0 -21
- package/dist/types/managers/SceneManager.d.ts +0 -22
- package/dist/types/particlesystem/Particle.d.ts +0 -42
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import GLManager from "./managers/GLManager.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @class RenderTarget
|
|
5
|
+
* @description An offscreen render surface: a framebuffer backed by a color
|
|
6
|
+
* texture (and an optional depth buffer). Bind it to render the scene (or a
|
|
7
|
+
* post-processing pass) into a texture instead of the screen. The resulting
|
|
8
|
+
* `texture` can then be sampled by another pass or drawn to the canvas.
|
|
9
|
+
*
|
|
10
|
+
* Used by the post-processing pipeline, but also useful on its own for
|
|
11
|
+
* minimaps, mirrors, render-to-texture effects, or picture-in-picture.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const rt = new RenderTarget(512, 512);
|
|
15
|
+
* rt.bind();
|
|
16
|
+
* // ...draw...
|
|
17
|
+
* rt.unbind();
|
|
18
|
+
* // rt.texture now holds the rendered image
|
|
19
|
+
*/
|
|
20
|
+
class RenderTarget {
|
|
21
|
+
/**
|
|
22
|
+
* @param {number} width - Width in pixels
|
|
23
|
+
* @param {number} height - Height in pixels
|
|
24
|
+
* @param {Object} [options] - { depth = false, pixelart = false }
|
|
25
|
+
*/
|
|
26
|
+
constructor(width, height, options = {}) {
|
|
27
|
+
this.gl = GLManager.getGL();
|
|
28
|
+
this.width = Math.max(1, width | 0);
|
|
29
|
+
this.height = Math.max(1, height | 0);
|
|
30
|
+
this.depth = !!options.depth;
|
|
31
|
+
this.pixelart = !!options.pixelart;
|
|
32
|
+
|
|
33
|
+
const gl = this.gl;
|
|
34
|
+
this.framebuffer = gl.createFramebuffer();
|
|
35
|
+
this.texture = gl.createTexture();
|
|
36
|
+
this.depthBuffer = this.depth ? gl.createRenderbuffer() : null;
|
|
37
|
+
|
|
38
|
+
this._allocate();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** @private */
|
|
42
|
+
_allocate() {
|
|
43
|
+
const gl = this.gl;
|
|
44
|
+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
45
|
+
gl.texImage2D(
|
|
46
|
+
gl.TEXTURE_2D,
|
|
47
|
+
0,
|
|
48
|
+
gl.RGBA,
|
|
49
|
+
this.width,
|
|
50
|
+
this.height,
|
|
51
|
+
0,
|
|
52
|
+
gl.RGBA,
|
|
53
|
+
gl.UNSIGNED_BYTE,
|
|
54
|
+
null
|
|
55
|
+
);
|
|
56
|
+
const filter = this.pixelart ? gl.NEAREST : gl.LINEAR;
|
|
57
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
|
|
58
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
59
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
60
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
61
|
+
|
|
62
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
|
63
|
+
gl.framebufferTexture2D(
|
|
64
|
+
gl.FRAMEBUFFER,
|
|
65
|
+
gl.COLOR_ATTACHMENT0,
|
|
66
|
+
gl.TEXTURE_2D,
|
|
67
|
+
this.texture,
|
|
68
|
+
0
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (this.depth) {
|
|
72
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, this.depthBuffer);
|
|
73
|
+
gl.renderbufferStorage(
|
|
74
|
+
gl.RENDERBUFFER,
|
|
75
|
+
gl.DEPTH_COMPONENT16,
|
|
76
|
+
this.width,
|
|
77
|
+
this.height
|
|
78
|
+
);
|
|
79
|
+
gl.framebufferRenderbuffer(
|
|
80
|
+
gl.FRAMEBUFFER,
|
|
81
|
+
gl.DEPTH_ATTACHMENT,
|
|
82
|
+
gl.RENDERBUFFER,
|
|
83
|
+
this.depthBuffer
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @method resize
|
|
92
|
+
* @description Resizes the surface (reallocating storage) if dimensions change.
|
|
93
|
+
*/
|
|
94
|
+
resize(width, height) {
|
|
95
|
+
const w = Math.max(1, width | 0);
|
|
96
|
+
const h = Math.max(1, height | 0);
|
|
97
|
+
if (w === this.width && h === this.height) return;
|
|
98
|
+
this.width = w;
|
|
99
|
+
this.height = h;
|
|
100
|
+
this._allocate();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @method bind
|
|
105
|
+
* @description Binds this framebuffer and sets the viewport to its full size.
|
|
106
|
+
*/
|
|
107
|
+
bind() {
|
|
108
|
+
const gl = this.gl;
|
|
109
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
|
110
|
+
gl.viewport(0, 0, this.width, this.height);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @method unbind
|
|
115
|
+
* @description Restores the default framebuffer (the canvas).
|
|
116
|
+
*/
|
|
117
|
+
unbind() {
|
|
118
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @method dispose
|
|
123
|
+
* @description Frees all GL resources held by this target.
|
|
124
|
+
*/
|
|
125
|
+
dispose() {
|
|
126
|
+
const gl = this.gl;
|
|
127
|
+
if (this.framebuffer) gl.deleteFramebuffer(this.framebuffer);
|
|
128
|
+
if (this.texture) gl.deleteTexture(this.texture);
|
|
129
|
+
if (this.depthBuffer) gl.deleteRenderbuffer(this.depthBuffer);
|
|
130
|
+
this.framebuffer = this.texture = this.depthBuffer = null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export default RenderTarget;
|
package/src/Scene.js
CHANGED
|
@@ -1,83 +1,115 @@
|
|
|
1
|
-
import GameObject from "./components/GameObject.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @class Scene
|
|
5
|
-
* @description Represents a scene
|
|
6
|
-
* @param {Array} objects - The objects in the scene
|
|
7
|
-
*/
|
|
8
|
-
class Scene {
|
|
9
|
-
constructor(objects = []) {
|
|
10
|
-
this.objects = objects;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @method add
|
|
15
|
-
* @description Adds an object to the scene
|
|
16
|
-
* @param {GameObject} object - The object to add
|
|
17
|
-
*/
|
|
18
|
-
add(object) {
|
|
19
|
-
if (!(object instanceof GameObject)) {
|
|
20
|
-
throw new Error("Object is not a GameObject");
|
|
21
|
-
}
|
|
22
|
-
object.setIsActive(true);
|
|
23
|
-
if (!this.objects.some((obj) => obj.id === object.id)) {
|
|
24
|
-
this.objects.push(object);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @method remove
|
|
30
|
-
* @description Removes an object from the scene
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
import GameObject from "./components/GameObject.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @class Scene
|
|
5
|
+
* @description Represents a scene
|
|
6
|
+
* @param {Array} objects - The objects in the scene
|
|
7
|
+
*/
|
|
8
|
+
class Scene {
|
|
9
|
+
constructor(objects = []) {
|
|
10
|
+
this.objects = objects;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @method add
|
|
15
|
+
* @description Adds an object to the scene
|
|
16
|
+
* @param {GameObject} object - The object to add
|
|
17
|
+
*/
|
|
18
|
+
add(object) {
|
|
19
|
+
if (!(object instanceof GameObject)) {
|
|
20
|
+
throw new Error("Object is not a GameObject");
|
|
21
|
+
}
|
|
22
|
+
object.setIsActive(true);
|
|
23
|
+
if (!this.objects.some((obj) => obj.id === object.id)) {
|
|
24
|
+
this.objects.push(object);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @method remove
|
|
30
|
+
* @description Removes an object from the scene. By default the object's GPU
|
|
31
|
+
* resources stay alive so it can be re-added later; pass { dispose: true }
|
|
32
|
+
* to also destroy it (free GL buffers/textures, physics bodies) when it is
|
|
33
|
+
* being removed for good.
|
|
34
|
+
* @param {GameObject} object - The object to remove
|
|
35
|
+
* @param {Object} [options] - { dispose = false }
|
|
36
|
+
*/
|
|
37
|
+
remove(object, options = {}) {
|
|
38
|
+
if (!(object instanceof GameObject)) {
|
|
39
|
+
throw new Error("Object is not a GameObject");
|
|
40
|
+
}
|
|
41
|
+
object.setIsActive(false);
|
|
42
|
+
this.objects = this.objects.filter(function (obj) {
|
|
43
|
+
var objId = obj ? obj.id : undefined;
|
|
44
|
+
var targetId = object ? object.id : undefined;
|
|
45
|
+
return objId !== targetId;
|
|
46
|
+
});
|
|
47
|
+
if (options.dispose) object.destroy();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @method dispose
|
|
52
|
+
* @description Destroys every object in the scene (freeing their GPU
|
|
53
|
+
* resources and physics bodies) and empties it. Call when a level/screen is
|
|
54
|
+
* torn down for good; removing objects without disposing leaks GL buffers
|
|
55
|
+
* over repeated scene swaps.
|
|
56
|
+
*/
|
|
57
|
+
dispose() {
|
|
58
|
+
for (const object of this.objects) {
|
|
59
|
+
if (object && typeof object.destroy === "function") object.destroy();
|
|
60
|
+
}
|
|
61
|
+
this.objects = [];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @method update
|
|
66
|
+
* @description Ticks every active object's component lifecycle. Call once per
|
|
67
|
+
* frame (before or after drawScene) to drive Behaviour components.
|
|
68
|
+
* @param {number} deltaTime - Seconds since the previous frame
|
|
69
|
+
*/
|
|
70
|
+
update(deltaTime) {
|
|
71
|
+
for (const object of this.objects) {
|
|
72
|
+
if (object.isActive && typeof object.update === "function") {
|
|
73
|
+
object.update(deltaTime);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @method setIsActive
|
|
80
|
+
* @description Sets the active state of the scene
|
|
81
|
+
* @param {boolean} bool - The active state
|
|
82
|
+
*/
|
|
83
|
+
setIsActive(bool) {
|
|
84
|
+
for (let object of this.objects) {
|
|
85
|
+
this.setActiveRecursive(object, bool);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @method setActiveRecursive
|
|
91
|
+
* @description Sets the active state of the scene recursively
|
|
92
|
+
* @param {Object} object - The object to set the active state of
|
|
93
|
+
* @param {boolean} bool - The active state
|
|
94
|
+
*/
|
|
95
|
+
setActiveRecursive(object, bool) {
|
|
96
|
+
object.setIsActive(bool);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
[Symbol.iterator]() {
|
|
100
|
+
let index = -1;
|
|
101
|
+
const data = this.objects;
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
next: () => ({ value: data[++index], done: !(index in data) }),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
forEach(callback) {
|
|
109
|
+
for (const obj of this.objects) {
|
|
110
|
+
callback(obj);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export default Scene;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import GameObject from "./components/GameObject.js";
|
|
2
|
+
import { Square2D } from "./Shapes.js";
|
|
3
|
+
import { Vector2, Vector3 } from "./Physics.js";
|
|
4
|
+
import Color from "./Color.js";
|
|
5
|
+
import Easing from "./Easing.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @class ScreenEffects
|
|
9
|
+
* @description In-engine full-screen camera/transition effects: fade to/from a
|
|
10
|
+
* color, screen flash, and cinematic letterbox bars. Everything is drawn with
|
|
11
|
+
* the engine's own screen-space quads (no DOM/CSS overlay), so it survives
|
|
12
|
+
* resolution changes, post-processing, and split-screen (the quads overfill
|
|
13
|
+
* every viewport and are clipped per camera).
|
|
14
|
+
*
|
|
15
|
+
* Add it to your scene's update loop by calling `update(dt)` each frame.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const fx = new ScreenEffects(scene, { layer: 100000 });
|
|
19
|
+
* await fx.fadeOut(0.4, new Color(0,0,0,255)); // to black
|
|
20
|
+
* loadNextLevel();
|
|
21
|
+
* await fx.fadeIn(0.4);
|
|
22
|
+
* // bumps:
|
|
23
|
+
* fx.flash(new Color(255,255,255,255), 0.15);
|
|
24
|
+
* // in the loop, before drawScene: fx.update(dt);
|
|
25
|
+
*/
|
|
26
|
+
class ScreenEffects {
|
|
27
|
+
/**
|
|
28
|
+
* @param {Scene} scene - The scene to draw the overlays into
|
|
29
|
+
* @param {Object} [options] - { layer = 100000, size = 5000 }
|
|
30
|
+
*/
|
|
31
|
+
constructor(scene, options = {}) {
|
|
32
|
+
this.scene = scene;
|
|
33
|
+
const layer = options.layer ?? 100000;
|
|
34
|
+
const half = options.size ?? 5000;
|
|
35
|
+
|
|
36
|
+
/** @private */
|
|
37
|
+
this._fade = this._makeQuad(layer, half, new Color(0, 0, 0, 255));
|
|
38
|
+
/** @private */
|
|
39
|
+
this._flashQuad = this._makeQuad(
|
|
40
|
+
layer + 1,
|
|
41
|
+
half,
|
|
42
|
+
new Color(255, 255, 255, 255)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
/** @private */
|
|
46
|
+
this._barTop = this._makeQuad(layer + 2, half, new Color(0, 0, 0, 255));
|
|
47
|
+
/** @private */
|
|
48
|
+
this._barBottom = this._makeQuad(layer + 2, half, new Color(0, 0, 0, 255));
|
|
49
|
+
this._barTop.setOpacity(0);
|
|
50
|
+
this._barBottom.setOpacity(0);
|
|
51
|
+
/** @private */
|
|
52
|
+
this._letterboxHeight = 0;
|
|
53
|
+
/** @private */
|
|
54
|
+
this._letterboxTarget = 0;
|
|
55
|
+
/** @private */
|
|
56
|
+
this._barHalf = half;
|
|
57
|
+
|
|
58
|
+
/** @private */
|
|
59
|
+
this._fadeAnim = null;
|
|
60
|
+
/** @private */
|
|
61
|
+
this._flashAnim = null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** @private */
|
|
65
|
+
_makeQuad(layer, half, color) {
|
|
66
|
+
const go = new GameObject(
|
|
67
|
+
"ScreenEffect",
|
|
68
|
+
new Vector3(0, 0, 0),
|
|
69
|
+
0,
|
|
70
|
+
new Vector2(half, half)
|
|
71
|
+
);
|
|
72
|
+
const shape = new Square2D();
|
|
73
|
+
shape.setColor(color);
|
|
74
|
+
shape.setUseLighting(false);
|
|
75
|
+
go.addComponent(shape);
|
|
76
|
+
go.setScreenSpace(true);
|
|
77
|
+
go.setLayer(layer);
|
|
78
|
+
go.alwaysVisible = true;
|
|
79
|
+
go.setOpacity(0);
|
|
80
|
+
/** @private */
|
|
81
|
+
this._shapeOf = this._shapeOf || new WeakMap();
|
|
82
|
+
this._shapeOf.set(go, shape);
|
|
83
|
+
this.scene.add(go);
|
|
84
|
+
return go;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @private */
|
|
88
|
+
_setColor(go, color) {
|
|
89
|
+
const shape = this._shapeOf.get(go);
|
|
90
|
+
if (shape) shape.setColor(color);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @method fadeOut
|
|
95
|
+
* @description Fades the screen to a solid color (opacity 0 -> 1).
|
|
96
|
+
* @param {number} duration - Seconds
|
|
97
|
+
* @param {Color} [color] - Target color (default black)
|
|
98
|
+
* @param {Function} [easing] - Easing function (default linear)
|
|
99
|
+
* @returns {Promise<void>} - Resolves when the fade completes
|
|
100
|
+
*/
|
|
101
|
+
fadeOut(
|
|
102
|
+
duration = 0.4,
|
|
103
|
+
color = new Color(0, 0, 0, 255),
|
|
104
|
+
easing = Easing.linear
|
|
105
|
+
) {
|
|
106
|
+
this._setColor(this._fade, color);
|
|
107
|
+
return this._startFade(this._fade.getOpacity(), 1, duration, easing);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @method fadeIn
|
|
112
|
+
* @description Fades the screen back in from the current overlay (opacity -> 0).
|
|
113
|
+
* @param {number} duration - Seconds
|
|
114
|
+
* @param {Function} [easing] - Easing function (default linear)
|
|
115
|
+
* @returns {Promise<void>}
|
|
116
|
+
*/
|
|
117
|
+
fadeIn(duration = 0.4, easing = Easing.linear) {
|
|
118
|
+
return this._startFade(this._fade.getOpacity(), 0, duration, easing);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** @private */
|
|
122
|
+
_startFade(from, to, duration, easing) {
|
|
123
|
+
return new Promise((resolve) => {
|
|
124
|
+
if (this._fadeAnim && this._fadeAnim.resolve) this._fadeAnim.resolve();
|
|
125
|
+
if (duration <= 0) {
|
|
126
|
+
this._fade.setOpacity(to);
|
|
127
|
+
resolve();
|
|
128
|
+
this._fadeAnim = null;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this._fadeAnim = { from, to, elapsed: 0, duration, easing, resolve };
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @method flash
|
|
137
|
+
* @description Flashes a color that ramps to full then fades out.
|
|
138
|
+
* @param {Color} [color] - Flash color (default white)
|
|
139
|
+
* @param {number} duration - Total seconds for the flash
|
|
140
|
+
* @returns {Promise<void>}
|
|
141
|
+
*/
|
|
142
|
+
flash(color = new Color(255, 255, 255, 255), duration = 0.2) {
|
|
143
|
+
this._setColor(this._flashQuad, color);
|
|
144
|
+
return new Promise((resolve) => {
|
|
145
|
+
if (this._flashAnim && this._flashAnim.resolve) this._flashAnim.resolve();
|
|
146
|
+
this._flashAnim = {
|
|
147
|
+
elapsed: 0,
|
|
148
|
+
duration: Math.max(0.0001, duration),
|
|
149
|
+
resolve,
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @method transition
|
|
156
|
+
* @description Fades the screen out to a color, runs a swap callback at the
|
|
157
|
+
* darkest point (e.g. tear down the old scene and build the new one), then
|
|
158
|
+
* fades back in. Requires `update(dt)` to be pumped each frame by your loop.
|
|
159
|
+
* @param {Function} swap - Called (and awaited) while the screen is covered
|
|
160
|
+
* @param {Object} [options] - { duration = 0.4, color = black, outDuration,
|
|
161
|
+
* inDuration, easing }
|
|
162
|
+
* @returns {Promise<void>} - Resolves after the fade-in completes
|
|
163
|
+
*/
|
|
164
|
+
async transition(swap, options = {}) {
|
|
165
|
+
const {
|
|
166
|
+
duration = 0.4,
|
|
167
|
+
color = new Color(0, 0, 0, 255),
|
|
168
|
+
outDuration,
|
|
169
|
+
inDuration,
|
|
170
|
+
easing = Easing.linear,
|
|
171
|
+
} = options;
|
|
172
|
+
await this.fadeOut(outDuration ?? duration, color, easing);
|
|
173
|
+
if (typeof swap === "function") await swap();
|
|
174
|
+
await this.fadeIn(inDuration ?? duration, easing);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @method setLetterbox
|
|
179
|
+
* @description Animates cinematic black bars to the given height (in pixels,
|
|
180
|
+
* per bar). Pass 0 to retract them.
|
|
181
|
+
* @param {number} heightPx - Target bar height in pixels
|
|
182
|
+
*/
|
|
183
|
+
setLetterbox(heightPx) {
|
|
184
|
+
this._letterboxTarget = Math.max(0, heightPx);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @method update
|
|
189
|
+
* @description Advances all active transitions. Call once per frame.
|
|
190
|
+
* @param {number} dt - Seconds since last frame
|
|
191
|
+
*/
|
|
192
|
+
update(dt) {
|
|
193
|
+
if (this._fadeAnim) {
|
|
194
|
+
const a = this._fadeAnim;
|
|
195
|
+
a.elapsed += dt;
|
|
196
|
+
const k = Math.min(1, a.elapsed / a.duration);
|
|
197
|
+
const eased = a.easing(k);
|
|
198
|
+
this._fade.setOpacity(a.from + (a.to - a.from) * eased);
|
|
199
|
+
if (k >= 1) {
|
|
200
|
+
const resolve = a.resolve;
|
|
201
|
+
this._fadeAnim = null;
|
|
202
|
+
if (resolve) resolve();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (this._flashAnim) {
|
|
207
|
+
const a = this._flashAnim;
|
|
208
|
+
a.elapsed += dt;
|
|
209
|
+
const k = Math.min(1, a.elapsed / a.duration);
|
|
210
|
+
const opacity = k < 0.25 ? k / 0.25 : 1 - (k - 0.25) / 0.75;
|
|
211
|
+
this._flashQuad.setOpacity(Math.max(0, opacity));
|
|
212
|
+
if (k >= 1) {
|
|
213
|
+
const resolve = a.resolve;
|
|
214
|
+
this._flashAnim = null;
|
|
215
|
+
this._flashQuad.setOpacity(0);
|
|
216
|
+
if (resolve) resolve();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (this._letterboxHeight !== this._letterboxTarget) {
|
|
221
|
+
const speed = 1200;
|
|
222
|
+
const dir = Math.sign(this._letterboxTarget - this._letterboxHeight);
|
|
223
|
+
this._letterboxHeight += dir * speed * dt;
|
|
224
|
+
if (
|
|
225
|
+
(dir > 0 && this._letterboxHeight > this._letterboxTarget) ||
|
|
226
|
+
(dir < 0 && this._letterboxHeight < this._letterboxTarget)
|
|
227
|
+
) {
|
|
228
|
+
this._letterboxHeight = this._letterboxTarget;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const visible = this._letterboxHeight > 0.5;
|
|
232
|
+
this._barTop.setOpacity(visible ? 1 : 0);
|
|
233
|
+
this._barBottom.setOpacity(visible ? 1 : 0);
|
|
234
|
+
if (visible) {
|
|
235
|
+
const offset =
|
|
236
|
+
this._barHalf + this._screenHalfHeight() - this._letterboxHeight;
|
|
237
|
+
this._barTop.transform.position.y = offset;
|
|
238
|
+
this._barBottom.transform.position.y = -offset;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** @private */
|
|
243
|
+
_screenHalfHeight() {
|
|
244
|
+
if (typeof window !== "undefined" && window.innerHeight) {
|
|
245
|
+
return window.innerHeight / 2;
|
|
246
|
+
}
|
|
247
|
+
return 360;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @method destroy
|
|
252
|
+
* @description Removes all overlay objects from the scene.
|
|
253
|
+
*/
|
|
254
|
+
destroy() {
|
|
255
|
+
for (const go of [
|
|
256
|
+
this._fade,
|
|
257
|
+
this._flashQuad,
|
|
258
|
+
this._barTop,
|
|
259
|
+
this._barBottom,
|
|
260
|
+
]) {
|
|
261
|
+
this.scene.remove(go);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export default ScreenEffects;
|