littlejsengine 1.10.4 → 1.11.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 (75) hide show
  1. package/LittleJS.zip +0 -0
  2. package/README.md +8 -78
  3. package/dist/littlejs.d.ts +60 -25
  4. package/dist/littlejs.esm.js +164 -63
  5. package/dist/littlejs.esm.min.js +1 -1
  6. package/dist/littlejs.js +160 -62
  7. package/dist/littlejs.min.js +1 -1
  8. package/dist/littlejs.release.js +160 -62
  9. package/examples/box2d/game.js +15 -4
  10. package/examples/box2d/gameObjects.js +10 -9
  11. package/examples/box2d/index.html +5 -5
  12. package/examples/box2d/scenes.js +4 -4
  13. package/examples/box2d/tiles.png +0 -0
  14. package/examples/breakout/index.html +3 -3
  15. package/examples/breakoutTutorial/index.html +2 -2
  16. package/examples/electron/game.js +3 -0
  17. package/examples/electron/index.html +2 -2
  18. package/examples/htmlMenu/index.html +3 -3
  19. package/examples/index.html +10 -3
  20. package/examples/js13k/game.js +3 -0
  21. package/examples/js13k/index.html +13 -13
  22. package/examples/module/game.js +4 -1
  23. package/examples/module/index.html +1 -1
  24. package/examples/particles/index.html +4 -1
  25. package/examples/platformer/game.js +19 -15
  26. package/examples/platformer/gameCharacter.js +3 -3
  27. package/examples/platformer/gameLevel.js +1 -0
  28. package/examples/platformer/index.html +8 -8
  29. package/examples/platformer/tiles.png +0 -0
  30. package/examples/puzzle/game.js +3 -2
  31. package/examples/puzzle/index.html +2 -2
  32. package/examples/starter/game.js +47 -10
  33. package/examples/starter/index.html +13 -13
  34. package/examples/starter/tiles.png +0 -0
  35. package/examples/stress/index.html +1 -1
  36. package/examples/typescript/game.js +2 -0
  37. package/examples/typescript/game.ts +3 -0
  38. package/examples/typescript/index.html +1 -1
  39. package/examples/uiSystem/game.js +23 -16
  40. package/examples/uiSystem/index.html +3 -14
  41. package/package.json +7 -2
  42. package/plugins/postProcess.js +2 -9
  43. package/plugins/uiSystem.js +85 -25
  44. package/reference.md +1 -1
  45. package/shortExamples/engine.html +71 -0
  46. package/shortExamples/index.html +47 -0
  47. package/shortExamples/index.js +0 -0
  48. package/shortExamples/tiles.png +0 -0
  49. package/src/engine.js +14 -12
  50. package/src/engineAudio.js +6 -9
  51. package/src/engineDraw.js +23 -7
  52. package/src/engineExport.js +4 -1
  53. package/src/engineInput.js +7 -3
  54. package/src/engineMedals.js +19 -5
  55. package/src/engineObject.js +8 -5
  56. package/src/engineSettings.js +13 -2
  57. package/src/engineTileLayer.js +9 -8
  58. package/src/engineUtilities.js +59 -10
  59. package/src/engineWebGL.js +1 -1
  60. package/examples/js13k/build/index.html +0 -1
  61. package/examples/js13k/build/index.js +0 -1
  62. package/examples/js13k/build/tiles.png +0 -0
  63. package/examples/js13k/game - Copy.zip +0 -0
  64. package/examples/js13k/game.zip +0 -0
  65. package/examples/starter/build/index.html +0 -2
  66. package/examples/starter/build/index.js +0 -1
  67. package/examples/starter/build/tiles.png +0 -0
  68. package/examples/starter/game.zip +0 -0
  69. package/examples/typescript/build/build/littlejs.esm.js +0 -4327
  70. package/examples/typescript/build/dist/littlejs.esm.js +0 -4425
  71. package/examples/typescript/build/examples/typescript/build.js +0 -24
  72. package/examples/typescript/build/examples/typescript/game.js +0 -100
  73. package/examples/typescript/build/examples/typescript/test/build/littlejs.esm.js +0 -3934
  74. package/examples/typescript/build/examples/typescript/test/examples/typescript/build.js +0 -86
  75. package/examples/typescript/build/examples/typescript/test/examples/typescript/game.js +0 -92
