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
@@ -14,6 +14,7 @@ export
14
14
  time,
15
15
  timeReal,
16
16
  paused,
17
+ getPaused,
17
18
  setPaused,
18
19
  engineInit,
19
20
  engineObjectsUpdate,
@@ -49,10 +50,13 @@ export
49
50
 
50
51
  // Settings
51
52
  cameraPos,
53
+ cameraAngle,
52
54
  cameraScale,
55
+ canvasColorTiles,
53
56
  canvasMaxSize,
54
57
  canvasFixedSize,
55
58
  canvasPixelated,
59
+ overlayCanvasPixelated,
56
60
  tilesPixelated,
57
61
  fontDefault,
58
62
  showSplashScreen,
@@ -63,13 +67,12 @@ export
63
67
  objectDefaultMass,
64
68
  objectDefaultDamping,
65
69
  objectDefaultAngleDamping,
66
- objectDefaultElasticity,
70
+ objectDefaultRestitution,
67
71
  objectDefaultFriction,
68
72
  objectMaxSpeed,
69
73
  gravity,
70
74
  particleEmitRateScale,
71
75
  glEnable,
72
- glOverlay,
73
76
  gamepadsEnable,
74
77
  gamepadDirectionEmulateStick,
75
78
  inputWASDEmulateDirection,
@@ -88,23 +91,25 @@ export
88
91
 
89
92
  // Setters for globals
90
93
  setCameraPos,
94
+ setCameraAngle,
91
95
  setCameraScale,
96
+ setCanvasColorTiles,
92
97
  setCanvasMaxSize,
93
98
  setCanvasFixedSize,
94
99
  setCanvasPixelated,
100
+ setOverlayCanvasPixelated,
95
101
  setTilesPixelated,
96
102
  setFontDefault,
97
103
  setShowSplashScreen,
98
104
  setHeadlessMode,
99
- setGlEnable,
100
- setGlOverlay,
105
+ setGLEnable,
101
106
  setTileSizeDefault,
102
107
  setTileFixBleedScale,
103
108
  setEnablePhysicsSolver,
104
109
  setObjectDefaultMass,
105
110
  setObjectDefaultDamping,
106
111
  setObjectDefaultAngleDamping,
107
- setObjectDefaultElasticity,
112
+ setObjectDefaultRestitution,
108
113
  setObjectDefaultFriction,
109
114
  setObjectMaxSpeed,
110
115
  setGravity,
@@ -156,7 +161,7 @@ export
156
161
  randInt,
157
162
  randSign,
158
163
  randInCircle,
159
- randVector,
164
+ randVec2,
160
165
  randColor,
161
166
 
162
167
  // Utility Classes
@@ -168,10 +173,14 @@ export
168
173
  rgb,
169
174
  hsl,
170
175
  isColor,
176
+ isVector2,
177
+ isNumber,
171
178
 
172
179
  // Default Colors
173
180
  WHITE,
181
+ CLEAR_WHITE,
174
182
  BLACK,
183
+ CLEAR_BLACK,
175
184
  GRAY,
176
185
  RED,
177
186
  ORANGE,
@@ -220,6 +229,7 @@ export
220
229
  glCopyToContext,
221
230
  glCreateProgram,
222
231
  glCreateTexture,
232
+ glDeleteTexture,
223
233
  glSetTextureData,
224
234
  glDraw,
225
235
  glFlush,
@@ -242,12 +252,15 @@ export
242
252
  keyWasPressed,
243
253
  keyWasReleased,
244
254
  keyDirection,
245
- clearInput,
255
+ inputClear,
256
+ inputClearKey,
246
257
  mouseIsDown,
247
258
  mouseWasPressed,
248
259
  mouseWasReleased,
249
260
  mousePos,
250
261
  mousePosScreen,
262
+ mouseDelta,
263
+ mouseDeltaScreen,
251
264
  mouseWheel,
252
265
  isUsingGamepad,
253
266
  inputPreventDefault,
@@ -260,6 +273,9 @@ export
260
273
  vibrate,
261
274
  vibrateStop,
262
275
  isTouchDevice,
276
+ pointerLockRequest,
277
+ pointerLockExit,
278
+ pointerLockIsActive,
263
279
 
264
280
  // Audio
265
281
  Sound,
@@ -279,10 +295,12 @@ export
279
295
 
280
296
  // Tiles
281
297
  tileCollisionLayers,
282
- getTileCollisionData,
298
+ tileCollisionGetData,
283
299
  tileCollisionTest,
284
300
  tileCollisionRaycast,
