littlejsengine 1.16.2 → 1.17.1

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 (47) hide show
  1. package/dist/littlejs.d.ts +200 -166
  2. package/dist/littlejs.esm.js +1231 -1086
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +888 -735
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +884 -731
  7. package/examples/box2d/gameObjects.js +1 -1
  8. package/examples/breakout/game.js +5 -6
  9. package/examples/electron/index.html +2 -2
  10. package/examples/electron/tiles.png +0 -0
  11. package/examples/htmlMenu/tiles.png +0 -0
  12. package/examples/index.html +1 -1
  13. package/examples/logo.png +0 -0
  14. package/examples/module/tiles.png +0 -0
  15. package/examples/platformer/gameEffects.js +23 -22
  16. package/examples/platformer/gameLevel.js +24 -25
  17. package/examples/shorts/base.html +1 -1
  18. package/examples/shorts/clock.js +3 -3
  19. package/examples/shorts/fontImage.js +4 -3
  20. package/examples/shorts/parallax.js +1 -1
  21. package/examples/shorts/sequencer.js +1 -1
  22. package/examples/shorts/shapes.js +1 -1
  23. package/examples/shorts/texture.js +10 -6
  24. package/examples/shorts/tiles.png +0 -0
  25. package/examples/shorts/tiltedView.js +2 -0
  26. package/examples/starter/index.html +2 -2
  27. package/examples/starter/tiles.png +0 -0
  28. package/examples/typescript/tiles.png +0 -0
  29. package/examples/uiSystem/game.js +1 -1
  30. package/examples/uiSystem/tiles.png +0 -0
  31. package/package.json +1 -1
  32. package/plugins/postProcess.js +47 -28
  33. package/plugins/uiSystem.js +15 -15
  34. package/reference.md +1 -1
  35. package/src/engine.js +174 -174
  36. package/src/engineAudio.js +4 -6
  37. package/src/engineDebug.js +4 -4
  38. package/src/engineDraw.js +179 -122
  39. package/src/engineExport.js +326 -334
  40. package/src/engineFont.png +0 -0
  41. package/src/engineInput.js +14 -20
  42. package/src/engineMath.js +15 -104
  43. package/src/engineObject.js +26 -25
  44. package/src/engineParticles.js +2 -2
  45. package/src/engineTileLayer.js +196 -170
  46. package/src/engineUtilities.js +100 -4
  47. package/src/engineWebGL.js +123 -72
@@ -76,7 +76,7 @@ export function spawnRandomEdges()
76
76
  edgePoints.push(vec2(40,0));
77
77
  for (let i=40, y=0; i--;)
78
78
  edgePoints.push(vec2(i, y=LJS.clamp(y+LJS.rand(-2,2),0,5)));
79
- edgePoints.push(vec2(0,0));
79
+ edgePoints.push(vec2());
80
80
  const o = new LJS.Box2dStaticObject;
81
81
  o.addEdgeList(edgePoints);
82
82
  }
@@ -103,13 +103,12 @@ function gameRender()
103
103
  function gameRenderPost()
104
104
  {
105
105
  // use built in image font for text
106
- const font = new LJS.FontImage;
107
-
108
- font.drawText('Score: ' + score, LJS.cameraPos.add(vec2(0,9.7)), .15, true);
106
+ const font = LJS.engineFontImage;
107
+ font.drawText('Score: ' + score, LJS.cameraPos.add(vec2(0,9.2)), 1);
109
108
  if (!brickCount)
110
- font.drawText('You Win!', LJS.cameraPos.add(vec2(0,-5)), .2, true);
109
+ font.drawText('You Win!', LJS.cameraPos.add(vec2(0,-5)), 2);
111
110
  else if (!ball)
112
- font.drawText('Click to Play', LJS.cameraPos.add(vec2(0,-5)), .2, true);
111
+ font.drawText('Click to Play', LJS.cameraPos.add(vec2(0,-5)), 2);
113
112
  }
