littlejsengine 1.14.16 → 1.14.23

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 (62) hide show
  1. package/dist/littlejs.d.ts +173 -50
  2. package/dist/littlejs.esm.js +892 -419
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +879 -419
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +854 -420
  7. package/examples/box2d/game.js +3 -2
  8. package/examples/box2d/tiles.png +0 -0
  9. package/examples/breakout/game.js +5 -5
  10. package/examples/electron/game.js +1 -41
  11. package/examples/electron/index.html +2 -2
  12. package/examples/htmlMenu/game.js +1 -1
  13. package/examples/index.html +69 -55
  14. package/examples/module/game.js +6 -8
  15. package/examples/particles/index.html +6 -9
  16. package/examples/platformer/gameCharacter.js +1 -1
  17. package/examples/platformer/gameEffects.js +8 -3
  18. package/examples/platformer/gameObjects.js +3 -3
  19. package/examples/shorts/animation.js +2 -2
  20. package/examples/shorts/base.html +4 -1
  21. package/examples/shorts/cameraDrag.js +22 -0
  22. package/examples/shorts/debugDraw.js +38 -0
  23. package/examples/shorts/fps.js +90 -0
  24. package/examples/shorts/helloWorld.js +1 -1
  25. package/examples/shorts/hillGlideGame.js +1 -1
  26. package/examples/shorts/landerGame.js +1 -1
  27. package/examples/shorts/musicPlayer.js +1 -0
  28. package/examples/shorts/parallax.js +1 -1
  29. package/examples/shorts/postProcess.js +1 -1
  30. package/examples/shorts/sequencer.js +5 -5
  31. package/examples/shorts/shader.js +29 -0
  32. package/examples/shorts/spaceGame.js +1 -1
  33. package/examples/shorts/spriteAtlas.js +6 -6
  34. package/examples/shorts/starfield.js +1 -1
  35. package/examples/shorts/tileLayer.js +1 -1
  36. package/examples/shorts/tileRaycast.js +39 -0
  37. package/examples/shorts/tiles.png +0 -0
  38. package/examples/shorts/tiltedView.js +14 -6
  39. package/examples/shorts/topDown.js +1 -1
  40. package/examples/starter/game.js +6 -8
  41. package/examples/starter/index.html +2 -2
  42. package/examples/style.css +1 -0
  43. package/examples/typescript/game.js +5 -4
  44. package/examples/typescript/game.ts +5 -7
  45. package/examples/uiSystem/game.js +3 -2
  46. package/package.json +1 -1
  47. package/plugins/postProcess.js +71 -51
  48. package/plugins/uiSystem.js +76 -23
  49. package/src/engine.js +30 -16
  50. package/src/engineAudio.js +33 -23
  51. package/src/engineDebug.js +27 -0
  52. package/src/engineDraw.js +103 -49
  53. package/src/engineExport.js +13 -0
  54. package/src/engineInput.js +14 -16
  55. package/src/engineObject.js +31 -6
  56. package/src/engineParticles.js +37 -16
  57. package/src/engineRelease.js +2 -1
  58. package/src/engineSettings.js +20 -1
  59. package/src/engineTileLayer.js +89 -94
  60. package/src/engineUtilities.js +206 -58
  61. package/src/engineWebGL.js +145 -69
  62. package/examples/shorts/raycasting.js +0 -79
@@ -29,7 +29,7 @@ let glContext;
29
29
  let glAntialias = true;
30
30
 
31
31
  // WebGL internal variables not exposed to documentation
32
- let glShader, glPolyShader, glPolyMode, glAdditive, glBatchAdditive, glActiveTexture, glArrayBuffer, glGeometryBuffer, glPositionData, glColorData, glBatchCount;
32
+ let glShader, glPolyShader, glPolyMode, glAdditive, glBatchAdditive, glActiveTexture, glArrayBuffer, glGeometryBuffer, glPositionData, glColorData, glBatchCount, glTextureInfos, glCanBeEnabled = true;
33
33
 