@@ -10,7 +10,7 @@
10
10
  setShowSplashScreen(true);
11
11
 
12
12
  // sound effects
13
- const sound_click = new Sound([1,0]);
13
+ const sound_ui = new Sound([1,0]);
14
14
 
15
15
  // UI system
16
16
  let uiRoot, uiMenu;
@@ -20,7 +20,7 @@ const setMenuVisible =(visible)=> uiMenu.visible = visible;
20
20
  function createUI()
21
21
  {
22
22
  // setup root to attach all ui elements to
23
- uiRoot = new UIObject(vec2(mainCanvasSize.x/2,0));
23
+ uiRoot = new UIObject();
24
24
  const uiInfo = new UIText(vec2(0,50), vec2(1e3, 70),
25
25
  'LittleJS UI System Example\nM = Toggle menu');
26
26
  uiInfo.textColor = WHITE;
@@ -30,54 +30,61 @@ function createUI()
30
30
  // setup example menu
31
31
  uiMenu = new UIObject(vec2(0,450));
32
32
  uiRoot.addChild(uiMenu);
33
- const uiBackground = new UIObject(vec2(0,0), vec2(450,550));
33
+ const uiBackground = new UIObject(vec2(0,0), vec2(450,580));
34
34
  uiMenu.addChild(uiBackground);
35
35
 
36
36
  // example large text
37
- const textTitle = new UIText(vec2(0,-200), vec2(500, 90), 'Test Title');
37
+ const textTitle = new UIText(vec2(0,-220), vec2(500, 90), 'Test Title');
38
38
  uiMenu.addChild(textTitle);
39
39
  textTitle.textColor = RED;
40
40
  textTitle.lineWidth = 4;
41
41
  textTitle.lineColor = BLUE;
42
42
 
43
43
  // example multiline text
44
- const textTest = new UIText(vec2(-60,-120), vec2(300, 50), 'Test Text\nSecond text line.')
44
+ const textTest = new UIText(vec2(-60,-140), vec2(300, 50), 'Test Text\nSecond text line.')
45
45
  uiMenu.addChild(textTest);
46
46
 
47
47
  // example tile image
48
- const tileTest = new UITile(vec2(150,-110), vec2(110), tile(3,128))
48
+ const tileTest = new UITile(vec2(150,-130), vec2(110), tile(3,128))
49
49
  uiMenu.addChild(tileTest);
50
50
 
51
51
  // example checkbox
52
- const checkbox = new UICheckbox(vec2(-160,0), vec2(50));
52
+ const checkbox = new UICheckbox(vec2(-140,-20), vec2(40));
53
53
  uiMenu.addChild(checkbox);
54
- checkbox.onClick = ()=>
54
+ checkbox.onPress = ()=>
55
55
  {
56
56
  checkbox.checked = !checkbox.checked;
57
57
  console.log('Checkbox clicked');
58
- sound_click.play(0,.5,checkbox.checked?4:1);
58
+ sound_ui.play(0,.5,checkbox.checked?4:1);
59
59
  }
60
60
 
61
61
  // text attached to checkbox
62
- const checkboxText = new UIText(vec2(200,0), vec2(300, 50), 'Test Checkbox');
62
+ const checkboxText = new UIText(vec2(170,0), vec2(300, 40), 'Test Checkbox');
63
63
  checkbox.addChild(checkboxText);
64
64
 
65
+ // example scrollbar
66
+ const scrollbar = new UIScrollbar(vec2(0,60), vec2(350, 50));
67
+ uiMenu.addChild(scrollbar);
68
+ scrollbar.onChange = ()=> console.log('New scrollbar value:', scrollbar.value);
69
+ scrollbar.onPress = ()=> sound_ui.play(0,.3,2);
70
+ scrollbar.onRelease = ()=> sound_ui.play(0,.3,4);
71
+
65
72
  // example button
66
- const button1 = new UIButton(vec2(0,90), vec2(350, 70), 'Test Button', RED, 6, CYAN);
73
+ const button1 = new UIButton(vec2(0,140), vec2(350, 50), 'Test Button');
67
74
  uiMenu.addChild(button1);
68
- button1.onClick = ()=>
75
+ button1.onPress = ()=>
69
76
  {
70
77
  console.log('Button 1 clicked');
71
- sound_click.play();
78
+ sound_ui.play();
72
79
  }
73
80
 
74
81
  // exit button
75
- const button2 = new UIButton(vec2(0,190), vec2(350, 70), 'Exit Menu', RED, 6, CYAN);
82
+ const button2 = new UIButton(vec2(0,220), vec2(350, 50), 'Exit Menu');
76
83
  uiMenu.addChild(button2);
77
- button2.onClick = ()=>
84
+ button2.onPress = ()=>
78
85
  {
79
86
  console.log('Button 2 clicked');
80
- sound_click.play(0,.5,2);
87
+ sound_ui.play(0,.5,2);
81
88
  setMenuVisible(false);
82
89
  }
83
90
  }