114
113
 
115
114
  ///////////////////////////////////////////////////////////////////////////////
@@ -138,7 +137,7 @@ function setupPostProcess()
138
137
 
139
138
  // scan lines
140
139
  const float scanlineScale = 2.;
141
- const float scanlineAlpha = .3;
140
+ const float scanlineAlpha = .6;
142
141
  c *= 1. - scanlineAlpha*cos(p.y*2.*iResolution.y/scanlineScale);
143
142
 
144
143
  {
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.16.2></script>
10
+ <script src=../../dist/littlejs.js?1.17.1></script>
11
11
 
12
12
  <!-- Add your game scripts here -->
13
- <script src=game.js?1.16.2></script>
13
+ <script src=game.js?1.17.1></script>
Binary file
Binary file
@@ -113,7 +113,6 @@ const exampleList =
113
113
  new ExampleInfo('Piano', 'piano.js', 'Interactive piano keyboard', false, 'music, sound, audio, notes, ui, instrument'),
114
114
  new ExampleInfo('Step Sequencer', 'sequencer.js', 'Simple music loop creation tool', false, 'music, sound, audio, notes, ui, instrument'),
115
115
  new ExampleInfo('Music Player', 'musicPlayer.js', 'Music player with audio seeking and drag and drop', false, 'sound, loading, audio, ui'),
116
- new ExampleInfo('WebGL Shader', 'shader.js', 'Full canvas webgl shader', false, 'webgl, visual, effect'),
117
116
  new ExampleInfo('--- MINI GAMES ---'),
118
117
  new ExampleInfo('Pong Game', 'pongGame.js', 'Classic paddle ball bouncing', false, 'objects, collision'),
119
118
  new ExampleInfo('Platformer Game', 'platformer.js', 'Jump and run side view', false, 'objects, gravity, level, tiles, camera'),
@@ -129,6 +128,7 @@ const exampleList =
129
128
  new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin', false, 'objects, mouse'),
130
129
  new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics', false, 'objects, vehicle, suspension, wheels'),
131
130
  new ExampleInfo('Box2d Pool', 'box2dPool.js', 'Billiard table pool game with physics', false, 'objects, game'),
131
+ new ExampleInfo('WebGL Shader', 'shader.js', 'Full canvas webgl shader', false, 'webgl, visual, effect'),
132
132
  new ExampleInfo('Post Processing', 'postProcess.js', 'Shader effects and filters', false, 'webgl, visual, effect'),
133
133
  new ExampleInfo('UI System', 'uiSystem.js', 'Buttons, sliders, and checkboxes', false, 'objects, widgets, interactive'),
134
134
  new ExampleInfo('Nine Slice', 'nineSlice.js', 'Scalable UI panels', false, 'three slice, stretch, corners, text, tiles'),
package/examples/logo.png CHANGED
Binary file
Binary file
@@ -43,8 +43,6 @@ export const persistentParticleDestroyCallback = (particle)=>
43
43
  if (particle.groundObject)
44
44
  {
45
45
  GameLevel.foregroundTileLayer.drawTile(particle.pos, particle.size, particle.tileInfo, particle.color, particle.angle, particle.mirror);
46
- // update WebGL texture
47
- GameLevel.foregroundTileLayer.useWebGL();
48
46
  }
49
47
  }
50
48
 
@@ -74,26 +72,27 @@ export function explosion(pos, radius=3)
74
72
 
75
73
  sound_explosion.play(pos);
76
74
 
