emeraldengine 2.2.0 → 3.0.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.
Files changed (162) hide show
  1. package/README.md +2359 -968
  2. package/dist/types/index.d.ts +72 -32
  3. package/dist/types/src/Animator.d.ts +50 -0
  4. package/dist/types/{BitmapText.d.ts → src/BitmapText.d.ts} +19 -21
  5. package/dist/types/src/Camera.d.ts +122 -0
  6. package/dist/types/src/CameraController.d.ts +107 -0
  7. package/dist/types/src/CanvasText.d.ts +91 -0
  8. package/dist/types/src/CollisionLayers.d.ts +58 -0
  9. package/dist/types/{Color.d.ts → src/Color.d.ts} +5 -6
  10. package/dist/types/src/Coroutine.d.ts +111 -0
  11. package/dist/types/src/DebugOverlay.d.ts +86 -0
  12. package/dist/types/src/Drawable.d.ts +271 -0
  13. package/dist/types/src/Easing.d.ts +22 -0
  14. package/dist/types/src/Emerald.d.ts +420 -0
  15. package/dist/types/src/EmeraldDB.d.ts +159 -0
  16. package/dist/types/{FPSCounter.d.ts → src/FPSCounter.d.ts} +1 -3
  17. package/dist/types/src/GLUtils.d.ts +4 -0
  18. package/dist/types/{Instance.d.ts → src/Instance.d.ts} +37 -15
  19. package/dist/types/{InstancedTexture.d.ts → src/InstancedTexture.d.ts} +60 -23
  20. package/dist/types/src/Interpolator.d.ts +66 -0
  21. package/dist/types/src/Material.d.ts +87 -0
  22. package/dist/types/src/MathUtils.d.ts +80 -0
  23. package/dist/types/src/ParticleEmitter.d.ts +131 -0
  24. package/dist/types/{Physics.d.ts → src/Physics.d.ts} +88 -20
  25. package/dist/types/src/Pool.d.ts +53 -0
  26. package/dist/types/src/PostEffects.d.ts +68 -0
  27. package/dist/types/src/PostProcessor.d.ts +124 -0
  28. package/dist/types/src/RenderTarget.d.ts +56 -0
  29. package/dist/types/src/Scene.d.ts +62 -0
  30. package/dist/types/src/ScreenEffects.d.ts +111 -0
  31. package/dist/types/src/Serializer.d.ts +86 -0
  32. package/dist/types/src/Shaders.d.ts +2 -0
  33. package/dist/types/{Shapes.d.ts → src/Shapes.d.ts} +4 -6
  34. package/dist/types/src/SpatialGrid.d.ts +50 -0
  35. package/dist/types/src/SpriteBatch.d.ts +89 -0
  36. package/dist/types/src/StateMachine.d.ts +59 -0
  37. package/dist/types/src/Storage.d.ts +89 -0
  38. package/dist/types/{Texture.d.ts → src/Texture.d.ts} +3 -4
  39. package/dist/types/src/TextureAtlas.d.ts +55 -0
  40. package/dist/types/src/Tilemap.d.ts +91 -0
  41. package/dist/types/src/Time.d.ts +53 -0
  42. package/dist/types/src/Timer.d.ts +54 -0
  43. package/dist/types/src/Transform.d.ts +94 -0
  44. package/dist/types/src/Tween.d.ts +81 -0
  45. package/dist/types/src/UI.d.ts +121 -0
  46. package/dist/types/src/components/Behaviour.d.ts +71 -0
  47. package/dist/types/{components → src/components}/BoxCollider.d.ts +14 -14
  48. package/dist/types/src/components/BoxColliderDebug.d.ts +15 -0
  49. package/dist/types/{components → src/components}/CircleCollider.d.ts +14 -12
  50. package/dist/types/src/components/CircleColliderDebug.d.ts +15 -0
  51. package/dist/types/src/components/Collider.d.ts +96 -0
  52. package/dist/types/src/components/GameObject.d.ts +135 -0
  53. package/dist/types/src/components/RigidBody.d.ts +183 -0
  54. package/dist/types/src/importers/Aseprite.d.ts +79 -0
  55. package/dist/types/src/importers/TiledMap.d.ts +62 -0
  56. package/dist/types/{lights → src/lights}/DirectionalLight.d.ts +7 -9
  57. package/dist/types/{lights → src/lights}/PointLight.d.ts +6 -9
  58. package/dist/types/src/managers/AssetManager.d.ts +116 -0
  59. package/dist/types/src/managers/AudioManager.d.ts +259 -0
  60. package/dist/types/{managers → src/managers}/CameraManager.d.ts +8 -8
  61. package/dist/types/{managers → src/managers}/EventManager.d.ts +46 -32
  62. package/dist/types/src/managers/GLManager.d.ts +84 -0
  63. package/dist/types/src/managers/GLState.d.ts +37 -0
  64. package/dist/types/src/managers/IDManager.d.ts +31 -0
  65. package/dist/types/src/managers/InputManager.d.ts +290 -0
  66. package/dist/types/src/managers/NetworkManager.d.ts +93 -0
  67. package/dist/types/src/managers/RenderStats.d.ts +34 -0
  68. package/dist/types/src/managers/SceneManager.d.ts +44 -0
  69. package/dist/types/src/managers/ShaderManager.d.ts +55 -0
  70. package/dist/types/src/managers/TextureManager.d.ts +102 -0
  71. package/dist/types/src/particlesystem/Particle.d.ts +64 -0
  72. package/dist/types/{particlesystem → src/particlesystem}/ParticleSettings.d.ts +32 -24
  73. package/dist/types/{particlesystem → src/particlesystem}/Particles.d.ts +20 -12
  74. package/index.js +72 -0
  75. package/package.json +74 -60
  76. package/src/Animator.js +95 -0
  77. package/src/BitmapText.js +6 -5
  78. package/src/Camera.js +183 -0
  79. package/src/CameraController.js +192 -0
  80. package/src/CanvasText.js +281 -0
  81. package/src/CollisionLayers.js +86 -0
  82. package/src/Color.js +18 -18
  83. package/src/Coroutine.js +259 -0
  84. package/src/DebugOverlay.js +246 -0
  85. package/src/Drawable.js +842 -555
  86. package/src/Easing.js +57 -0
  87. package/src/Emerald.js +1150 -459
  88. package/src/EmeraldDB.js +328 -0
  89. package/src/FPSCounter.js +43 -43
  90. package/src/GLUtils.js +60 -67
  91. package/src/Instance.js +41 -5
  92. package/src/InstancedTexture.js +251 -118
  93. package/src/Interpolator.js +124 -0
  94. package/src/Material.js +202 -0
  95. package/src/MathUtils.js +133 -0
  96. package/src/ParticleEmitter.js +284 -0
  97. package/src/Physics.js +186 -5
  98. package/src/Pool.js +85 -0
  99. package/src/PostEffects.js +296 -0
  100. package/src/PostProcessor.js +304 -0
  101. package/src/RenderTarget.js +134 -0
  102. package/src/Scene.js +115 -83
  103. package/src/ScreenEffects.js +266 -0
  104. package/src/Serializer.js +131 -0
  105. package/src/Shaders.js +150 -165
  106. package/src/Shapes.js +118 -129
  107. package/src/SpatialGrid.js +111 -0
  108. package/src/SpriteBatch.js +299 -0
  109. package/src/StateMachine.js +82 -0
  110. package/src/Storage.js +175 -47
  111. package/src/Texture.js +58 -67
  112. package/src/TextureAtlas.js +96 -0
  113. package/src/Tilemap.js +274 -0
  114. package/src/Time.js +51 -6
  115. package/src/Timer.js +99 -0
  116. package/src/Transform.js +100 -7
  117. package/src/Tween.js +160 -0
  118. package/src/UI.js +394 -0
  119. package/src/components/Behaviour.js +90 -0
  120. package/src/components/BoxCollider.js +22 -3
  121. package/src/components/CircleCollider.js +19 -3
  122. package/src/components/CircleColliderDebug.js +24 -24
  123. package/src/components/Collider.js +140 -34
  124. package/src/components/GameObject.js +130 -21
  125. package/src/components/RigidBody.js +123 -2
  126. package/src/importers/Aseprite.js +142 -0
  127. package/src/importers/TiledMap.js +158 -0
  128. package/src/lights/DirectionalLight.js +6 -15
  129. package/src/lights/PointLight.js +4 -4
  130. package/src/managers/AssetManager.js +239 -0
  131. package/src/managers/AudioManager.js +565 -146
  132. package/src/managers/EventManager.js +488 -477
  133. package/src/managers/GLManager.js +57 -0
  134. package/src/managers/GLState.js +70 -0
  135. package/src/managers/IDManager.js +24 -2
  136. package/src/managers/InputManager.js +779 -0
  137. package/src/managers/NetworkManager.js +178 -0
  138. package/src/managers/RenderStats.js +34 -0
  139. package/src/managers/SceneManager.js +30 -0
  140. package/src/managers/ShaderManager.js +0 -2
  141. package/src/managers/TextureManager.js +218 -0
  142. package/src/particlesystem/Particle.js +82 -7
  143. package/src/particlesystem/ParticleSettings.js +21 -3
  144. package/src/particlesystem/Particles.js +80 -31
  145. package/dist/types/Drawable.d.ts +0 -157
  146. package/dist/types/Emerald.d.ts +0 -73
  147. package/dist/types/GLUtils.d.ts +0 -6
  148. package/dist/types/Scene.d.ts +0 -39
  149. package/dist/types/Shaders.d.ts +0 -4
  150. package/dist/types/Storage.d.ts +0 -46
  151. package/dist/types/Time.d.ts +0 -22
  152. package/dist/types/Transform.d.ts +0 -41
  153. package/dist/types/components/BoxColliderDebug.d.ts +0 -19
  154. package/dist/types/components/CircleColliderDebug.d.ts +0 -19
  155. package/dist/types/components/Collider.d.ts +0 -53
  156. package/dist/types/components/GameObject.d.ts +0 -72
  157. package/dist/types/components/RigidBody.d.ts +0 -104
  158. package/dist/types/managers/AudioManager.d.ts +0 -60
  159. package/dist/types/managers/GLManager.d.ts +0 -47
  160. package/dist/types/managers/IDManager.d.ts +0 -21
  161. package/dist/types/managers/SceneManager.d.ts +0 -22
  162. package/dist/types/particlesystem/Particle.d.ts +0 -42