34
34
  // WebGL internal constants
35
35
  const gl_ARRAY_BUFFER_SIZE = 5e5;
@@ -45,7 +45,14 @@ const gl_MAX_POLY_VERTEXES = gl_ARRAY_BUFFER_SIZE / gl_POLY_VERTEX_BYTE_STRIDE |
45
45
  // Initialize WebGL, called automatically by the engine
46
46
  function glInit()
47
47
  {
48
- if (!glEnable || headlessMode) return;
48
+ // keep set of texture infos so they can be restored if context is lost
49
+ glTextureInfos = new Set;
50
+
51
+ if (!glEnable || headlessMode)
52
+ {
53
+ glCanBeEnabled = false;
54
+ return;
55
+ }
49
56
 
50
57
  // create the canvas and textures
51
58
  glCanvas = document.createElement('canvas');
@@ -56,74 +63,108 @@ function glInit()
56
63
  console.warn('WebGL2 not supported, falling back to 2D canvas rendering!');
57
64
  glCanvas = glContext = undefined;
58
65
  glEnable = false;
66
+ glCanBeEnabled = false;
59
67
  return;
60
68
  }
61
69
 
62
- // create the WebGL canvas
70
+ // attach the WebGL canvas
63
71
  const rootElement = mainCanvas.parentElement;
64
72
  rootElement.appendChild(glCanvas);
73
+
74
+ // startup webgl
75
+ initWebGL();
65
76
 