77
- // destroy level
78
- for (let x = -radius; x < radius; ++x)
79
75
  {
80
- const h = (radius*radius - x*x)**.5;
81
- for (let y = -h; y <= h; ++y)
82
- destroyTile(pos.add(vec2(x,y)), 0, 0);
83
- }
84
-
85
- // cleanup neighbors
86
- const cleanupRadius = radius + 2;
87
- for (let x = -cleanupRadius; x < cleanupRadius; ++x)
88
- {
89
- const h = (cleanupRadius**2 - x**2)**.5;
90
- for (let y = -h; y < h; ++y)
91
- GameLevel.decorateTile(pos.add(vec2(x,y)).floor());
76
+ // destroy level
77
+ const layer = GameLevel.tileLayers[1];
78
+ layer.redrawStart();
79
+ for (let x = -radius; x < radius; ++x)
80
+ {
81
+ const h = (radius*radius - x*x)**.5;
82
+ for (let y = -h; y <= h; ++y)
83
+ destroyTile(pos.add(vec2(x,y)), 0, 0);
84
+ }
85
+ // cleanup neighbors
86
+ const cleanupRadius = radius + 2;
87
+ for (let x = -cleanupRadius; x < cleanupRadius; ++x)
88
+ {
89
+ const h = (cleanupRadius**2 - x**2)**.5;
90
+ for (let y = -h; y < h; ++y)
91
+ GameLevel.decorateTile(pos.add(vec2(x,y)).floor(), layer);
92
+ }
93
+ layer.redrawEnd();
92
94
  }
93
95
 
94
- // update WebGL texture
95
- GameLevel.foregroundTileLayer.useWebGL();
96
-
97
96
  // kill/push objects
98
97
  LJS.engineObjectsCallback(pos, radius*3, (o)=>
99
98
  {
@@ -165,10 +164,12 @@ export function destroyTile(pos, makeSound = 1, cleanup = 1)
165
164
  // cleanup neighbors and rebuild WebGL
166
165
  if (cleanup)
167
166
  {
167
+ const layer = GameLevel.tileLayers[1];
168
+ layer.redrawStart();
168
169
  for (let i=-1;i<=1;++i)
169
170
  for (let j=-1;j<=1;++j)
170
- GameLevel.decorateTile(pos.add(vec2(i,j)));
171
- layer.useWebGL();
171
+ GameLevel.decorateTile(pos.add(vec2(i,j)), layer);
172
+ layer.redrawEnd();
172
173
  }
173
174
 
174
175
  return true;
@@ -260,7 +261,7 @@ export class ParallaxLayer extends LJS.CanvasLayer
260
261
  this.context.clearRect(0,0,1,h);
261
262
 
262
263
  // make WebGL texture
263
- this.useWebGL();
264
+ this.updateWebGL();
264
265
  }
265
266
 
266
267
  render()
@@ -126,28 +126,25 @@ function loadLevelData()
126
126
  }
127
127
  }
128
128
  }
129
+
130
+ tileLayer.onRedraw = ()=>
131
+ {
132
+ // apply decoration to level tiles
133
+ for (let x=levelSize.x; x--;)
134
+ for (let y=levelSize.y; y--;)
135
+ decorateTile(vec2(x,y), tileLayer);
136
+ }
129
137
  tileLayer.redraw();
130
138
  }
131
-
132
- // apply decoration to all level tiles
133
- const pos = vec2();
134
- const layerCount = tileMapData.layers.length;
135
- for (let layer=layerCount; layer--;)
136
- {
137
- for (pos.x=levelSize.x; pos.x--;)
138
- for (pos.y=levelSize.y; pos.y--;)
139
- decorateTile(pos, layer);
140
- tileLayers[layer].useWebGL();
141
- }
142
139
  }
143
140
 