package/src/Shapes.js CHANGED
@@ -1,129 +1,118 @@
1
- import { initVertexBuffer } from "./GLUtils.js";
2
- import Drawable from "./Drawable.js";
3
- import GLManager from "./managers/GLManager.js";
4
-
5
- /**
6
- * @class Square2D
7
- * @description Represents a square 2D shape
8
- */
9
- class Square2D extends Drawable {
10
- constructor() {
11
- const vertices = [1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0];
12
- const verticesBuffer = initVertexBuffer(GLManager.getGL(), vertices);
13
- const textureCoordinates = [
14
- 1.0,
15
- 1.0, // Top-right
16
- 0.0,
17
- 1.0, // Top-left
18
- 1.0,
19
- 0.0, // Bottom-right
20
- 0.0,
21
- 0.0, // Bottom-left
22
- ];
23
- const texCoordBuffer = initVertexBuffer(
24
- GLManager.getGL(),
25
- textureCoordinates
26
- );
27
-
28
- super(
29
- GLManager.getGL(),
30
- GLManager.getProgramInfo(),
31
- verticesBuffer,
32
- texCoordBuffer,
33
- vertices,
34
- false,
35
- "",
36
- 0,
37
- 0,
38
- 0,
39
- 0,
40
- 0,
41
- false
42
- );
43
- }
44
- }
45
-
46
- /**
47
- * @class Triangle2D
48
- * @description Represents a triangle 2D shape
49
- */
50
- class Triangle2D extends Drawable {
51
- constructor() {
52
- const vertices = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
53
- const verticesBuffer = initVertexBuffer(GLManager.getGL(), vertices);
54
-
55
- const textureCoordinates = [0.5, 1.0, 1.0, 0.0, 0.0, 0.0];
56
- const texCoordBuffer = initVertexBuffer(
57
- GLManager.getGL(),
58
- textureCoordinates
59
- );
60
-
61
- super(
62
- GLManager.getGL(),
63
- GLManager.getProgramInfo(),
64
- verticesBuffer,
65
- texCoordBuffer,
66
- vertices,
67
- false,
68
- "",
69
- 0,
70
- 0,
71
- 0,
72
- 0,
73
- 0,
74
- false
75
- );
76
- }
77
- }
78
-
79
- /**
80
- * @class Circle2D
81
- * @description Represents a circle 2D shape
82
- * @param {number} segments - The number of segments to use to draw the circle
83
- */
84
- class Circle2D extends Drawable {
85
- constructor(segments = 32) {
86
- const radius = 1.0;
87
- const vertices = [];
88
- const textureCoordinates = [];
89
-
90
- // Add center vertex
91
- vertices.push(0, 0);
92
- textureCoordinates.push(0.5, 0.5);
93
-
94
- // Add perimeter vertices
95
- for (let i = 0; i <= segments; i++) {
96
- const angle = (i * 2 * Math.PI) / segments;
97
- const x = radius * Math.cos(angle);
98
- const y = radius * Math.sin(angle);
99
- vertices.push(x, y);
100
- textureCoordinates.push((x / radius + 1) / 2, (y / radius + 1) / 2);
101
- }
102
-
103
- const verticesBuffer = initVertexBuffer(GLManager.getGL(), vertices);
104
- const texCoordBuffer = initVertexBuffer(
105
- GLManager.getGL(),
106
- textureCoordinates
107
- );
108
-
109
- super(
110
- GLManager.getGL(),
111
- GLManager.getProgramInfo(),
112
- verticesBuffer,
113
- texCoordBuffer,
114
- vertices,
115
- false,
116
- "",
117
- 0,
118
- 0,
119
- 0,
120
- 0,
121
- 0,
122
- false,
123
- true,
124
- false
125
- );
126
- }
127
- }
128
-
129
- export { Square2D, Triangle2D, Circle2D };
1
+ import { initVertexBuffer } from "./GLUtils.js";
2
+ import Drawable from "./Drawable.js";
3
+ import GLManager from "./managers/GLManager.js";
4
+
5
+ /**
6
+ * @class Square2D
7
+ * @description Represents a square 2D shape
8
+ */
9
+ class Square2D extends Drawable {
10
+ constructor() {
11
+ const vertices = [1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0];
12
+ const verticesBuffer = initVertexBuffer(GLManager.getGL(), vertices);
13
+ const textureCoordinates = [1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0];
14
+ const texCoordBuffer = initVertexBuffer(
15
+ GLManager.getGL(),
16
+ textureCoordinates
17
+ );
18
+
19
+ super(
20
+ GLManager.getGL(),
21
+ GLManager.getProgramInfo(),
22
+ verticesBuffer,
23
+ texCoordBuffer,
24
+ vertices,
25
+ false,
26
+ "",
27
+ 0,
28
+ 0,
29
+ 0,
30
+ 0,
31
+ 0,
32
+ false
33
+ );
34
+ }
35
+ }
36
+
37
+ /**
38
+ * @class Triangle2D
39
+ * @description Represents a triangle 2D shape
40
+ */
41
+ class Triangle2D extends Drawable {
42
+ constructor() {
43
+ const vertices = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
44
+ const verticesBuffer = initVertexBuffer(GLManager.getGL(), vertices);
45
+
46
+ const textureCoordinates = [0.5, 1.0, 1.0, 0.0, 0.0, 0.0];
47
+ const texCoordBuffer = initVertexBuffer(
48
+ GLManager.getGL(),
49
+ textureCoordinates
50
+ );
51
+
52
+ super(
53
+ GLManager.getGL(),
54
+ GLManager.getProgramInfo(),
55
+ verticesBuffer,
56
+ texCoordBuffer,
57
+ vertices,
58
+ false,
59
+ "",
60
+ 0,
61
+ 0,
62
+ 0,
63
+ 0,
64
+ 0,
65
+ false
66
+ );
67
+ }
68
+ }
69
+
70
+ /**
71
+ * @class Circle2D
72
+ * @description Represents a circle 2D shape
73
+ * @param {number} segments - The number of segments to use to draw the circle
74
+ */
75
+ class Circle2D extends Drawable {
76
+ constructor(segments = 32) {
77
+ const radius = 1.0;
78
+ const vertices = [];
79
+ const textureCoordinates = [];
80
+
81
+ vertices.push(0, 0);
82
+ textureCoordinates.push(0.5, 0.5);
83
+
84
+ for (let i = 0; i <= segments; i++) {
85
+ const angle = (i * 2 * Math.PI) / segments;
86
+ const x = radius * Math.cos(angle);
87
+ const y = radius * Math.sin(angle);
88
+ vertices.push(x, y);
89
+ textureCoordinates.push((x / radius + 1) / 2, (y / radius + 1) / 2);
90
+ }
91
+
92
+ const verticesBuffer = initVertexBuffer(GLManager.getGL(), vertices);
93
+ const texCoordBuffer = initVertexBuffer(
94
+ GLManager.getGL(),
95
+ textureCoordinates
96
+ );
97
+
98
+ super(
99
+ GLManager.getGL(),
100
+ GLManager.getProgramInfo(),
101
+ verticesBuffer,
102
+ texCoordBuffer,
103
+ vertices,
104
+ false,
105
+ "",
106
+ 0,
107
+ 0,
108
+ 0,
109
+ 0,
110
+ 0,
111
+ false,
112
+ true,
113
+ false
114
+ );
115
+ }
116
+ }
117
+
118
+ export { Square2D, Triangle2D, Circle2D };
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @class SpatialGrid
3
+ * @description A uniform spatial hash grid for fast 2D neighbor queries (picking,
4
+ * proximity, broadphase). Rebuild it each frame (or as objects move) with
5
+ * clear()/insert(), then query by radius or rectangle.
6
+ *
7
+ * @example
8
+ * const grid = new SpatialGrid(64);
9
+ * grid.clear();
10
+ * for (const e of enemies) grid.insert(e, e.transform.position.x, e.transform.position.y);
11
+ * const near = grid.queryRadius(player.x, player.y, 100);
12
+ */
13
+ class SpatialGrid {
14
+ /**
15
+ * @param {number} cellSize - World units per cell
16
+ */
17
+ constructor(cellSize = 64) {
18
+ this.cellSize = cellSize;
19
+ this.cells = new Map();
20
+ }
21
+
22
+ /** @private */
23
+ _key(cx, cy) {
24
+ return cx + "," + cy;
25
+ }
26
+
27
+ /** @private */
28
+ _cell(x, y) {
29
+ return [Math.floor(x / this.cellSize), Math.floor(y / this.cellSize)];
30
+ }
31
+
32
+ /**
33
+ * @method clear
34
+ * @description Empties the grid.
35
+ */
36
+ clear() {
37
+ this.cells.clear();
38
+ }
39
+
40
+ /**
41
+ * @method insert
42
+ * @description Inserts an item at a world position.
43
+ * @param {*} item - The item to store
44
+ * @param {number} x - World x
45
+ * @param {number} y - World y
46
+ */
47
+ insert(item, x, y) {
48
+ const [cx, cy] = this._cell(x, y);
49
+ const key = this._key(cx, cy);
50
+ let bucket = this.cells.get(key);
51
+ if (!bucket) {
52
+ bucket = [];
53
+ this.cells.set(key, bucket);
54
+ }
55
+ bucket.push({ item, x, y });
56
+ }
57
+
58
+ /**
59
+ * @method queryRect
60
+ * @description Returns items whose stored position lies within a rectangle.
61
+ * @returns {Array} - Matching items
62
+ */
63
+ queryRect(minX, minY, maxX, maxY) {
64
+ const [cx0, cy0] = this._cell(minX, minY);
65
+ const [cx1, cy1] = this._cell(maxX, maxY);
66
+ const results = [];
67
+ for (let cx = cx0; cx <= cx1; cx++) {
68
+ for (let cy = cy0; cy <= cy1; cy++) {
69
+ const bucket = this.cells.get(this._key(cx, cy));
70
+ if (!bucket) continue;
71
+ for (const entry of bucket) {
72
+ if (
73
+ entry.x >= minX &&
74
+ entry.x <= maxX &&
75
+ entry.y >= minY &&
76
+ entry.y <= maxY
77
+ ) {
78
+ results.push(entry.item);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return results;
84
+ }
85
+
86
+ /**
87
+ * @method queryRadius
88
+ * @description Returns items within a radius of a point.
89
+ * @returns {Array} - Matching items
90
+ */
91
+ queryRadius(x, y, radius) {
92
+ const r2 = radius * radius;
93
+ const results = [];
94
+ const [cx0, cy0] = this._cell(x - radius, y - radius);
95
+ const [cx1, cy1] = this._cell(x + radius, y + radius);
96
+ for (let cx = cx0; cx <= cx1; cx++) {
97
+ for (let cy = cy0; cy <= cy1; cy++) {
98
+ const bucket = this.cells.get(this._key(cx, cy));
99
+ if (!bucket) continue;
100
+ for (const entry of bucket) {
101
+ const dx = entry.x - x;
102
+ const dy = entry.y - y;
103
+ if (dx * dx + dy * dy <= r2) results.push(entry.item);
104
+ }
105
+ }
106
+ }
107
+ return results;
108
+ }
109
+ }
110
+
111
+ export default SpatialGrid;
@@ -0,0 +1,299 @@
1
+ import { initShaderProgram } from "./GLUtils.js";
2
+ import GLManager from "./managers/GLManager.js";
3
+ import RenderStats from "./managers/RenderStats.js";
4
+
5
+ const BATCH_VERTEX_SHADER = `
6
+ attribute vec2 aPos;
7
+ attribute vec2 aUV;
8
+ attribute vec4 aColor;
9
+ uniform mat4 uProjection;
10
+ uniform mat4 uView;
11
+ varying vec2 vUV;
12
+ varying vec4 vColor;
13
+ void main() {
14
+ gl_Position = uProjection * uView * vec4(aPos, 0.0, 1.0);
15
+ vUV = aUV;
16
+ vColor = aColor;
17
+ }
18
+ `;
19
+
20
+ const BATCH_FRAGMENT_SHADER = `
21
+ #ifdef GL_ES
22
+ precision highp float;
23
+ #endif
24
+ uniform sampler2D uSampler;
25
+ varying vec2 vUV;
26
+ varying vec4 vColor;
27
+ void main() {
28
+ vec4 tex = texture2D(uSampler, vUV);
29
+ if (tex.a < 0.01) discard;
30
+ gl_FragColor = tex * vColor;
31
+ }
32
+ `;
33
+
34
+ const FLOATS_PER_VERTEX = 8;
35
+ const VERTS_PER_QUAD = 4;
36
+ const INDICES_PER_QUAD = 6;
37
+
38
+ /**
39
+ * @class SpriteBatch
40
+ * @description A dynamic batched sprite renderer. Instead of one draw call per
41
+ * sprite (as ordinary Drawables incur), it accumulates many sprites that share a
42
+ * texture into a single interleaved buffer and submits them in one
43
+ * `drawElements` call. Batches are flushed automatically when the texture
44
+ * changes or the buffer fills, so for content that shares a texture/atlas this
45
+ * collapses hundreds of draw calls into a handful.
46
+ *
47
+ * It uses its own minimal shader program (position + uv + per-vertex color), so
48
+ * it is independent of the main render pipeline.
49
+ *
50
+ * @example
51
+ * const batch = new SpriteBatch();
52
+ * batch.begin(projectionMatrix, viewMatrix); // gl-matrix mat4s
53
+ * for (const e of entities) {
54
+ * batch.draw({ texture: atlasTex, x: e.x, y: e.y, w: 32, h: 32,
55
+ * u0: e.u0, v0: e.v0, u1: e.u1, v1: e.v1 });
56
+ * }
57
+ * batch.end();
58
+ */
59
+ class SpriteBatch {
60
+ /**
61
+ * @param {Object} [options] - { maxQuads = 2000 }
62
+ */
63
+ constructor(options = {}) {
64
+ this.gl = GLManager.getGL();
65
+ this.maxQuads = options.maxQuads ?? 2000;
66
+
67
+ const gl = this.gl;
68
+ this.program = initShaderProgram(
69
+ gl,
70
+ BATCH_VERTEX_SHADER,
71
+ BATCH_FRAGMENT_SHADER
72
+ );
73
+ this.attribs = {
74
+ pos: gl.getAttribLocation(this.program, "aPos"),
75
+ uv: gl.getAttribLocation(this.program, "aUV"),
76
+ color: gl.getAttribLocation(this.program, "aColor"),
77
+ };
78
+ this.uniforms = {
79
+ projection: gl.getUniformLocation(this.program, "uProjection"),
80
+ view: gl.getUniformLocation(this.program, "uView"),
81
+ sampler: gl.getUniformLocation(this.program, "uSampler"),
82
+ };
83
+
84
+ this.vertexData = new Float32Array(
85
+ this.maxQuads * VERTS_PER_QUAD * FLOATS_PER_VERTEX
86
+ );
87
+ this.vertexBuffer = gl.createBuffer();
88
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
89
+ gl.bufferData(gl.ARRAY_BUFFER, this.vertexData.byteLength, gl.DYNAMIC_DRAW);
90
+
91
+ const indices = new Uint16Array(this.maxQuads * INDICES_PER_QUAD);
92
+ for (let q = 0; q < this.maxQuads; q++) {
93
+ const v = q * VERTS_PER_QUAD;
94
+ const i = q * INDICES_PER_QUAD;
95
+ indices[i] = v;
96
+ indices[i + 1] = v + 1;
97
+ indices[i + 2] = v + 2;
98
+ indices[i + 3] = v;
99
+ indices[i + 4] = v + 2;
100
+ indices[i + 5] = v + 3;
101
+ }
102
+ this.indexBuffer = gl.createBuffer();
103
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
104
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
105
+
106
+ /** @private */
107
+ this._quadCount = 0;
108
+ /** @private */
109
+ this._currentTexture = null;
110
+ /** @private */
111
+ this._projection = null;
112
+ /** @private */
113
+ this._view = null;
114
+ this.drawCalls = 0;
115
+ }
116
+
117
+ /**
118
+ * @method begin
119
+ * @description Starts a batch with the given projection and view matrices
120
+ * (gl-matrix mat4 / Float32Array(16)).
121
+ */
122
+ begin(projectionMatrix, viewMatrix) {
123
+ this._projection = projectionMatrix;
124
+ this._view = viewMatrix;
125
+ this._quadCount = 0;
126
+ this._currentTexture = null;
127
+ this.drawCalls = 0;
128
+ }
129
+
130
+ /**
131
+ * @method draw
132
+ * @description Queues one sprite. Flushes first if the texture changed or the
133
+ * batch is full.
134
+ * @param {Object} sprite - {
135
+ * texture, x, y, w, h,
136
+ * rotation = 0, originX = 0.5, originY = 0.5,
137
+ * u0 = 0, v0 = 0, u1 = 1, v1 = 1,
138
+ * r = 1, g = 1, b = 1, a = 1
139
+ * }
140
+ */
141
+ draw(sprite) {
142
+ const tex = sprite.texture;
143
+ if (
144
+ (this._currentTexture && tex !== this._currentTexture) ||
145
+ this._quadCount >= this.maxQuads
146
+ ) {
147
+ this.flush();
148
+ }
149
+ this._currentTexture = tex;
150
+
151
+ const {
152
+ x,
153
+ y,
154
+ w,
155
+ h,
156
+ rotation = 0,
157
+ originX = 0.5,
158
+ originY = 0.5,
159
+ u0 = 0,
160
+ v0 = 0,
161
+ u1 = 1,
162
+ v1 = 1,
163
+ r = 1,
164
+ g = 1,
165
+ b = 1,
166
+ a = 1,
167
+ } = sprite;
168
+
169
+ const cx = x + (0.5 - originX) * w;
170
+ const cy = y + (0.5 - originY) * h;
171
+ const offset = this._quadCount * VERTS_PER_QUAD * FLOATS_PER_VERTEX;
172
+ SpriteBatch._writeQuad(
173
+ this.vertexData,
174
+ offset,
175
+ cx,
176
+ cy,
177
+ w / 2,
178
+ h / 2,
179
+ rotation,
180
+ u0,
181
+ v0,
182
+ u1,
183
+ v1,
184
+ r,
185
+ g,
186
+ b,
187
+ a
188
+ );
189
+ this._quadCount++;
190
+ }
191
+
192
+ /**
193
+ * @method end
194
+ * @description Flushes any remaining sprites.
195
+ */
196
+ end() {
197
+ this.flush();
198
+ }
199
+
200
+ /**
201
+ * @method flush
202
+ * @description Uploads and draws the currently staged quads.
203
+ */
204
+ flush() {
205
+ if (this._quadCount === 0 || !this._currentTexture) return;
206
+ const gl = this.gl;
207
+
208
+ gl.useProgram(this.program);
209
+ gl.uniformMatrix4fv(this.uniforms.projection, false, this._projection);
210
+ gl.uniformMatrix4fv(this.uniforms.view, false, this._view);
211
+
212
+ gl.activeTexture(gl.TEXTURE0);
213
+ gl.bindTexture(gl.TEXTURE_2D, this._currentTexture);
214
+ gl.uniform1i(this.uniforms.sampler, 0);
215
+
216
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
217
+ const used = this._quadCount * VERTS_PER_QUAD * FLOATS_PER_VERTEX;
218
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexData.subarray(0, used));
219
+
220
+ const stride = FLOATS_PER_VERTEX * 4;
221
+ gl.enableVertexAttribArray(this.attribs.pos);
222
+ gl.vertexAttribPointer(this.attribs.pos, 2, gl.FLOAT, false, stride, 0);
223
+ gl.enableVertexAttribArray(this.attribs.uv);
224
+ gl.vertexAttribPointer(this.attribs.uv, 2, gl.FLOAT, false, stride, 2 * 4);
225
+ gl.enableVertexAttribArray(this.attribs.color);
226
+ gl.vertexAttribPointer(
227
+ this.attribs.color,
228
+ 4,
229
+ gl.FLOAT,
230
+ false,
231
+ stride,
232
+ 4 * 4
233
+ );
234
+
235
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
236
+ gl.drawElements(
237
+ gl.TRIANGLES,
238
+ this._quadCount * INDICES_PER_QUAD,
239
+ gl.UNSIGNED_SHORT,
240
+ 0
241
+ );
242
+
243
+ this.drawCalls++;
244
+ RenderStats.drawCalls++;
245
+ RenderStats.quads += this._quadCount;
246
+ RenderStats.textureBinds++;
247
+ this._quadCount = 0;
248
+ }
249
+
250
+ /**
251
+ * @method _writeQuad
252
+ * @description Pure helper that writes one quad's 4 interleaved vertices
253
+ * (position, uv, color) into `out` at `offset`. Positions are rotated around
254
+ * the quad center (cx, cy). Exposed (and side-effect free) for testing.
255
+ * @private
256
+ */
257
+ static _writeQuad(
258
+ out,
259
+ offset,
260
+ cx,
261
+ cy,
262
+ hw,
263
+ hh,
264
+ rot,
265
+ u0,
266
+ v0,
267
+ u1,
268
+ v1,
269
+ r,
270
+ g,
271
+ b,
272
+ a
273
+ ) {
274
+ const cos = Math.cos(rot);
275
+ const sin = Math.sin(rot);
276
+ const corners = [
277
+ [-hw, hh, u0, v0],
278
+ [hw, hh, u1, v0],
279
+ [hw, -hh, u1, v1],
280
+ [-hw, -hh, u0, v1],
281
+ ];
282
+ let o = offset;
283
+ for (let i = 0; i < 4; i++) {
284
+ const lx = corners[i][0];
285
+ const ly = corners[i][1];
286
+ out[o++] = cx + lx * cos - ly * sin;
287
+ out[o++] = cy + lx * sin + ly * cos;
288
+ out[o++] = corners[i][2];
289
+ out[o++] = corners[i][3];
290
+ out[o++] = r;
291
+ out[o++] = g;
292
+ out[o++] = b;
293
+ out[o++] = a;
294
+ }
295
+ return o;
296
+ }
297
+ }
298
+
299
+ export default SpriteBatch;