littlejsengine 1.12.6 → 1.13.4

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 (102) hide show
  1. package/README.md +15 -12
  2. package/dist/littlejs.d.ts +466 -236
  3. package/dist/littlejs.esm.js +6126 -5370
  4. package/dist/littlejs.esm.min.js +4 -1
  5. package/dist/littlejs.js +6093 -5359
  6. package/dist/littlejs.min.js +4 -1
  7. package/dist/littlejs.release.js +5614 -4907
  8. package/examples/box2d/game.js +2 -2
  9. package/examples/box2d/gameObjects.js +8 -7
  10. package/examples/box2d/index.html +1 -1
  11. package/examples/box2d/scenes.js +8 -8
  12. package/examples/breakout/game.js +1 -1
  13. package/examples/breakout/gameObjects.js +2 -2
  14. package/examples/breakout/index.html +1 -1
  15. package/examples/breakoutTutorial/README.md +46 -43
  16. package/examples/breakoutTutorial/game.js +3 -3
  17. package/examples/breakoutTutorial/index.html +1 -1
  18. package/examples/electron/build.bat +7 -0
  19. package/examples/electron/build.js +124 -0
  20. package/examples/electron/electron.js +35 -0
  21. package/examples/electron/game.js +140 -0
  22. package/examples/electron/index.html +13 -0
  23. package/examples/electron/package.json +12 -0
  24. package/examples/electron/tiles.png +0 -0
  25. package/examples/empty/game.js +1 -0
  26. package/examples/empty/index.html +1 -1
  27. package/examples/htmlMenu/game.js +1 -1
  28. package/examples/htmlMenu/index.html +1 -1
  29. package/examples/index.html +486 -182
  30. package/examples/module/game.js +6 -3
  31. package/examples/module/index.html +1 -1
  32. package/examples/particles/index.html +12 -3
  33. package/examples/platformer/game.js +4 -4
  34. package/examples/platformer/gameCharacter.js +6 -6
  35. package/examples/platformer/gameEffects.js +74 -57
  36. package/examples/platformer/gameLevel.js +61 -70
  37. package/examples/platformer/gameObjects.js +4 -4
  38. package/examples/platformer/index.html +1 -1
  39. package/examples/puzzle/index.html +1 -1
  40. package/examples/shorts/base.html +23 -3
  41. package/examples/shorts/blending.js +9 -5
  42. package/examples/shorts/box2d.js +1 -1
  43. package/examples/shorts/box2dCar.js +9 -13
  44. package/examples/shorts/clock.js +1 -1
  45. package/examples/shorts/colors.js +2 -2
  46. package/examples/shorts/flappyGame.js +52 -0
  47. package/examples/shorts/helloWorld.js +6 -3
  48. package/examples/shorts/hillGlideGame.js +56 -0
  49. package/examples/shorts/landerGame.js +32 -0
  50. package/examples/shorts/maze.js +47 -0
  51. package/examples/shorts/medals.js +42 -0
  52. package/examples/shorts/nineSlice.js +21 -0
  53. package/examples/shorts/piano.js +52 -0
  54. package/examples/shorts/platformer.js +24 -20
  55. package/examples/shorts/{pong.js → pongGame.js} +1 -1
  56. package/examples/shorts/raycasting.js +71 -0
  57. package/examples/shorts/shapes.js +9 -9
  58. package/examples/shorts/slidingPuzzle.js +42 -0
  59. package/examples/shorts/spaceGame.js +56 -0
  60. package/examples/shorts/starfield.js +15 -0
  61. package/examples/shorts/systemFont.js +1 -1
  62. package/examples/shorts/tileLayer.js +3 -5
  63. package/examples/shorts/tiles.png +0 -0
  64. package/examples/shorts/tiltedView.js +8 -7
  65. package/examples/shorts/topDown.js +18 -26
  66. package/examples/shorts/uiSystem.js +5 -7
  67. package/examples/starter/build.bat +6 -1
  68. package/examples/starter/build.js +9 -8
  69. package/examples/starter/game.js +7 -4
  70. package/examples/starter/index.html +23 -13
  71. package/examples/stress/index.html +7 -8
  72. package/examples/style.css +139 -0
  73. package/examples/typescript/build.js +2 -3
  74. package/examples/typescript/game.js +4 -4
  75. package/examples/typescript/game.ts +6 -3
  76. package/examples/typescript/index.html +1 -1
  77. package/examples/uiSystem/game.js +10 -25
  78. package/examples/uiSystem/index.html +1 -1
  79. package/package.json +2 -2
  80. package/plugins/box2d.js +22 -97
  81. package/plugins/drawUtilities.js +132 -0
  82. package/plugins/newgrounds.js +1 -1
  83. package/plugins/pluginExport.js +7 -1
  84. package/plugins/postProcess.js +9 -2
  85. package/plugins/uiSystem.js +155 -67
  86. package/plugins/zzfxm.js +1 -1
  87. package/reference.md +10 -10
  88. package/src/engine.js +56 -30
  89. package/src/engineAudio.js +15 -6
  90. package/src/engineBuild.bat +6 -1
  91. package/src/engineBuild.js +20 -5
  92. package/src/engineDebug.js +55 -28
  93. package/src/engineDraw.js +321 -177
  94. package/src/engineExport.js +27 -9
  95. package/src/engineInput.js +110 -38
  96. package/src/engineMedals.js +4 -4
  97. package/src/engineObject.js +71 -70
  98. package/src/engineParticles.js +33 -9
  99. package/src/engineSettings.js +69 -23
  100. package/src/engineTileLayer.js +312 -153
  101. package/src/engineUtilities.js +187 -135
  102. package/src/engineWebGL.js +70 -39
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * LittleJS WebGL Interface
3
3
  * - All webgl used by the engine is wrapped up here