144
- export function decorateTile(pos, layer=1)
141
+ export function decorateTile(pos, tileLayer)
145
142
  {
146
143
  LJS.ASSERT((pos.x|0) == pos.x && (pos.y|0)== pos.y);
147
- const tileLayer = tileLayers[layer];
148
144
  if (!tileLayer)
149
145
  return;
150
146
 
147
+ const w = tileLayer.tileInfo.size.x;
151
148
  if (tileLayer == foregroundTileLayer)
152
149
  {
153
150
  const tileType = tileLayer.getCollisionData(pos);
@@ -167,12 +164,11 @@ export function decorateTile(pos, layer=1)
167
164
 
168
165
  // make pixel perfect outlines
169
166
  const size = i&1 ? vec2(2, 16) : vec2(16, 2);
170
- tileLayer.context.fillStyle = levelOutlineColor.mutate(.1);
171
167
  const drawPos = pos.scale(16)
172
168
  .add(vec2(i==1?14:0,(i==0?14:0)))
173
169
  .subtract((i&1? vec2(0,8-size.y/2) : vec2(8-size.x/2,0)));
174
- tileLayer.context.fillRect(
175
- drawPos.x, tileLayer.canvas.height - drawPos.y, size.x, -size.y);
170
+ const color = levelOutlineColor.mutate(.1);
171
+ tileLayer.drawLayerRect(drawPos, size, color);
176
172
  }
177
173
  }
178
174
  else
@@ -185,15 +181,18 @@ export function decorateTile(pos, layer=1)
185
181
  const neighborTileDataB = tileLayer.getData(pos.add(vec2().setDirection((i+1)%4))).tile;
186
182
  if (neighborTileDataA > 0 || neighborTileDataB > 0)
187
183
  continue;
188
-
189
- const directionVector = vec2().setAngle((i+.5)*LJS.PI/2, 10).floor();
190
- const drawPos = pos.add(vec2(.5)) // center
191
- .scale(16).add(directionVector).floor(); // direction offset
192
-
193
- // clear rect without any scaling to prevent blur from filtering
194
- const s = 2;
195
- tileLayer.context.clearRect(
196
- drawPos.x - s/2, tileLayer.canvas.height - drawPos.y - s/2, s, s);
184
+
185
+ // get direction of corner
186
+ const directionVector = vec2();
187
+ if (i==0) directionVector.set(w-1,w-1);
188
+ if (i==1) directionVector.set(w-1,1);
189
+ if (i==2) directionVector.set(1,1);
190
+ if (i==3) directionVector.set(1,w-1);
191
+
192
+ // clear rect from corner
193
+ const s = vec2(2);
194
+ const drawPos = pos.scale(w).add(directionVector).subtract(s.scale(.5));
195
+ tileLayer.clearLayerRect(drawPos, s);
197
196
  }
198
197
  }
199
198
  }
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html><meta charset=utf-8><body>
2
- <script src=../../dist/littlejs.js?1.16.2></script>
2
+ <script src=../../dist/littlejs.js?1.17.1></script>
3
3
  <script src=../../dist/box2d.wasm.js></script>
4
4
 
5
5
  <!-- LittleJS Engine Source
@@ -15,7 +15,7 @@ function gameRender()
15
15
  const h = (d.slice(0,2)|0) + m/60;
16
16
 
17
17
  // draw clock hands
18
- drawLine(vec2(0,0), vec2(0,4).rotate(h/12*2*PI), 1);
19
- drawLine(vec2(0,0), vec2(0,6).rotate(m/60*2*PI), .4);
20
- drawLine(vec2(0,0), vec2(0,8).rotate(s/60*2*PI), .1);
18
+ drawLine(vec2(), vec2(0,4).rotate(h/12*2*PI), 1);
19
+ drawLine(vec2(), vec2(0,6).rotate(m/60*2*PI), .4);
20
+ drawLine(vec2(), vec2(0,8).rotate(s/60*2*PI), .1);
21
21
  }
@@ -1,8 +1,8 @@
1
1
  function gameRender()
2
2
  {
3
3
  // draw text with built in engine font image
4
- const font = new FontImage;
5
- font.drawText('Engine Font Test', cameraPos.add(vec2(0,3)), .2);
4
+ const font = engineFontImage
5
+ font.drawText('Engine Font', vec2(0,3), 2);
6
6
 
7
7
  // show every character in the font
8
8
  let s = '';
@@ -12,5 +12,6 @@ function gameRender()
12
12
  s += '\n';
13
13
  s += String.fromCharCode(i);
14
14
  }