@@ -7,19 +7,8 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../src/engineDebug.js?1100></script>
11
- <script src=../../src/engineUtilities.js?1100></script>
12
- <script src=../../src/engineSettings.js?1100></script>
13
- <script src=../../src/engineObject.js?1100></script>
14
- <script src=../../src/engineDraw.js?1100></script>
15
- <script src=../../src/engineInput.js?1100></script>
16
- <script src=../../src/engineAudio.js?1100></script>
17
- <script src=../../src/engineTileLayer.js?1100></script>
18
- <script src=../../src/engineParticles.js?1100></script>
19
- <script src=../../src/engineMedals.js?1100></script>
20
- <script src=../../src/engineWebGL.js?1100></script>
21
- <script src=../../src/engine.js?1100></script>
10
+ <script src=../../dist/littlejs.js?1105></script>
22
11
 
23
12
  <!-- Add your game scripts here -->
24
- <script src=../../plugins/uiSystem.js?1100></script>
25
- <script src=game.js?1100></script>
13
+ <script src=../../plugins/uiSystem.js?1105></script>
14
+ <script src=game.js?1105></script>
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.10.4",
3
+ "version": "1.11.1",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
- "main": "dist/littlejs.esm.js",
5
+ "main": "dist/littlejs.esm.min.js",
6
6
  "types": "dist/littlejs.d.ts",
7
+ "exports": {
8
+ "types": "./dist/littlejs.d.ts",
9
+ "production": "./dist/littlejs.esm.min.js",
10
+ "default": "./dist/littlejs.esm.js"
11
+ },
7
12
  "repository": {
8
13
  "type": "git",
9
14
  "url": "git+https://github.com/KilledByAPixel/LittleJS.git"
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * LittleJS Post Processing Plugin
3
3
  * - Supports shadertoy style post processing shaders
4
- * - call glInitPostProcess
4
+ * - call initPostProcess to set it up
5
5
  */
6
6
 
7
7
  'use strict';
@@ -98,11 +98,4 @@ function initPostProcess(shaderCode, includeOverlay=false)
98
98
  glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
99
99
  glContext.drawArrays(gl_TRIANGLE_STRIP, 0, 4);
100
100
  }
101
- }
102
-
103
- export {
104
- initPostProcess,
105
- glPostShader,
106
- glPostTexture,
107
- glPostIncludeOverlay
108
- };
101
+ }
@@ -40,7 +40,7 @@ function initUISystem(context=overlayContext)
40
40
  o.pos = o.localPos.add(o.parent.pos);
41
41
  o.update();