4
+ * - Will fall back to 2D canvas rendering if webgl is not supported
4
5
  * - For normal stuff you won't need to see or call anything in this file
5
6
  * - For advanced stuff there are helper functions to create shaders, textures, etc
6
7
  * - Can be disabled with glEnable to revert to 2D canvas rendering
7
8
  * - Batches sprite rendering on GPU for incredibly fast performance
8
9
  * - Sprite transform math is done in the shader where possible
9
- * - Supports shadertoy style post processing shaders
10
+ * - Supports shadertoy style post processing shaders via plugin
10
11
  * @namespace WebGL
11
12
  */
12
13
 
@@ -47,9 +48,17 @@ function glInit()
47
48
  glCanvas = document.createElement('canvas');
48
49
  glContext = glCanvas.getContext('webgl2', {antialias:glAntialias});
49
50
 
50
- // some browsers are much faster without copying the gl buffer so we just overlay it instead
51
+ if (!glContext)
52
+ {
53
+ console.warn('WebGL2 not supported, falling back to 2D canvas rendering!');
54
+ glCanvas = glContext = undefined;
55
+ glEnable = false;
56
+ return;
57
+ }
58
+
59
+ // create the webgl canvas
51
60
  const rootElement = mainCanvas.parentElement;
52
- glOverlay && rootElement.appendChild(glCanvas);
61
+ rootElement.appendChild(glCanvas);
53
62
 
54
63
  // setup vertex and fragment shaders
55
64
  glShader = glCreateProgram(
@@ -92,10 +101,11 @@ function glInit()
92
101
  glContext.bufferData(glContext.ARRAY_BUFFER, geometry, glContext.STATIC_DRAW);
93
102
  }
94
103
 
95
- // Setup render each frame, called automatically by engine
104
+ // Setup webgl render each frame, called automatically by engine
105
+ // Also used by tile layer rendering when redrawing tiles
96
106
  function glPreRender()
97
107
  {
98
- if (!glEnable || headlessMode) return;
108
+ if (!glEnable || !glContext) return;
99
109
 
100
110
  // set up the shader and canvas
101
111
  glClearCanvas();
@@ -126,41 +136,51 @@ function glPreRender()
126
136
  initVertexAttribArray('c', glContext.UNSIGNED_BYTE, 1, 4); // color
127
137
  initVertexAttribArray('a', glContext.UNSIGNED_BYTE, 1, 4); // additiveColor
128
138
  initVertexAttribArray('r', glContext.FLOAT, 4, 1); // rotation
129
-
139
+
130
140
  // build the transform matrix
131
141
  const s = vec2(2*cameraScale).divide(mainCanvasSize);
132
- const p = vec2(-1).subtract(cameraPos.multiply(s));
142
+ const rotatedCam = cameraPos.rotate(-cameraAngle);
143
+ const p = vec2(-1).subtract(rotatedCam.multiply(s));
144
+ const ca = Math.cos(cameraAngle);
145
+ const sa = Math.sin(cameraAngle);
133
146
  glContext.uniformMatrix4fv(glContext.getUniformLocation(glShader, 'm'), false,
134
- [
135
- s.x, 0, 0, 0,
136
- 0, s.y, 0, 0,
137
- 1, 1, 1, 1,
138
- p.x, p.y, 0, 0
139
- ]
140
- );
147
+ [
148
+ s.x * ca, s.y * sa, 0, 0,
149
+ -s.x * sa, s.y * ca, 0, 0,
150
+ 1, 1, 1, 0,
151
+ p.x, p.y, 0, 1
152
+ ]);
141
153
  }