66
- // setup instanced rendering shader program
67
- glShader = glCreateProgram(
68
- '#version 300 es\n' + // specify GLSL ES version
69
- 'precision highp float;'+ // use highp for better accuracy
70
- 'uniform mat4 m;'+ // transform matrix
71
- 'in vec2 g;'+ // in: geometry
72
- 'in vec4 p,u,c,a;'+ // in: position/size, uvs, color, additiveColor
73
- 'in float r;'+ // in: rotation
74
- 'out vec2 v;'+ // out: uv
75
- 'out vec4 d,e;'+ // out: color, additiveColor
76
- 'void main(){'+ // shader entry point
77
- 'vec2 s=(g-.5)*p.zw;'+ // get size offset
78
- 'gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);'+ // transform position
79
- 'v=mix(u.xw,u.zy,g);'+ // pass uv to fragment shader
80
- 'd=c;e=a;'+ // pass colors to fragment shader
81
- '}' // end of shader
82
- ,
83
- '#version 300 es\n' + // specify GLSL ES version
84
- 'precision highp float;'+ // use highp for better accuracy
85
- 'uniform sampler2D s;'+ // texture
86
- 'in vec2 v;'+ // in: uv
87
- 'in vec4 d,e;'+ // in: color, additiveColor
88
- 'out vec4 c;'+ // out: color
89
- 'void main(){'+ // shader entry point
90
- 'c=texture(s,v)*d+e;'+ // modulate texture by color plus additive
91
- '}' // end of shader
92
- );
93
-
94
- // setup poly rendering shaders
95
- glPolyShader = glCreateProgram(
96
- '#version 300 es\n' + // specify GLSL ES version
97
- 'precision highp float;'+ // use highp for better accuracy
98
- 'uniform mat4 m;'+ // transform matrix
99
- 'in vec2 p;'+ // in: position
100
- 'in vec4 c;'+ // in: color
101
- 'out vec4 d;'+ // out: color
102
- 'void main(){'+ // shader entry point
103
- 'gl_Position=m*vec4(p,1,1);'+ // transform position
104
- 'd=c;'+ // pass color to fragment shader
105
- '}' // end of shader
106
- ,
107
- '#version 300 es\n' + // specify GLSL ES version
108
- 'precision highp float;'+ // use highp for better accuracy
109
- 'in vec4 d;'+ // in: color
110
- 'out vec4 c;'+ // out: color
111
- 'void main(){'+ // shader entry point
112
- 'c=d;'+ // set color
113
- '}' // end of shader
114
- );
115
-
116
- // init buffers
117
- const glInstanceData = new ArrayBuffer(gl_ARRAY_BUFFER_SIZE);
118
- glPositionData = new Float32Array(glInstanceData);
119
- glColorData = new Uint32Array(glInstanceData);
120
- glArrayBuffer = glContext.createBuffer();
121
- glGeometryBuffer = glContext.createBuffer();
122
-
123
- // create the geometry buffer, triangle strip square
124
- const geometry = new Float32Array([glBatchCount=0,0,1,0,0,1,1,1]);
125
- glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
126
- glContext.bufferData(glContext.ARRAY_BUFFER, geometry, glContext.STATIC_DRAW);
77
+ // setup context lost and restore handlers
78
+ glCanvas.addEventListener('webglcontextlost', (e)=>
79
+ {
80
+ glEnable = false; // disable WebGL rendering
81
+ glCanvas.style.display = 'none'; // hide the gl canvas
82
+ e.preventDefault(); // prevent default to allow restoration
83
+ LOG('WebGL context lost! Switching to Canvas2d rendering.');
84
+
85
+ // remove WebGL textures
86
+ for (const info of glTextureInfos)
87
+ info.glTexture = undefined;
88
+ glActiveTexture = undefined;
89
+ pluginList.forEach(plugin=>plugin.glContextLost?.());
90
+ });
91
+ glCanvas.addEventListener('webglcontextrestored', ()=>
92
+ {
93
+ glEnable = true; // re-enable WebGL rendering
94
+ glCanvas.style.display = ''; // show the gl canvas
95
+ LOG('WebGL context restored, reinitializing...');
96
+
97
+ // reinit WebGL and restore textures
98
+ initWebGL();
99
+ for (const info of glTextureInfos)
100
+ info.glTexture = glCreateTexture(info.image);
101
+ pluginList.forEach(plugin=>plugin.glContextRestored?.());
102
+ });
103
+
104
+ function initWebGL()
105
+ {
106
+ // setup instanced rendering shader program
107
+ glShader = glCreateProgram(
108
+ '#version 300 es\n' + // specify GLSL ES version
109
+ 'precision highp float;'+ // use highp for better accuracy
110
+ 'uniform mat4 m;'+ // transform matrix
111
+ 'in vec2 g;'+ // in: geometry
112
+ 'in vec4 p,u,c,a;'+ // in: position/size, uvs, color, additiveColor
113
+ 'in float r;'+ // in: rotation
114
+ 'out vec2 v;'+ // out: uv
115
+ 'out vec4 d,e;'+ // out: color, additiveColor
116
+ 'void main(){'+ // shader entry point
117
+ 'vec2 s=(g-.5)*p.zw;'+ // get size offset
118
+ 'gl_Position=m*vec4(p.xy+s*cos(r)-vec2(-s.y,s)*sin(r),1,1);'+ // transform position
119
+ 'v=mix(u.xw,u.zy,g);'+ // pass uv to fragment shader
120
+ 'd=c;e=a;'+ // pass colors to fragment shader
121
+ '}' // end of shader
122
+ ,
123
+ '#version 300 es\n' + // specify GLSL ES version
124
+ 'precision highp float;'+ // use highp for better accuracy
125
+ 'uniform sampler2D s;'+ // texture
126
+ 'in vec2 v;'+ // in: uv
127
+ 'in vec4 d,e;'+ // in: color, additiveColor
128
+ 'out vec4 c;'+ // out: color
129
+ 'void main(){'+ // shader entry point
130
+ 'c=texture(s,v)*d+e;'+ // modulate texture by color plus additive
131
+ '}' // end of shader
132
+ );
133
+
134
+ // setup poly rendering shaders
135
+ glPolyShader = glCreateProgram(
136
+ '#version 300 es\n' + // specify GLSL ES version
137
+ 'precision highp float;'+ // use highp for better accuracy
138
+ 'uniform mat4 m;'+ // transform matrix
139
+ 'in vec2 p;'+ // in: position
140
+ 'in vec4 c;'+ // in: color
141
+ 'out vec4 d;'+ // out: color
142
+ 'void main(){'+ // shader entry point
143
+ 'gl_Position=m*vec4(p,1,1);'+ // transform position
144
+ 'd=c;'+ // pass color to fragment shader
145
+ '}' // end of shader
146
+ ,
147
+ '#version 300 es\n' + // specify GLSL ES version
148
+ 'precision highp float;'+ // use highp for better accuracy
149
+ 'in vec4 d;'+ // in: color
150
+ 'out vec4 c;'+ // out: color
151
+ 'void main(){'+ // shader entry point
152
+ 'c=d;'+ // set color
153
+ '}' // end of shader
154
+ );
155
+
156
+ // init buffers
157
+ const glInstanceData = new ArrayBuffer(gl_ARRAY_BUFFER_SIZE);
158
+ glPositionData = new Float32Array(glInstanceData);
159
+ glColorData = new Uint32Array(glInstanceData);
160
+ glArrayBuffer = glContext.createBuffer();
161
+ glGeometryBuffer = glContext.createBuffer();
162
+
163
+ // create the geometry buffer, triangle strip square
164
+ const geometry = new Float32Array([glBatchCount=0,0,1,0,0,1,1,1]);
165
+ glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
166
+ glContext.bufferData(glContext.ARRAY_BUFFER, geometry, glContext.STATIC_DRAW);
167
+ }
127
168
  }