42
42
  for(const c of o.children)
43
- updateObject(c)
43
+ updateObject(c);
44
44
  }
45
45
  uiObjects.forEach(o=> o.parent || updateObject(o));
46
46
  }
@@ -50,9 +50,11 @@ function initUISystem(context=overlayContext)
50
50
  {
51
51
  if (!o.visible)
52
52
  return;
53
+ if (o.parent)
54
+ o.pos = o.localPos.add(o.parent.pos);
53
55
  o.render();
54
56
  for(const c of o.children)
55
- renderObject(c)
57
+ renderObject(c);
56
58
  }
57
59
  uiObjects.forEach(o=> o.parent || renderObject(o));
58
60
  }
@@ -82,21 +84,21 @@ function drawUILine(posA, posB, thickness=uiDefaultLineWidth, color=uiDefaultLin
82
84
  uiContext.stroke();
83
85
  }
84
86
 
85
- function drawUITile(pos, size, tileInfo, color=uiDefaultColor, angle=0, mirror=false, additiveColor=BLACK)
87
+ function drawUITile(pos, size, tileInfo, color=uiDefaultColor, angle=0, mirror=false)
86
88
  {
87
- drawTile(pos, size, tileInfo, color, angle, mirror, additiveColor, false, true, uiContext);
89
+ drawTile(pos, size, tileInfo, color, angle, mirror, BLACK, false, true, uiContext);
88
90
  }
89
91
 
90
92
  function drawUIText(text, pos, size, color=uiDefaultColor, lineWidth=uiDefaultLineWidth, lineColor=uiDefaultLineColor, align='center', font=uiDefaultFont)
91
93
  {
92
- drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, uiContext, size.x);
94
+ drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, size.x, uiContext);
93
95
  }
94
96
 
95
97
  ///////////////////////////////////////////////////////////////////////////////
96
98
 
97
99
  class UIObject
98
100
  {
99
- constructor(localPos, size=vec2())
101
+ constructor(localPos=vec2(), size=vec2())
100
102
  {
101
103
  this.localPos = localPos.copy();
102
104
  this.pos = localPos.copy();
@@ -131,21 +133,28 @@ class UIObject
131
133
  {
132
134
  // track mouse input
133
135
  const mouseWasOver = this.mouseIsOver;
134
- this.mouseIsOver = isOverlapping(this.pos, this.size, mousePosScreen);
135
- if (this.mouseIsOver && !mouseWasOver)
136
- this.onEnter();
137
- if (!this.mouseIsOver && mouseWasOver)
138
- this.onLeave();
136
+ const mouseDown = mouseIsDown(0);
137
+ if (!mouseDown || isTouchDevice)
138
+ {
139
+ this.mouseIsOver = isOverlapping(this.pos, this.size, mousePosScreen);
140
+ if (!mouseDown && isTouchDevice)
141
+ this.mouseIsOver = false;
142
+ if (this.mouseIsOver && !mouseWasOver)
143
+ this.onEnter();
144
+ if (!this.mouseIsOver && mouseWasOver)
145
+ this.onLeave();
146
+ }
139
147
  if (mouseWasPressed(0) && this.mouseIsOver)
140
148
  {
141
149
  this.mouseIsHeld = true;
142
150
  this.onPress();
151
+ if (isTouchDevice)
152
+ this.mouseIsOver = false;
143
153
  }
144
- else if (this.mouseIsHeld && !mouseIsDown(0))
154
+ else if (this.mouseIsHeld && !mouseDown)
145
155
  {
146
156
  this.mouseIsHeld = false;
147
- if (this.mouseIsOver)
148
- this.onClick();
157
+ this.onRelease();
149
158
  }
150
159
  }
151
160
  render()
@@ -155,17 +164,18 @@ class UIObject
155
164
  }
156
165
 
157
166
  // callback functions
158
- onEnter() {}
159
- onLeave() {}
160
- onPress() {}
161
- onClick() {}
167
+ onEnter() {}
168
+ onLeave() {}
169
+ onPress() {}
170
+ onRelease() {}
171
+ onChange() {}
162
172
  }