142
154
 
143
155
  /** Clear the canvas and setup the viewport
144
156
  * @memberof WebGL */
145
157
  function glClearCanvas()
146
158
  {
159
+ if (!glContext) return;
160
+
147
161
  // clear and set to same size as main canvas
148
- glContext.viewport(0, 0, glCanvas.width=mainCanvas.width, glCanvas.height=mainCanvas.height);
162
+ glContext.viewport(0, 0, glCanvas.width=drawCanvas.width, glCanvas.height=drawCanvas.height);
149
163
  glContext.clear(glContext.COLOR_BUFFER_BIT);
150
164
  }
151
165
 
152
166
  /** Set the WebGl texture, called automatically if using multiple textures
153
167
  * - This may also flush the gl buffer resulting in more draw calls and worse performance
154
168
  * @param {WebGLTexture} texture
169
+ * @param {boolean} wrap - Should the texture wrap or clamp
155
170
  * @memberof WebGL */
156
- function glSetTexture(texture)
171
+ function glSetTexture(texture, wrap=false)
157
172
  {
158
173
  // must flush cache with the old texture to set a new one
159
- if (headlessMode || texture == glActiveTexture)
174
+ if (!glContext || texture == glActiveTexture)
160
175
  return;
161
176
 
162
177
  glFlush();
163
178
  glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture = texture);
179
+
180
+ // set wrap mode
181
+ const wrapMode = wrap ? glContext.REPEAT : glContext.CLAMP_TO_EDGE;
182
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_S, wrapMode);
183
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_T, wrapMode);
164
184
  }
165
185
 
166
186
  /** Compile WebGL shader of the given type, will throw errors if in debug mode
@@ -170,6 +190,8 @@ function glSetTexture(texture)
170
190
  * @memberof WebGL */
171
191
  function glCompileShader(source, type)