15
- font.drawText(s, cameraPos, .1);
15
+
16
+ font.drawText(s, vec2());
16
17
  }
@@ -53,7 +53,7 @@ class ParallaxLayer extends CanvasLayer
53
53
  this.context.clearRect(0,0,1,h);
54
54
 
55
55
  // make WebGL texture
56
- this.useWebGL();
56
+ this.updateWebGL();
57
57
  }
58
58
 
59
59
  render()
@@ -72,7 +72,7 @@ function gameInit()
72
72
  new UISystemPlugin;
73
73
  uiSystem.defaultCornerRadius = 8;
74
74
  uiSystem.defaultShadowColor = BLACK;
75
- canvasClearColor = hsl(0,0,.3);
75
+ canvasClearColor = GRAY;
76
76
 
77
77
  // create sequencer buttons
78
78
  for (let step=stepCount; step--;)
@@ -7,7 +7,7 @@ function gameRender()
7
7
 
8
8
  // polygon shapes
9
9
  drawRectGradient(vec2(-6,0), vec2(5,4), RED, BLUE)
10
- drawRegularPoly(vec2(0,0), vec2(4), 3, PURPLE, .3, WHITE, time);
10
+ drawRegularPoly(vec2(), vec2(4), 3, PURPLE, .3, WHITE, time);
11
11
  let starPath = []
12
12
  for (let i=10; i--;)
13
13
  starPath.push(vec2(0,2*(i%2?.4:1)).rotate(i/10*PI*2));
@@ -1,12 +1,16 @@
1
1
  function gameRender()
2
2
  {
3
3
  // show the full texture
4
- let pos = vec2(0,0); // world position to draw
5
- let size = vec2(15); // world size of the tile
6
- let color = hsl(0,0,1); // color to multiply the tile by
7
- let tilePos = vec2(0,0); // top left corner in pixels
8
- let tileSize = vec2(256); // source size in pixels
4
+ let pos = vec2(); // world position to draw
5
+ let size = vec2(15); // world size of the tile
6
+ let color = hsl(0,0,1); // color to multiply the tile by
7
+ let tilePos = vec2(); // top left corner in pixels
8
+ let tileSize = vec2(256); // source size in pixels
9
9
  let tileInfo = new TileInfo(tilePos, tileSize); // tile info
10
- drawRect(pos, size, GRAY); // draw background
10
+
11
+ // draw background
12
+ drawRect(pos, size, GRAY);
13
+
14
+ // draw the tile
11
15
  drawTile(pos, size, tileInfo, color);
12
16
  }