301
+ tileCollisionLoad,
285
302
  TileLayerData,
303
+ CanvasLayer,
286
304
  TileLayer,
287
305
  TileCollisionLayer,
288
306
 
@@ -295,4 +313,4 @@ export
295
313
  medalsPreventUnlock,
296
314
  medalsInit,
297
315
  Medal,
298
- };
316
+ };
@@ -17,7 +17,8 @@
17
17
  * @memberof Input */
18
18
  function keyIsDown(key, device=0)
19
19
  {
20
- ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
20
+ ASSERT(key !== undefined, 'key is undefined');
21
+ ASSERT(device > 0 || typeof key != 'number' || key < 3, 'use code string for keyboard');
21
22
  return inputData[device] && !!(inputData[device][key] & 1);
22
23
  }
23
24
 
@@ -28,7 +29,8 @@ function keyIsDown(key, device=0)
28
29
  * @memberof Input */
29
30
  function keyWasPressed(key, device=0)
30
31
  {
31
- ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
32
+ ASSERT(key !== undefined, 'key is undefined');
33
+ ASSERT(device > 0 || typeof key != 'number' || key < 3, 'use code string for keyboard');
32
34
  return inputData[device] && !!(inputData[device][key] & 2);
33
35
  }
34
36
 
@@ -39,7 +41,8 @@ function keyWasPressed(key, device=0)
39
41
  * @memberof Input */
40
42
  function keyWasReleased(key, device=0)
41
43
  {
42
- ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
44
+ ASSERT(key !== undefined, 'key is undefined');
45
+ ASSERT(device > 0 || typeof key != 'number' || key < 3, 'use code string for keyboard');
43
46
  return inputData[device] && !!(inputData[device][key] & 4);
44
47
  }
45
48
 
@@ -54,7 +57,21 @@ function keyDirection(up='ArrowUp', down='ArrowDown', left='ArrowLeft', right='A
54
57
 
55
58
  /** Clears all input
56
59
  * @memberof Input */
57
- function clearInput() { inputData = [[]]; touchGamepadButtons = []; }
60
+ function inputClear() { inputData = [[]]; touchGamepadButtons = []; }
61
+
62
+ /** Clears an input key state
63
+ * @param {string|number} key
64
+ * @param {number} [device]
65
+ * @param {boolean} [clearDown=true]
66
+ * @param {boolean} [clearPressed=true]
67
+ * @param {boolean} [clearReleased=true]
68
+ * @memberof Input */
69
+ function inputClearKey(key, device=0, clearDown=true, clearPressed=true, clearReleased=true)
70
+ {
71
+ if (!inputData[device])
72
+ return;
73
+ inputData[device][key] &= ~((clearDown?1:0)|(clearPressed?2:0)|(clearReleased?4:0));
74
+ }
58
75
 
59
76
  /** Returns true if mouse button is down
60
77
  * @function
@@ -87,6 +104,16 @@ let mousePos = vec2();
87
104
  * @memberof Input */
88
105
  let mousePosScreen = vec2();
89
106
 
107
+ /** Mouse movement delta in world space
108
+ * @type {Vector2}
109
+ * @memberof Input */
110
+ let mouseDelta = vec2();
111
+
112
+ /** Mouse movement delta in screen space
113
+ * @type {Vector2}
114
+ * @memberof Input */
115
+ let mouseDeltaScreen = vec2();
116
+
90
117
  /** Mouse wheel delta this frame
91
118
  * @type {number}
92
119
  * @memberof Input */
@@ -153,10 +180,11 @@ function inputUpdate()
153
180
 
154
181
  // clear input when lost focus (prevent stuck keys)
155
182
  if(!(touchInputEnable && isTouchDevice) && !document.hasFocus())
156
- clearInput();
183
+ inputClear();
157
184
 
158
185
  // update mouse world space position
159
186
  mousePos = screenToWorld(mousePosScreen);
187
+ mouseDelta = mouseDeltaScreen.multiply(vec2(1,-1)).rotate(-cameraAngle);
160
188
 
161
189
  // update gamepads if enabled
162
190
  gamepadsUpdate();
@@ -171,13 +199,29 @@ function inputUpdatePost()
171
199
  for (const i in deviceInputData)
172
200
  deviceInputData[i] &= 1;
173
201
  mouseWheel = 0;
202
+ mouseDelta = vec2();
203
+ mouseDeltaScreen = vec2();
174
204
  }
175
205
 
176
206
  function inputInit()