172
192
  {
193
+ if (!glContext) return;
194
+
173
195
  // build the shader
174
196
  const shader = glContext.createShader(type);
175
197
  glContext.shaderSource(shader, source);
@@ -188,6 +210,8 @@ function glCompileShader(source, type)
188
210
  * @memberof WebGL */
189
211
  function glCreateProgram(vsSource, fsSource)
190
212
  {
213
+ if (!glContext) return;
214
+
191
215
  // build the program
192
216
  const program = glContext.createProgram();
193
217
  glContext.attachShader(program, glCompileShader(vsSource, glContext.VERTEX_SHADER));
@@ -201,19 +225,19 @@ function glCreateProgram(vsSource, fsSource)
201
225
  }
202
226
 
203
227
  /** Create WebGL texture from an image and init the texture settings
204
- * @param {HTMLImageElement} image
228
+ * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} [image]
205
229
  * @return {WebGLTexture}
206
230
  * @memberof WebGL */
207
231
  function glCreateTexture(image)
208
232
  {
233
+ if (!glContext) return;
234
+
209
235
  // build the texture
210
236
  const texture = glContext.createTexture();
211
237
  glContext.bindTexture(glContext.TEXTURE_2D, texture);
212
238
  if (image && image.width)
213
239
  {
214
240
  glSetTextureData(texture, image);
215
-
216
- const isPowerOfTwo = (value)=> !(value & (value - 1));
217
241
  if (!tilesPixelated && isPowerOfTwo(image.width) && isPowerOfTwo(image.height))
218
242
  {
219
243
  // use mipmap filtering
@@ -237,12 +261,24 @@ function glCreateTexture(image)
237
261
  return texture;
238
262
  }
239
263
 
264
+
265
+ /** Deletes a WebGL texture
266
+ * @param {WebGLTexture} [texture]
267
+ * @memberof WebGL */
268
+ function glDeleteTexture(texture)
269
+ {
270
+ if (!glContext) return;
271
+ glContext.deleteTexture(texture);
272
+ }
273
+
240
274
  /** Set WebGL texture data from an image
241
275
  * @param {WebGLTexture} texture
242
- * @param {HTMLImageElement} image
276
+ * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} image
243
277
  * @memberof WebGL */
244
278
  function glSetTextureData(texture, image)
245
279
  {
280
+ if (!glContext) return;
281
+
246
282
  // build the texture
247
283
  ASSERT(!!image && image.width > 0, 'Invalid image data.');
248
284
  glContext.bindTexture(glContext.TEXTURE_2D, texture);
@@ -253,7 +289,7 @@ function glSetTextureData(texture, image)
253
289
  * @memberof WebGL */
254
290
  function glFlush()
255
291
  {
256
- if (!glInstanceCount) return;
292
+ if (!glEnable || !glContext || !glInstanceCount) return;
257
293
 
258
294
  const destBlend = glBatchAdditive ? glContext.ONE : glContext.ONE_MINUS_SRC_ALPHA;
259
295
  glContext.blendFuncSeparate(glContext.SRC_ALPHA, destBlend, glContext.ONE, destBlend);
@@ -262,25 +298,22 @@ function glFlush()
262
298
  // draw all the sprites in the batch and reset the buffer
263
299
  glContext.bufferSubData(glContext.ARRAY_BUFFER, 0, glPositionData);
264
300
  glContext.drawArraysInstanced(glContext.TRIANGLE_STRIP, 0, 4, glInstanceCount);
265
- if (showWatermark)
301
+ if (debug || showWatermark)
266
302
  drawCount += glInstanceCount;
267
303
  glInstanceCount = 0;
268
304
  glBatchAdditive = glAdditive;
269
305
  }
270
306
 
271
- /** Draw any sprites still in the buffer and copy to main canvas
307
+ /** Flush any sprites still in the buffer and copy to main canvas
272
308
  * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
273
- * @param {boolean} [forceDraw]
274
309
  * @memberof WebGL */
275
- function glCopyToContext(context, forceDraw=false)
310
+ function glCopyToContext(context)
276
311
  {
277
- if (!glEnable || !glInstanceCount && !forceDraw) return;
312
+ if (!glEnable || !glContext)
313
+ return;
278
314
 
279
315
  glFlush();
280
-
281
- // do not draw in overlay mode because the canvas is visible
282
- if (!glOverlay || forceDraw)
283
- context.drawImage(glCanvas, 0, 0);
316
+ context.drawImage(glCanvas, 0, 0);
284
317
  }
285
318
 
286
319
  /** Set anti-aliasing for webgl canvas
@@ -297,18 +330,16 @@ function glSetAntialias(antialias=true)
297
330
  * @param {Number} y
298
331
  * @param {Number} sizeX
299
332
  * @param {Number} sizeY
300
- * @param {Number} angle
301
- * @param {Number} uv0X
302
- * @param {Number} uv0Y
303
- * @param {Number} uv1X
304
- * @param {Number} uv1Y
333
+ * @param {Number} [angle]
334
+ * @param {Number} [uv0X]
335
+ * @param {Number} [uv0Y]
336
+ * @param {Number} [uv1X]
337
+ * @param {Number} [uv1Y]
305
338
  * @param {Number} [rgba=-1] - white is -1
306
339
  * @param {Number} [rgbaAdditive=0] - black is 0
307
340
  * @memberof WebGL */
308
- function glDraw(x, y, sizeX, sizeY, angle, uv0X, uv0Y, uv1X, uv1Y, rgba=-1, rgbaAdditive=0)
341
+ function glDraw(x, y, sizeX, sizeY, angle=0, uv0X=0, uv0Y=0, uv1X=1, uv1Y=1, rgba=-1, rgbaAdditive=0)
309
342
  {
310
- ASSERT(typeof rgba == 'number' && typeof rgbaAdditive == 'number', 'invalid color');
311
-
312
343
  // flush if there is not enough room or if different blend mode
313
344
  if (glInstanceCount >= gl_MAX_INSTANCES || glBatchAdditive != glAdditive)
314
345
  glFlush();