Binary file
@@ -19,6 +19,8 @@ class Player extends GameObject
19
19
  {
20
20
  update()
21
21
  {
22
+ super.update();
23
+
22
24
  // apply movement controls
23
25
  const moveInput = keyDirection().clampLength(1).scale(.2);
24
26
  this.velocity = this.velocity.add(moveInput);
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.16.2></script>
10
+ <script src=../../dist/littlejs.js?1.17.1></script>
11
11
 
12
12
  <!-- LittleJS Engine Source
13
13
  <script src=../../src/engine.js></script>
@@ -32,4 +32,4 @@
32
32
  -->
33
33
 
34
34
  <!-- Add your game scripts here -->
35
- <script src=game.js?1.16.2></script>
35
+ <script src=game.js?1.17.1></script>
Binary file
Binary file
@@ -38,7 +38,7 @@ function createUI()
38
38
  // setup example menu
39
39
  uiMenu = new LJS.UIObject(vec2(0,500));
40
40
  uiRoot.addChild(uiMenu);
41
- const uiBackground = new LJS.UIObject(vec2(0,0), vec2(450,580));
41
+ const uiBackground = new LJS.UIObject(vec2(), vec2(450,580));
42
42
  uiBackground.lineWidth = 8;
43
43
  uiMenu.addChild(uiBackground);
44
44
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.16.2",
3
+ "version": "1.17.1",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
5
  "main": "dist/littlejs.esm.js",
6
6
  "types": "dist/littlejs.d.ts",
@@ -24,14 +24,16 @@ class PostProcessPlugin
24
24
  {
25
25
  /** Create global post processing shader
26
26
  * @param {string} shaderCode
27
- * @param {boolean} [includeMainCanvas]
28
- * @example
29
- * // create the post process plugin object
30
- * new PostProcessPlugin(shaderCode);
31
- */
32
- constructor(shaderCode, includeMainCanvas=true)
27
+ * @param {boolean} [includeMainCanvas] - combine mainCanvs onto glCanvas
28
+ * @param {boolean} [feedbackTexture] - use glCanvas from previous frame as the texture
29
+ * @example
30
+ * // create the post process plugin object
31
+ * new PostProcessPlugin(shaderCode);
32
+ */
33
+ constructor(shaderCode, includeMainCanvas=false, feedbackTexture=false)
33
34
  {
34
35
  ASSERT(!postProcess, 'Post process already initialized');
36
+ ASSERT(!(includeMainCanvas && feedbackTexture), 'Post process cannot both include main canvas and use feedback texture');
35
37
  postProcess = this;
36
38
 
37
39
  if (!shaderCode) // default shader pass through
@@ -39,9 +41,10 @@ class PostProcessPlugin
39
41
 
40
42
  /** @property {WebGLProgram} - Shader for post processing */
41
43
  this.shader = undefined;
42
-
43
44
  /** @property {WebGLTexture} - Texture for post processing */
44
45
  this.texture = undefined;
46
+ /** @property {WebGLVertexArrayObject} - Vertex array object */
47
+ this.vao = undefined;
45
48
 
46
49
  // setup the post processing plugin
47
50
  initPostProcess();
@@ -50,7 +53,6 @@ class PostProcessPlugin
50
53
  function initPostProcess()
51
54
  {
52
55
  if (headlessMode) return;
53
-
54
56
  if (!glEnable)
55
57
  {
56
58
  console.warn('PostProcessPlugin: WebGL not enabled!');
@@ -61,14 +63,14 @@ class PostProcessPlugin
61
63
  postProcess.texture = glCreateTexture();
62
64
  postProcess.shader = glCreateProgram(
63
65
  '#version 300 es\n' + // specify GLSL ES version
64
- 'precision highp float;'+ // use highp for better accuracy
66
+ 'precision highp float;'+ // use highp for accuracy
65
67
  'in vec2 p;'+ // position
66
68
  'void main(){'+ // shader entry point
67
69
  'gl_Position=vec4(p+p-1.,1,1);'+ // set position
68
70
  '}' // end of shader
69
71
  ,
70
72
  '#version 300 es\n' + // specify GLSL ES version
71
- 'precision highp float;'+ // use highp for better accuracy
73
+ 'precision highp float;'+ // use highp for accuracy
72
74
  'uniform sampler2D iChannel0;'+ // input texture
73
75
  'uniform vec3 iResolution;'+ // size of output texture
74
76
  'uniform float iTime;'+ // time
@@ -79,6 +81,17 @@ class PostProcessPlugin
79
81
  'c.a=1.;'+ // always use full alpha
80
82
  '}' // end of shader
81
83
  );
84
+
85
+ // setup VAO for post processing
86
+ postProcess.vao = glContext.createVertexArray();
87
+ glContext.bindVertexArray(postProcess.vao);
88
+ glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
89
+
90
+ // configure vertex attributes
91
+ const vertexByteStride = 8;
92
+ const pLocation = glContext.getAttribLocation(postProcess.shader, 'p');
93
+ glContext.enableVertexAttribArray(pLocation);
94
+ glContext.vertexAttribPointer(pLocation, 2, glContext.FLOAT, false, vertexByteStride, 0);
82
95
  }
83
96
  function postProcessContextLost()
84
97
  {
@@ -93,14 +106,17 @@ class PostProcessPlugin
93
106
  }
94
107
  function postProcessRender()
95
108
  {
96
- if (headlessMode) return;
97
-
98
- if (!glEnable)
99
- return;
109
+ if (headlessMode || !glEnable) return;
100
110
 
101
111
  // clear out the buffer
102
112
  glFlush();
103
-
113
+
114
+ // setup shader program to draw a quad
115
+ glContext.useProgram(postProcess.shader);
116
+ glContext.bindVertexArray(postProcess.vao);
117
+ glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, true);
118
+ glContext.disable(glContext.BLEND);
119
+
104
120
  // setup texture
105
121
  glContext.activeTexture(glContext.TEXTURE0);
106
122
  glContext.bindTexture(glContext.TEXTURE_2D, postProcess.texture);
@@ -111,29 +127,32 @@ class PostProcessPlugin
111
127
  workCanvas.height = mainCanvasSize.y;
112
128
  glCopyToContext(workContext);
113
129
  workContext.drawImage(mainCanvas, 0, 0);
130
+ mainCanvas.width |= 0
114
131
 
115
132
  // copy work canvas to texture
116
133
  glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, workCanvas);
117
134
  }
118
-
119
- // setup shader program to draw a quad
120
- glContext.useProgram(postProcess.shader);
121
- glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
122
- glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, 1);
123
- glContext.disable(glContext.BLEND);
124
-
125
- // set vertex position attribute
126
- const vertexByteStride = 8;
127
- const pLocation = glContext.getAttribLocation(postProcess.shader, 'p');
128
- glContext.enableVertexAttribArray(pLocation);
129
- glContext.vertexAttribPointer(pLocation, 2, glContext.FLOAT, false, vertexByteStride, 0);
130
-
135
+ else if (!feedbackTexture)
136
+ {
137
+ // copy glCanvas to texture
138
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
139
+ }
140
+
131
141
  // set uniforms and draw
132
142
  const uniformLocation = (name)=>glContext.getUniformLocation(postProcess.shader, name);
133
143
  glContext.uniform1i(uniformLocation('iChannel0'), 0);
134
144
  glContext.uniform1f(uniformLocation('iTime'), time);
135
145
  glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
136
146
  glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, 4);
147
+
148
+ if (feedbackTexture)
149
+ {
150
+ // pass glCanvas back to overlay texture
151
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
152
+ }
153
+
154
+ // force it to set instanced mode
155
+ glSetInstancedMode(true);
137
156
  }