128
169
 
129
170
  function glSetInstancedMode()
@@ -201,8 +242,8 @@ function glPreRender()
201
242
  const s = vec2(2*cameraScale).divide(mainCanvasSize);
202
243
  const rotatedCam = cameraPos.rotate(-cameraAngle);
203
244
  const p = vec2(-1).subtract(rotatedCam.multiply(s));
204
- const ca = Math.cos(cameraAngle);
205
- const sa = Math.sin(cameraAngle);
245
+ const ca = cos(cameraAngle);
246
+ const sa = sin(cameraAngle);
206
247
  const transform = [
207
248
  s.x * ca, s.y * sa, 0, 0,
208
249
  -s.x * sa, s.y * ca, 0, 0,
@@ -230,7 +271,7 @@ function glPreRender()
230
271
  // start with additive blending off
231
272
  glAdditive = glBatchAdditive = false;
232
273
 
233
- // force it to enter instanced mode
274
+ // force it to set instanced mode by first setting poly mode true
234
275
  glPolyMode = true;
235
276
  glSetInstancedMode();
236
277
  }
@@ -371,6 +412,41 @@ function glSetTextureData(texture, image)
371
412
  glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture); // rebind active texture
372
413
  }
373
414
 
415
+ /** Tells WebGL to create or update the glTexture and start tracking it
416
+ * @param {TextureInfo} textureInfo
417
+ * @memberof WebGL */
418
+ function glRegisterTextureInfo(textureInfo)
419
+ {
420
+ if (headlessMode) return;
421
+
422
+ // add texture info to tracking list even if gl is not enabled
423
+ glTextureInfos.add(textureInfo);
424
+
425
+ if (!glContext) return;
426
+
427
+ // create or set the texture data
428
+ if (textureInfo.glTexture)
429
+ glSetTextureData(textureInfo.glTexture, textureInfo.image);
430
+ else
431
+ textureInfo.glTexture = glCreateTexture(textureInfo.image);
432
+ }
433
+
434
+ /** Tells WebGL to destroy the glTexture and stop tracking it
435
+ * @param {TextureInfo} textureInfo
436
+ * @memberof WebGL */
437
+ function glUnregisterTextureInfo(textureInfo)
438
+ {
439
+ if (headlessMode) return;
440
+
441
+ // delete texture info from tracking list even if gl is not enabled
442
+ glTextureInfos.delete(textureInfo);
443
+
444
+ // unset and destroy the texture
445
+ const glTexture = textureInfo.glTexture;
446
+ textureInfo.glTexture = undefined;
447
+ glDeleteTexture(glTexture);
448
+ }
449
+
374
450
  /** Draw all sprites and clear out the buffer, called automatically by the system whenever necessary
375
451
  * @memberof WebGL */