177
207
  {
178
208
  if (headlessMode) return;
179
209
 
180
- onkeydown = (e)=>
210
+ // add event listeners
211
+ document.addEventListener('keydown', onKeyDown);
212
+ document.addEventListener('keyup', onKeyUp);
213
+ document.addEventListener('mousedown', onMouseDown);
214
+ document.addEventListener('mouseup', onMouseUp);
215
+ document.addEventListener('mousemove', onMouseMove);
216
+ document.addEventListener('wheel', onMouseWheel);
217
+ document.addEventListener('contextmenu', onContextMenu);
218
+ document.addEventListener('blur', onBlur);
219
+
220
+ // init touch input
221
+ if (isTouchDevice && touchInputEnable)
222
+ touchInputInit();
223
+
224
+ function onKeyDown(e)
181
225
  {
182
226
  if (!e.repeat)
183
227
  {
@@ -187,45 +231,49 @@ function inputInit()
187
231
  inputData[0][remapKey(e.code)] = 3;
188
232
  }
189
233
  }
190
-
191
- onkeyup = (e)=>
234
+ function onKeyUp(e)
192
235
  {
193
- inputData[0][e.code] = 4;
236
+ inputData[0][e.code] = (inputData[0][e.code]&2) | 4;
194
237
  if (inputWASDEmulateDirection)
195
238
  inputData[0][remapKey(e.code)] = 4;
196
239
  }
197
-
198
- // handle remapping wasd keys to directions
199
240
  function remapKey(c)
200
241
  {
201
- return inputWASDEmulateDirection ?
202
- c == 'KeyW' ? 'ArrowUp' :
203
- c == 'KeyS' ? 'ArrowDown' :
204
- c == 'KeyA' ? 'ArrowLeft' :
242
+ // handle remapping wasd keys to directions
243
+ return inputWASDEmulateDirection ?
244
+ c == 'KeyW' ? 'ArrowUp' :
245
+ c == 'KeyS' ? 'ArrowDown' :
246
+ c == 'KeyA' ? 'ArrowLeft' :
205
247
  c == 'KeyD' ? 'ArrowRight' : c : c;
206
248
  }
207
-
208
- // mouse event handlers
209
- onmousedown = (e)=>
249
+ function onMouseDown(e)
210
250
  {
251
+ if (isTouchDevice && touchInputEnable)
252
+ return;
253
+
211
254
  // fix stalled audio requiring user interaction
212
255
  if (soundEnable && !headlessMode && audioContext && audioContext.state != 'running')
213
256
  audioContext.resume();
214
257
 
215
- isUsingGamepad = false;
216
- inputData[0][e.button] = 3;
217
- mousePosScreen = mouseEventToScreen(e);
258
+ isUsingGamepad = false;
259
+ inputData[0][e.button] = 3;
260
+ mousePosScreen = mouseEventToScreen(vec2(e.x,e.y));
218
261
  inputPreventDefault && e.button && e.preventDefault();
219
262
  }
220
- onmouseup = (e)=> inputData[0][e.button] = inputData[0][e.button] & 2 | 4;
221
- onmousemove = (e)=> mousePosScreen = mouseEventToScreen(e);
222
- onwheel = (e)=> mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY);
223
- oncontextmenu = (e)=> false; // prevent right click menu
224
- onblur = (e) => clearInput(); // reset input when focus is lost
225
-
226
- // init touch input
227
- if (isTouchDevice && touchInputEnable)
228
- touchInputInit();
263
+ function onMouseUp(e)
264
+ {
265
+ if (isTouchDevice && touchInputEnable)
266
+ return;
267
+ inputData[0][e.button] = (inputData[0][e.button]&2) | 4;
268
+ }
269
+ function onMouseMove(e)
270
+ {
271
+ mousePosScreen = mouseEventToScreen(vec2(e.x,e.y));
272
+ mouseDeltaScreen = mouseDeltaScreen.add(vec2(e.movementX, e.movementY));
273
+ }
274
+ function onMouseWheel(e) { mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY); }
275
+ function onContextMenu(e) { e.preventDefault(); } // prevent right click menu
276
+ function onBlur() { inputClear(); } // reset input when focus is lost
229
277
  }
230
278
 
231
279
  // convert a mouse or touch event position to screen space
@@ -373,9 +421,6 @@ function touchInputInit()
373
421
  document.addEventListener('touchmove', (e) => handleTouch(e), { passive: false });
374
422
  document.addEventListener('touchend', (e) => handleTouch(e), { passive: false });
375
423
 