138
157
  }
139
158
  }
@@ -512,7 +512,7 @@ class UISystemPlugin
512
512
  const up = 'ArrowUp', down = 'ArrowDown', left = 'ArrowLeft', right = 'ArrowRight';
513
513
  if (both)
514
514
  {
515
- return keyIsDown(up) || keyIsDown(left) ? -1 :
515
+ return keyIsDown(up) || keyIsDown(left) ? -1 :
516
516
  keyIsDown(down) || keyIsDown(right) ? 1 : 0;
517
517
  }
518
518
  const back = vertical ? up : left;
@@ -543,7 +543,7 @@ class UISystemPlugin
543
543
  * @return {boolean} */
544
544
  getNavigationWasPressed()
545
545
  {
546
- return isUsingGamepad ? gamepadWasPressed(0, gamepadPrimary) :
546
+ return isUsingGamepad ? gamepadWasPressed(0, gamepadPrimary) :
547
547
  keyWasPressed('Space') || keyWasPressed('Enter');
548
548
  }
549
549
 
@@ -591,7 +591,7 @@ class UISystemPlugin
591
591
  buttonYes.textHeight = 40;
592
592
  buttonYes.navigationIndex = 1;
593
593
  buttonYes.hoverColor = hsl(0,1,.5);
594
- buttonYes.onClick = ()=> { closeMenu(); yesCallback && yesCallback(); };
594
+ buttonYes.onClick = ()=> { closeMenu(); yesCallback && yesCallback(); };
595
595
  confirmMenu.addChild(buttonYes);