376
452
  function glFlush()
@@ -472,8 +548,8 @@ function glDrawPointsTransform(points, rgba, x, y, sx, sy, angle, tristrip=true)
472
548
  // transform the point
473
549
  const px = p.x*sx;
474
550
  const py = p.y*sy;
475
- const sa = Math.sin(-angle);
476
- const ca = Math.cos(-angle);
551
+ const sa = sin(-angle);
552
+ const ca = cos(-angle);
477
553
  pointsOut.push(vec2(x + ca*px - sa*py, y + sa*px + ca*py));
478
554
  }
479
555
  const drawPoints = tristrip ? glPolyStrip(pointsOut) : pointsOut;
@@ -1,79 +0,0 @@
1
- let playerPos = vec2(), playerAngle = 0;
2
-
3
- // a simple function to generate a level
4
- const levelTest = (X,Y)=> ((X|0)**3&(Y|0)**2)%30>5;
5
-
6
- // cast a ray and return the distance to the first wall hit (0-1)
7
- function raycast(pos, angle)
8
- {
9
- const maxDistance = 40, delta = .05;
10
- const rayX = delta*Math.sin(angle);
11
- const rayY = delta*Math.cos(angle);
12
- let posX = pos.x, posY = pos.y;
13
- for (let distance = 0; distance < maxDistance; distance += delta)
14
- {
15
- if (levelTest(posX, posY))
16
- return distance/maxDistance;
17
- posX += rayX;
18
- posY += rayY;
19
- }
20
- return 1;
21
- }
22
-
23
- function gameUpdate()
24
- {
25
- // update camera angle with mouse pointer lock
26
- if (mouseWasPressed(0))
27
- pointerLockRequest();
28
- if (keyWasPressed('Escape'))
29
- pointerLockExit()
30
- if (pointerLockIsActive() || isTouchDevice)
31
- playerAngle += mouseDelta.x * .003;
32
-
33
- // update player movement, prevent walking through walls
34
- let velocity = keyDirection();
35
- if (velocity.y && mouseIsDown(0))
36
- velocity.y = 1; // forward movement with mouse
37
- velocity = velocity.rotate(playerAngle).scale(.1);
38
- const newPos = playerPos.add(velocity);
39
- if (!levelTest(newPos.x, newPos.y))
40
- playerPos = newPos;
41
- }
42
-
43
- function gameRender()
44
- {
45
- {
46
- // draw horizontal slizes to create floor and ceiling
47
- const h = 9;
48
- let pos = vec2(), size = vec2(39, .15), color = rgb();
49
- for (let y=-h; y<h; y+=.1)
50
- {
51
- const p = 1.01-abs(y/h)
52
- pos.y = y;
53
- color.setHSLA(.1, y>0?0:.5, .7-p*.7);
54
- drawRect(pos, size, color);
55
- }
56
- }
57
- {
58
- // draw vertical slices to create the walls
59
- const w = 20;
60
- const pos = vec2(), size = vec2(.15), color = rgb();
61
- for (let x=-w; x<w; x+=.1)
62
- {
63
- const p = raycast(playerPos, playerAngle + x/w);
64
- pos.x = x;
65
- size.y = .4/p;
66
- color.setHSLA(.6, .5, .7-p*.7);
67
- drawRect(pos, size, color);
68
- }
69
- }
70
- // draw instructions and pointer lock status
71
- const instructions = pointerLockIsActive() ?
72
- 'Mouse Control Active - ESC To Exit' :
73
- 'Click To Enable Mouse Control';
74
- const textPos = vec2(mainCanvasSize.x/2, 50);
75
- const textSize = 24;
76
- const textColor = pointerLockIsActive() ? GREEN : WHITE;
77
- if (!isTouchDevice)
78
- drawTextScreen(instructions, textPos, textSize, textColor);
79
- }