376
- // override mouse events
377
- onmousedown = onmouseup = ()=> 0;
378
-
379
424
  // handle all touch events the same way
380
425
  let wasTouching;
381
426
  function handleTouchDefault(e)
@@ -390,9 +435,16 @@ function touchInputInit()
390
435
  if (touching)
391
436
  {
392
437
  // set event pos and pass it along
393
- const p = vec2(e.touches[0].clientX, e.touches[0].clientY);
394
- mousePosScreen = mouseEventToScreen(p);
395
- wasTouching ? isUsingGamepad = touchGamepadEnable : inputData[0][button] = 3;
438
+ const pos = vec2(e.touches[0].clientX, e.touches[0].clientY);
439
+ const lastMousePosScreen = mousePosScreen;
440
+ mousePosScreen = mouseEventToScreen(pos);
441
+ if (wasTouching)
442
+ {
443
+ mouseDeltaScreen = mouseDeltaScreen.add(mousePosScreen.subtract(lastMousePosScreen));
444
+ isUsingGamepad = touchGamepadEnable;
445
+ }
446
+ else
447
+ inputData[0][button] = 3;
396
448
  }
397
449
  else if (wasTouching)
398
450
  inputData[0][button] = inputData[0][button] & 2 | 4;
@@ -498,7 +550,7 @@ function touchGamepadRender()
498
550
  }
499
551
  else // draw cross shaped gamepad
500
552
  {
501
- for(let i=10; i--;)
553
+ for (let i=10; i--;)
502
554
  {
503
555
  const angle = i*PI/4;
504
556
  context.arc(leftCenter.x, leftCenter.y,touchGamepadSize*.6, angle + PI/8, angle + PI/8);
@@ -522,4 +574,24 @@ function touchGamepadRender()
522
574
 
523
575
  // set canvas back to normal
524
576
  context.restore();
525
- }
577
+ }
578
+
579
+ ///////////////////////////////////////////////////////////////////////////////
580
+ // Pointer Lock
581
+
582
+ /** Request to lock the pointer, does not work on touch devices
583
+ * @memberof Input */
584
+ function pointerLockRequest()
585
+ {
586
+ if (!isTouchDevice)
587
+ mainCanvas.requestPointerLock && mainCanvas.requestPointerLock();
588
+ }
589
+
590
+ /** Request to unlock the pointer
591
+ * @memberof Input */
592
+ function pointerLockExit() { document.exitPointerLock && document.exitPointerLock(); }
593
+
594
+ /** Check if pointer is locked (true if locked)
595
+ * @return {boolean}
596
+ * @memberof Input */
597
+ function pointerLockIsActive() { return document.pointerLockElement == mainCanvas; }
@@ -142,7 +142,7 @@ class Medal
142
142
  context.save();
143
143
  context.beginPath();
144
144
  context.fillStyle = new Color(.9,.9,.9).toString();
145
- context.strokeStyle = new Color(0,0,0).toString();
145
+ context.strokeStyle = BLACK.toString();
146
146
  context.lineWidth = 3;
147
147
  context.rect(x, y, width, height);
148
148
  context.fill();
@@ -159,11 +159,11 @@ class Medal
159
159
  const descriptionSize = height*.3;
160
160
  const pos = vec2(x + medalDisplayIconSize + 2*gap.x, y + gap.y*2 + nameSize/2);
161
161
  const textWidth = width - medalDisplayIconSize - 3*gap.x;
162
- drawTextScreen(this.name, pos, nameSize, new Color(0,0,0), 0, undefined, 'left', undefined, textWidth);
162
+ drawTextScreen(this.name, pos, nameSize, BLACK, 0, undefined, 'left', undefined, textWidth);
163
163
 
164
164
  // draw the description
165
165
  pos.y = y + height - gap.y*2 - descriptionSize/2;
166
- drawTextScreen(this.description, pos, descriptionSize, new Color(0,0,0), 0, undefined, 'left', undefined, textWidth);
166
+ drawTextScreen(this.description, pos, descriptionSize, BLACK, 0, undefined, 'left', undefined, textWidth);
167
167
  context.restore();
168
168
  }
169
169
 
@@ -177,7 +177,7 @@ class Medal
177
177
  if (this.image)
178
178
  overlayContext.drawImage(this.image, pos.x-size/2, pos.y-size/2, size, size);
179
179
  else
180
- drawTextScreen(this.icon, pos, size*.7, new Color(0,0,0));
180
+ drawTextScreen(this.icon, pos, size*.7, BLACK);
181
181
  }
182
182
 
183
183
  // Get local storage key used by the medal