596
596
 
597
597
  // no button
@@ -621,8 +621,8 @@ class UISystemPlugin
621
621
  class UIObject
622
622
  {
623
623
  /** Create a UIObject
624
- * @param {Vector2} [pos=(0,0)]
625
- * @param {Vector2} [size=(1,1)]
624
+ * @param {Vector2} [pos=vec2()]
625
+ * @param {Vector2} [size=vec2(1)]
626
626
  */
627
627
  constructor(pos=vec2(), size=vec2())
628
628
  {
@@ -637,7 +637,7 @@ class UIObject
637
637
  this.size = size.copy();
638
638
  /** @property {Color} - Color of the object */
639
639
  this.color = uiSystem.defaultColor.copy();
640
- /** @property {Color} - Color of the object when active, uses color if undefined */
640
+ /** @property {Color} - Color of the object when active, uses hoverColor if undefined */
641
641
  this.activeColor = undefined;
642
642
  /** @property {string} - Text for this ui object */
643
643
  this.text = undefined;
@@ -735,10 +735,10 @@ class UIObject
735
735
 
736
736
  // disconnect from parent and destroy children
737
737
  this.destroyed = 1;
738
- this.parent && this.parent.removeChild(this);
738
+ this.parent?.removeChild(this);
739
739
  for (const child of this.children)
740
740
  {
741
- child.parent = 0;
741
+ child.parent = undefined;
742
742
  child.destroy();
743
743
  }
744
744
  }
@@ -834,10 +834,10 @@ class UIObject
834
834
  this.interactive && this.isActiveObject() && !this.disabled ?
835
835
  this.color : this.lineColor;
836
836
  const color = isNavigationObject ? this.hoverColor :
837
- this.disabled ? this.disabledColor :
838
- this.interactive ?
839
- this.isHoverObject() ? this.hoverColor :
840
- this.isActiveObject() ? this.activeColor || this.color :
837
+ this.disabled ? this.disabledColor :
838
+ this.interactive ?
839
+ this.isActiveObject() ? this.activeColor || this.hoverColor :
840
+ this.isHoverObject() ? this.hoverColor :
841
841
  this.color : this.color;
842
842
  const lineWidth = this.lineWidth * (isNavigationObject ? 1.5 : 1);
843
843
 
@@ -849,7 +849,7 @@ class UIObject
849
849
  getTextSize()
850
850
  {
851
851
  return vec2(
852
- this.textWidth || this.textFitScale * this.size.x,
852
+ this.textWidth || this.textFitScale * this.size.x,
853
853
  this.textHeight || this.textFitScale * this.size.y);
854
854
  }
855
855
 
@@ -897,9 +897,9 @@ class UIObject
897
897
  renderDebug(visible=true)
898
898
  {
899
899
  // apply color based on state
900
- const color =
900
+ const color =
901
901
  !visible ? GREEN :
902
- this.isHoverObject() ? YELLOW :
902
+ this.isHoverObject() ? YELLOW :
903
903
  this.disabled ? PURPLE :
904
904
  this.interactive ? RED : BLUE;
905
905
  uiSystem.drawRect(this.pos, this.size, CLEAR_BLACK, 4, color);
package/reference.md CHANGED
@@ -375,7 +375,7 @@ CanvasLayer(position, size) // Create a canvas layer object
375
375
  CanvasLayer.canvas // The canvas used by this layer
376
376
  CanvasLayer.context // The 2D context of the canvas
377
377
  CanvasLayer.getImageData() // Get image data from canvas
378
- CanvasLayer.useWebGL() // Creates or updates WebGL texture
378
+ CanvasLayer.updateWebGL() // Creates or updates WebGL texture
379
379
 
380
380
  // LittleJS Layer System
381
381
  TileLayer(position, size, tileInfo, scale) // Create a tile layer object