163
173
 
164
174
  ///////////////////////////////////////////////////////////////////////////////
165
175
 
166
176
  class UIText extends UIObject
167
177
  {
168
- constructor(pos, size, text, align='center', font=fontDefault)
178
+ constructor(pos, size, text='', align='center', font=fontDefault)
169
179
  {
170
180
  super(pos, size);
171
181
 
@@ -184,7 +194,7 @@ class UIText extends UIObject
184
194
 
185
195
  class UITile extends UIObject
186
196
  {
187
- constructor(pos, size, tileInfo, color=WHITE, angle=0, mirror=false, additiveColor=BLACK)
197
+ constructor(pos, size, tileInfo, color=WHITE, angle=0, mirror=false)
188
198
  {
189
199
  super(pos, size);
190
200
 
@@ -192,11 +202,10 @@ class UITile extends UIObject
192
202
  this.color = color;
193
203
  this.angle = angle;
194
204
  this.mirror = mirror;
195
- this.additiveColor = additiveColor;
196
205
  }
197
206
  render()
198
207
  {
199
- drawUITile(this.pos, this.size, this.tileInfo, this.color, this.angle, this.mirror, this.additiveColor);
208
+ drawUITile(this.pos, this.size, this.tileInfo, this.color, this.angle, this.mirror);
200
209
  }
201
210
  }
202
211
 
@@ -215,8 +224,9 @@ class UIButton extends UIObject
215
224
  const lineColor = this.mouseIsHeld ? this.color : this.lineColor;
216
225
  const color = this.mouseIsOver? this.hoverColor : this.color;
217
226
  drawUIRect(this.pos, this.size, color, this.lineWidth, lineColor);
218
- drawTextScreen(this.text, this.pos, this.size.y*.8,
219
- this.textColor, undefined, undefined, this.align, this.font, uiContext);
227
+ const textSize = vec2(this.size.x, this.size.y*.8);
228
+ drawUIText(this.text, this.pos, textSize,
229
+ this.textColor, 0, undefined, this.align, this.font);
220
230
  }
221
231
  }
222
232
 
@@ -229,7 +239,11 @@ class UICheckbox extends UIObject
229
239
  super(pos, size);
230
240
  this.checked = checked;
231
241
  }
232
- onClick() { this.checked = !this.checked; }
242
+ onPress()
243
+ {
244
+ this.checked = !this.checked;
245
+ this.onChange();
246
+ }
233
247
  render()
234
248
  {
235
249
  drawUIRect(this.pos, this.size, this.color, this.lineWidth, this.lineColor);
@@ -241,3 +255,49 @@ class UICheckbox extends UIObject
241
255
  }
242
256
  }
243
257
  }
258
+
259
+ ///////////////////////////////////////////////////////////////////////////////
260
+
261
+ class UIScrollbar extends UIObject
262
+ {
263
+ constructor(pos, size, value=.5, text='')
264
+ {
265
+ super(pos, size);
266
+ this.value = value;
267
+ this.text = text;
268
+ this.color = uiDefaultButtonColor;
269
+ this.handleColor = WHITE;
270
+ }
271
+ update()
272
+ {
273
+ super.update();
274
+ if (this.mouseIsHeld)
275
+ {
276
+ const handleSize = vec2(this.size.y);
277
+ const handleWidth = this.size.x - handleSize.x;
278
+ const p1 = this.pos.x - handleWidth/2;
279
+ const p2 = this.pos.x + handleWidth/2;
280
+ const oldValue = this.value;
281
+ this.value = percent(mousePosScreen.x, p1, p2);
282
+ this.value == oldValue || this.onChange();
283
+ }
284
+ }
285
+ render()
286
+ {
287
+ const lineColor = this.mouseIsHeld ? this.color : this.lineColor;
288
+ const color = this.mouseIsOver? this.hoverColor : this.color;
289
+ drawUIRect(this.pos, this.size, color, this.lineWidth, lineColor);
290
+
291
+ const handleSize = vec2(this.size.y);
292
+ const handleWidth = this.size.x - handleSize.x;
293
+ const p1 = this.pos.x - handleWidth/2;
294
+ const p2 = this.pos.x + handleWidth/2;
295
+ const handlePos = vec2(lerp(this.value, p1, p2), this.pos.y);
296
+ const barColor = this.mouseIsHeld ? this.color : this.handleColor;
297
+ drawUIRect(handlePos, handleSize, barColor, this.lineWidth, this.lineColor);
298
+
299
+ const textSize = vec2(this.size.x, this.size.y*.8);
300
+ drawUIText(this.text, this.pos, textSize,
301
+ this.textColor, 0, undefined, this.align, this.font);
302
+ }
303
+ }
package/reference.md CHANGED
@@ -3,7 +3,7 @@
3
3
  ## This cheat sheet contains all LittleJS essentials.
4
4
  - [LittleJS on GitHub](https://github.com/KilledByAPixel/LittleJS) - Official LittleJS website with more info
5
5
  - [LittleJS Documentation](https://killedbyapixel.github.io/LittleJS/docs) - LittleJS documentation browser
6
- - [Particle Deigner](https://killedbyapixel.github.io/LittleJS/examples/particles) - Editor for LittleJS Particle Systems
6
+ - [Particle System Designer](https://killedbyapixel.github.io/LittleJS/examples/particles) - Editor for LittleJS Particle Systems
7
7
  - [Sound Effect Designer](https://killedbyapixel.github.io/ZzFX) - Tool for creating ZzFX sound effects
8
8
  - [Starter Project](https://killedbyapixel.github.io/LittleJS/examples/starter) - Simple LittleJS demo to start with
9
9
 
@@ -0,0 +1,71 @@
1
+ <!DOCTYPE html><head>
2
+ <title>LittleJS Starter Project</title>
3
+ <meta charset=utf-8>
4
+ <meta name=apple-mobile-web-app-capable content=yes>
5
+ <meta name=mobile-web-app-capable content=yes>
6
+ <link rel=icon type=image/png href=../favicon.png>
7
+ </head><body>
8
+
9
+ <!-- LittleJS Engine -->
10
+ <script src=../src/engineDebug.js?1105></script>
11
+ <script src=../src/engineUtilities.js?1105></script>
12
+ <script src=../src/engineSettings.js?1105></script>
13
+ <script src=../src/engineObject.js?1105></script>
14
+ <script src=../src/engineDraw.js?1105></script>
15
+ <script src=../src/engineInput.js?1105></script>
16
+ <script src=../src/engineAudio.js?1105></script>
17
+ <script src=../src/engineTileLayer.js?1105></script>
18
+ <script src=../src/engineParticles.js?1105></script>
19
+ <script src=../src/engineMedals.js?1105></script>
20
+ <script src=../src/engineWebGL.js?1105></script>
21
+ <script src=../src/engine.js?1105></script>
22
+
23
+ <!-- Add your game scripts here -->
24
+ <script>
25
+
26
+
27
+
28
+
29
+ /*
30
+ Little JS Starter Project
31
+ - A simple starter project for LittleJS
32
+ - Demos all the main engine features
33
+ - Builds to a zip file
34
+ */
35
+
36
+ 'use strict';
37
+
38
+ ///////////////////////////////////////////////////////////////////////////////
39
+ function gameInit()
40
+ {
41
+
42
+ }
43
+
44
+ ///////////////////////////////////////////////////////////////////////////////
45
+ function gameUpdate()
46
+ {
47
+
48
+ }
49
+
50
+ ///////////////////////////////////////////////////////////////////////////////
51
+ function gameUpdatePost()
52
+ {
53
+
54
+ }
55
+
56
+ ///////////////////////////////////////////////////////////////////////////////
57
+ function gameRender()
58
+ {
59
+
60
+ }
61
+
62
+ ///////////////////////////////////////////////////////////////////////////////
63
+ function gameRenderPost()
64
+ {
65
+ }
66
+
67
+
68
+
69
+
70
+
71
+ </script>
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html><head>
2
+ <title>LittleJS Box2D Example</title>
3
+ <meta charset=utf-8>
4
+ <meta name=apple-mobile-web-app-capable content=yes>
5
+ <meta name=mobile-web-app-capable content=yes>
6
+ <link rel=icon type=image/png href=../favicon.png>
7
+ </head><body>
8
+
9
+
10
+ <iframe id=iframe src="engine.html"></iframe>
11
+
12
+ <script>
13
+
14
+
15
+ iframe.onload = function()
16
+ {
17
+ let iframeContent = iframe.contentWindow;
18
+
19
+ iframeContent.eval(`
20
+
21
+
22
+ function gameRender()
23
+ {
24
+ // draw to overlay canvas for hud rendering
25
+ drawTextScreen('TEST',
26
+ vec2(mainCanvasSize.x/2, 70), 80, // position, size
27
+ hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
28
+ }
29
+
30
+ `);
31
+
32
+
33
+
34
+ iframeContent.engineInit(iframeContent.gameInit, iframeContent.gameUpdate, iframeContent.gameUpdatePost, iframeContent.gameRender, iframeContent.gameRenderPost, ['tiles.png']);
35
+
36
+ }
37
+ iframe.src = './engine.html';
38
+
39
+
40
+ </script>
41
+
42
+
43
+ </body>
44
+
45
+
46
+
47
+ </html>
File without changes
Binary file
package/src/engine.js CHANGED
@@ -30,7 +30,7 @@ const engineName = 'LittleJS';
30
30
  * @type {String}
31
31
  * @default
32
32
  * @memberof Engine */
33
- const engineVersion = '1.10.4';
33
+ const engineVersion = '1.11.1';
34
34
 
35
35
  /** Frames per second to update
36
36
  * @type {Number}
@@ -93,6 +93,8 @@ const pluginUpdateList = [], pluginRenderList = [];
93
93
  * @memberof Engine */
94
94
  function engineAddPlugin(updateFunction, renderFunction)
95
95
  {
96
+ ASSERT(!pluginUpdateList.includes(updateFunction));
97
+ ASSERT(!pluginRenderList.includes(renderFunction));
96
98
  updateFunction && pluginUpdateList.push(updateFunction);
97
99
  renderFunction && pluginRenderList.push(renderFunction);
98
100
  }
@@ -101,12 +103,12 @@ function engineAddPlugin(updateFunction, renderFunction)
101
103
  // Main engine functions
102
104
 
103
105
  /** Startup LittleJS engine with your callback functions
104
- * @param {Function} gameInit - Called once after the engine starts up, setup the game
105
- * @param {Function} gameUpdate - Called every frame at 60 frames per second, handle input and update the game state
106
- * @param {Function} gameUpdatePost - Called after physics and objects are updated, setup camera and prepare for render
107
- * @param {Function} gameRender - Called before objects are rendered, draw any background effects that appear behind objects
108
- * @param {Function} gameRenderPost - Called after objects are rendered, draw effects or hud that appear above all objects
109
- * @param {Array} [imageSources=[]] - Image to load
106
+ * @param {Function|function():Promise} gameInit - Called once after the engine starts up
107
+ * @param {Function} gameUpdate - Called every frame before objects are updated
108
+ * @param {Function} gameUpdatePost - Called after physics and objects are updated, even when paused
109
+ * @param {Function} gameRender - Called before objects are rendered, for drawing the background
110
+ * @param {Function} gameRenderPost - Called after objects are rendered, useful for drawing UI
111
+ * @param {Array} [imageSources=[]] - List of images to load
110
112
  * @param {HTMLElement} [rootElement] - Root element to attach to, the document body by default
111
113
  * @memberof Engine */
112
114
  function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement=document.body)
@@ -120,7 +122,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
120
122
  mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
121
123
 
122
124
  // disable smoothing for pixel art
123
- mainContext.imageSmoothingEnabled = !canvasPixelated;
125
+ overlayContext.imageSmoothingEnabled =
126
+ mainContext.imageSmoothingEnabled = !tilesPixelated;
124
127
 
125
128
  // setup gl rendering if enabled
126
129
  glPreRender();
@@ -256,8 +259,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
256
259
 
257
260
  function startEngine()
258
261
  {
259
- gameInit();
260
- engineUpdate();
262
+ new Promise((resolve) => resolve(gameInit())).then(engineUpdate);
261
263
  }
262
264
 
263
265
  if (headlessMode)
@@ -272,9 +274,9 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
272
274
  'width:100vw;height:100vh;' + // fill the window
273
275
  'display:flex;' + // use flexbox
274
276
  'align-items:center;' + // horizontal center
275
- (canvasPixelated ? 'image-rendering:pixelated;' : '') + // pixel art
276
277
  'justify-content:center;' + // vertical center
277
278
  'background:#000;' + // set background color
279
+ (canvasPixelated ? 'image-rendering:pixelated;' : '') + // pixel art
278
280
  'user-select:none;' + // prevent hold to select
279
281
  '-webkit-user-select:none;' + // compatibility for ios
280
282
  (!touchInputEnable ? '' : // no touch css setttings
@@ -610,4 +612,4 @@ function drawEngineSplashScreen(t)
610
612
  }
611
613
 
612
614
  x.restore();
613
- }
615
+ }
@@ -14,7 +14,7 @@
14
14
  /** Audio context used by the engine
15
15
  * @type {AudioContext}
16
16
  * @memberof Audio */
17
- let audioContext;
17
+ let audioContext = new AudioContext;
18
18
 
19
19
  /** Master gain node for all audio to pass through
20
20
  * @type {GainNode}
@@ -25,14 +25,10 @@ function audioInit()
25
25
  {
26
26
  if (!soundEnable || headlessMode) return;
27
27
 
28
- // create audio context
29
- audioContext = new AudioContext;
30
-
31
- // create and connect gain node
32
28
  // (createGain is more widely spported then GainNode construtor)
33
29
  audioGainNode = audioContext.createGain();
34
30
  audioGainNode.connect(audioContext.destination);
35
- setSoundVolume(soundVolume); // update gain volume
31
+ audioGainNode.gain.value = soundVolume; // set starting value
36
32
  }
37
33
 
38
34
  ///////////////////////////////////////////////////////////////////////////////
@@ -72,7 +68,7 @@ class Sound
72
68
  {
73
69
  // generate zzfx sound now for fast playback
74
70
  const defaultRandomness = .05;
75
- this.randomness = zzfxSound[1] || defaultRandomness;
71
+ this.randomness = zzfxSound[1] != undefined ? zzfxSound[1] : defaultRandomness;
76
72
  zzfxSound[1] = 0; // generate without randomness
77
73
  this.sampleChannels = [zzfxG(...zzfxSound)];
78
74
  this.sampleRate = zzfxR;
@@ -114,10 +110,11 @@ class Sound
114
110
  // play the sound
115
111
  const playbackRate = pitch + pitch * this.randomness*randomnessScale*rand(-1,1);
116
112
  this.gainNode = audioContext.createGain();
117
- return this.source = playSamples(this.sampleChannels, volume, playbackRate, pan, loop, this.sampleRate, this.gainNode);
113
+ this.source = playSamples(this.sampleChannels, volume, playbackRate, pan, loop, this.sampleRate, this.gainNode);
114
+ return this.source;
118
115
  }
119
116
 
120
- /** Set the sound volume
117
+ /** Set the sound volume of the most recently played instance of this sound
121
118
  * @param {Number} [volume] - How much to scale volume by
122
119
  */
123
120
  setVolume(volume=1)