littlejsengine 1.13.4 → 1.14.2

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 (53) hide show
  1. package/README.md +2 -1
  2. package/copyToGithub.bat +28 -0
  3. package/dist/littlejs.d.ts +346 -240
  4. package/dist/littlejs.esm.js +1370 -723
  5. package/dist/littlejs.esm.min.js +1 -1
  6. package/dist/littlejs.js +1350 -709
  7. package/dist/littlejs.min.js +1 -1
  8. package/dist/littlejs.release.js +1333 -692
  9. package/examples/box2d/game.js +1 -1
  10. package/examples/box2d/gameObjects.js +1 -1
  11. package/examples/breakout/game.js +30 -25
  12. package/examples/electron/index.html +2 -2
  13. package/examples/index.html +207 -96
  14. package/examples/platformer/gameEffects.js +19 -18
  15. package/examples/platformer/gameLevel.js +6 -1
  16. package/examples/shorts/base.html +1 -1
  17. package/examples/shorts/flappyGame.js +2 -1
  18. package/examples/shorts/helloWorld.js +1 -1
  19. package/examples/shorts/music.js +106 -0
  20. package/examples/shorts/parallax.js +71 -0
  21. package/examples/shorts/piano.js +7 -8
  22. package/examples/shorts/postProcess.js +25 -8
  23. package/examples/shorts/shapes.js +1 -9
  24. package/examples/shorts/song.mp3 +0 -0
  25. package/examples/shorts/uiSystem.js +15 -8
  26. package/examples/starter/index.html +2 -2
  27. package/examples/stress/index.html +8 -3
  28. package/examples/style.css +14 -4
  29. package/examples/uiSystem/game.js +11 -11
  30. package/package.json +1 -1
  31. package/plugins/box2d.js +10 -8
  32. package/plugins/drawUtilities.js +5 -5
  33. package/plugins/newgrounds.js +6 -6
  34. package/plugins/pluginExport.js +1 -1
  35. package/plugins/uiSystem.js +103 -79
  36. package/plugins/zzfxm.js +10 -10
  37. package/reference.md +90 -54
  38. package/src/engine.js +22 -22
  39. package/src/engineAudio.js +284 -109
  40. package/src/engineBuild.js +9 -9
  41. package/src/engineDebug.js +26 -26
  42. package/src/engineDraw.js +148 -97
  43. package/src/engineExport.js +22 -16
  44. package/src/engineInput.js +57 -67
  45. package/src/engineMedals.js +25 -25
  46. package/src/engineObject.js +25 -22
  47. package/src/engineParticles.js +59 -59
  48. package/src/engineRelease.js +1 -1
  49. package/src/engineSettings.js +20 -13
  50. package/src/engineTileLayer.js +34 -34
  51. package/src/engineUtilities.js +62 -55
  52. package/src/engineWebGL.js +447 -65
  53. /package/examples/shorts/{playSound.js → sound.js} +0 -0
@@ -1,4 +1,4 @@
1
- /**
1
+ /**
2
2
  * LittleJS Input System
3
3
  * - Tracks keyboard down, pressed, and released
4
4
  * - Tracks mouse buttons, position, and wheel
@@ -16,10 +16,10 @@
16
16
  * @return {boolean}
17
17
  * @memberof Input */
18
18
  function keyIsDown(key, device=0)
19
- {
19
+ {
20
20
  ASSERT(key !== undefined, 'key is undefined');
21
- ASSERT(device > 0 || typeof key != 'number' || key < 3, 'use code string for keyboard');
22
- return inputData[device] && !!(inputData[device][key] & 1);
21
+ ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
22
+ return inputData[device] && !!(inputData[device][key] & 1);
23
23
  }
24
24
 
25
25
  /** Returns true if device key was pressed this frame
@@ -28,10 +28,10 @@ function keyIsDown(key, device=0)
28
28
  * @return {boolean}
29
29
  * @memberof Input */
30
30
  function keyWasPressed(key, device=0)
31
- {
31
+ {
32
32
  ASSERT(key !== undefined, 'key is undefined');
33
- ASSERT(device > 0 || typeof key != 'number' || key < 3, 'use code string for keyboard');
34
- return inputData[device] && !!(inputData[device][key] & 2);
33
+ ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
34
+ return inputData[device] && !!(inputData[device][key] & 2);
35
35
  }
36
36
 
37
37
  /** Returns true if device key was released this frame
@@ -40,9 +40,9 @@ function keyWasPressed(key, device=0)
40
40
  * @return {boolean}
41
41
  * @memberof Input */
42
42
  function keyWasReleased(key, device=0)
43
- {
43
+ {
44
44
  ASSERT(key !== undefined, 'key is undefined');
45
- ASSERT(device > 0 || typeof key != 'number' || key < 3, 'use code string for keyboard');
45
+ ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
46
46
  return inputData[device] && !!(inputData[device][key] & 4);
47
47
  }
48
48
 
@@ -164,7 +164,7 @@ function gamepadWasReleased(button, gamepad=0)
164
164
  * @param {number} [gamepad]
165
165
  * @return {Vector2}
166
166
  * @memberof Input */
167
- function gamepadStick(stick, gamepad=0)
167
+ function gamepadStick(stick, gamepad=0)
168
168
  { return gamepadStickData[gamepad] ? gamepadStickData[gamepad][stick] || vec2() : vec2(); }
169
169
 
170
170
  ///////////////////////////////////////////////////////////////////////////////
@@ -241,10 +241,10 @@ function inputInit()
241
241
  {
242
242
  // handle remapping wasd keys to directions
243
243
  return inputWASDEmulateDirection ?
244
- c == 'KeyW' ? 'ArrowUp' :
245
- c == 'KeyS' ? 'ArrowDown' :
246
- c == 'KeyA' ? 'ArrowLeft' :
247
- c == 'KeyD' ? 'ArrowRight' : c : c;
244
+ c === 'KeyW' ? 'ArrowUp' :
245
+ c === 'KeyS' ? 'ArrowDown' :
246
+ c === 'KeyA' ? 'ArrowLeft' :
247
+ c === 'KeyD' ? 'ArrowRight' : c : c;
248
248
  }
249
249
  function onMouseDown(e)
250
250
  {
@@ -252,9 +252,9 @@ function inputInit()
252
252
  return;
253
253
 
254
254
  // fix stalled audio requiring user interaction
255
- if (soundEnable && !headlessMode && audioContext && audioContext.state != 'running')
255
+ if (soundEnable && !headlessMode && audioContext && !audioIsRunning())
256
256
  audioContext.resume();
257
-
257
+
258
258
  isUsingGamepad = false;
259
259
  inputData[0][e.button] = 3;
260
260
  mousePosScreen = mouseEventToScreen(vec2(e.x,e.y));
@@ -297,8 +297,8 @@ function gamepadsUpdate()
297
297
  const applyDeadZones = (v)=>
298
298
  {
299
299
  const min=.3, max=.8;
300
- const deadZone = (v)=>
301
- v > min ? percent( v, min, max) :
300
+ const deadZone = (v)=>
301
+ v > min ? percent(v, min, max) :
302
302
  v < -min ? -percent(-v, min, max) : 0;
303
303
  return vec2(deadZone(v.x), deadZone(-v.y)).clampLength();
304
304
  }
@@ -306,30 +306,29 @@ function gamepadsUpdate()
306
306
  // update touch gamepad if enabled
307
307
  if (touchGamepadEnable && isTouchDevice)
308
308
  {
309
- ASSERT(touchGamepadButtons, 'set touchGamepadEnable before calling init!');
310
- if (touchGamepadTimer.isSet())
309
+ if (!touchGamepadTimer.isSet())
310
+ return;
311
+
312
+ // read virtual analog stick
313
+ const sticks = gamepadStickData[0] || (gamepadStickData[0] = []);
314
+ sticks[0] = vec2();
315
+ if (touchGamepadAnalog)
316
+ sticks[0] = applyDeadZones(touchGamepadStick);
317
+ else if (touchGamepadStick.lengthSquared() > .3)
311
318
  {
312
- // read virtual analog stick
313
- const sticks = gamepadStickData[0] || (gamepadStickData[0] = []);
314
- sticks[0] = vec2();
315
- if (touchGamepadAnalog)
316
- sticks[0] = applyDeadZones(touchGamepadStick);
317
- else if (touchGamepadStick.lengthSquared() > .3)
318
- {
319
- // convert to 8 way dpad
320
- sticks[0].x = Math.round(touchGamepadStick.x);
321
- sticks[0].y = -Math.round(touchGamepadStick.y);
322
- sticks[0] = sticks[0].clampLength();
323
- }
319
+ // convert to 8 way dpad
320
+ sticks[0].x = Math.round(touchGamepadStick.x);
321
+ sticks[0].y = -Math.round(touchGamepadStick.y);
322
+ sticks[0] = sticks[0].clampLength();
323
+ }
324
324
 
325
- // read virtual gamepad buttons
326
- const data = inputData[1] || (inputData[1] = []);
327
- for (let i=10; i--;)
328
- {
329
- const j = i == 3 ? 2 : i == 2 ? 3 : i; // fix button locations
330
- const wasDown = gamepadIsDown(j,0);
331
- data[j] = touchGamepadButtons[i] ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
332
- }
325
+ // read virtual gamepad buttons
326
+ const data = inputData[1] || (inputData[1] = []);
327
+ for (let i=10; i--;)
328
+ {
329
+ const j = i === 3 ? 2 : i === 2 ? 3 : i; // fix button locations
330
+ const wasDown = gamepadIsDown(j,0);
331
+ data[j] = touchGamepadButtons[i] ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
333
332
  }
334
333
  }
335
334
 
@@ -355,7 +354,7 @@ function gamepadsUpdate()
355
354
  // read analog sticks
356
355
  for (let j = 0; j < gamepad.axes.length-1; j+=2)
357
356
  sticks[j>>1] = applyDeadZones(vec2(gamepad.axes[j],gamepad.axes[j+1]));
358
-
357
+
359
358
  // read buttons
360
359
  for (let j = gamepad.buttons.length; j--;)
361
360
  {
@@ -371,14 +370,14 @@ function gamepadsUpdate()
371
370
  {
372
371
  // copy dpad to left analog stick when pressed
373
372
  const dpad = vec2(
374
- (gamepadIsDown(15,i)&&1) - (gamepadIsDown(14,i)&&1),
373
+ (gamepadIsDown(15,i)&&1) - (gamepadIsDown(14,i)&&1),
375
374
  (gamepadIsDown(12,i)&&1) - (gamepadIsDown(13,i)&&1));
376
375
  if (dpad.lengthSquared())
377
376
  sticks[0] = dpad.clampLength();
378
377
  }
379
378
 
380
379
  // disable touch gamepad if using real gamepad
381
- touchGamepadEnable && isUsingGamepad && touchGamepadTimer.unset();
380
+ touchGamepadEnable && isUsingGamepad && touchGamepadTimer.unset();
382
381
  }
383
382
  }
384
383
  }
@@ -403,20 +402,13 @@ function vibrateStop() { vibrate(0); }
403
402
  const isTouchDevice = !headlessMode && window.ontouchstart !== undefined;
404
403
 
405
404
  // touch gamepad internal variables
406
- let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
405
+ let touchGamepadTimer = new Timer, touchGamepadButtons = [], touchGamepadStick = vec2();
407
406
 
408
407
  // enable touch input mouse passthrough
409
408
  function touchInputInit()
410
409
  {
411
410
  // add non passive touch event listeners
412
411
  let handleTouch = handleTouchDefault;
413
- if (touchGamepadEnable)
414
- {
415
- // touch input internal variables
416
- handleTouch = handleTouchGamepad;
417
- touchGamepadButtons = [];
418
- touchGamepadStick = vec2();
419
- }
420
412
  document.addEventListener('touchstart', (e) => handleTouch(e), { passive: false });
421
413
  document.addEventListener('touchmove', (e) => handleTouch(e), { passive: false });
422
414
  document.addEventListener('touchend', (e) => handleTouch(e), { passive: false });
@@ -425,8 +417,15 @@ function touchInputInit()
425
417
  let wasTouching;
426
418
  function handleTouchDefault(e)
427
419
  {
420
+ if (!touchInputEnable)
421
+ return;
422
+
423
+ // route touch to gamepad
424
+ if (touchGamepadEnable)
425
+ handleTouchGamepad(e);
426
+
428
427
  // fix stalled audio requiring user interaction
429
- if (soundEnable && !headlessMode && audioContext && audioContext.state != 'running')
428
+ if (soundEnable && !headlessMode && audioContext && !audioIsRunning())
430
429
  audioContext.resume();
431
430
 
432
431
  // check if touching and pass to mouse events
@@ -455,7 +454,7 @@ function touchInputInit()
455
454
  // prevent default handling like copy and magnifier lens
456
455
  if (inputPreventDefault && document.hasFocus()) // allow document to get focus
457
456
  e.preventDefault();
458
-
457
+
459
458
  // must return true so the document will get focus
460
459
  return true;
461
460
  }
@@ -467,7 +466,7 @@ function touchInputInit()
467
466
  touchGamepadStick = vec2();
468
467
  touchGamepadButtons = [];
469
468
  isUsingGamepad = true;
470
-
469
+
471
470
  const touching = e.touches.length;
472
471
  if (touching)
473
472
  {
@@ -476,9 +475,6 @@ function touchInputInit()
476
475
  {
477
476
  // touch anywhere to press start when paused
478
477
  touchGamepadButtons[9] = 1;
479
-
480
- // call default touch handler so normal touch events still work
481
- handleTouchDefault(e);
482
478
  return;
483
479
  }
484
480
  }
@@ -509,12 +505,6 @@ function touchInputInit()
509
505
  touchGamepadButtons[9] = 1;
510
506
  }
511
507
  }
512
-
513
- // call default touch handler so normal touch events still work
514
- handleTouchDefault(e);
515
-
516
- // must return true so the document will get focus
517
- return true;
518
508
  }
519
509
  }
520
510
 
@@ -524,7 +514,7 @@ function touchGamepadRender()
524
514
  if (!touchInputEnable || !isTouchDevice || headlessMode) return;
525
515
  if (!touchGamepadEnable || !touchGamepadTimer.isSet())
526
516
  return;
527
-
517
+
528
518
  // fade off when not touching or paused
529
519
  const alpha = percent(touchGamepadTimer.get(), 4, 3);
530
520
  if (!alpha || paused)
@@ -555,11 +545,11 @@ function touchGamepadRender()
555
545
  const angle = i*PI/4;
556
546
  context.arc(leftCenter.x, leftCenter.y,touchGamepadSize*.6, angle + PI/8, angle + PI/8);
557
547
  i%2 && context.arc(leftCenter.x, leftCenter.y, touchGamepadSize*.33, angle, angle);
558
- i==1 && context.fill();
548
+ i===1 && context.fill();
559
549
  }
560
550
  context.stroke();
561
551
  }
562
-
552
+
563
553
  // draw right face buttons
564
554
  const rightCenter = vec2(mainCanvasSize.x-touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
565
555
  for (let i=4; i--;)
@@ -594,4 +584,4 @@ function pointerLockExit() { document.exitPointerLock && document.exitPointerLoc
594
584
  /** Check if pointer is locked (true if locked)
595
585
  * @return {boolean}
596
586
  * @memberof Input */
597
- function pointerLockIsActive() { return document.pointerLockElement == mainCanvas; }
587
+ function pointerLockIsActive() { return document.pointerLockElement === mainCanvas; }
@@ -1,4 +1,4 @@
1
- /**
1
+ /**
2
2
  * LittleJS Medal System
3
3
  * - Tracks and displays medals
4
4
  * - Saves medals to local storage
@@ -21,7 +21,7 @@ let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
21
21
  /** Initialize medals with a save name used for storage
22
22
  * - Call this after creating all medals
23
23
  * - Checks if medals are unlocked
24
- * @param {String} saveName
24
+ * @param {string} saveName
25
25
  * @memberof Medals */
26
26
  function medalsInit(saveName)
27
27
  {
@@ -36,7 +36,7 @@ function medalsInit(saveName)
36
36
  {
37
37
  if (!medalsDisplayQueue.length)
38
38
  return;
39
-
39
+
40
40
  // update first medal in queue
41
41
  const medal = medalsDisplayQueue[0];
42
42
  const time = timeReal - medalsDisplayTimeLast;
@@ -51,7 +51,7 @@ function medalsInit(saveName)
51
51
  {
52
52
  // slide on/off medals
53
53
  const slideOffTime = medalDisplayTime - medalDisplaySlideTime;
54
- const hidePercent =
54
+ const hidePercent =
55
55
  time < medalDisplaySlideTime ? 1 - time / medalDisplaySlideTime :
56
56
  time > slideOffTime ? (time - slideOffTime) / medalDisplaySlideTime : 0;
57
57
  medal.render(hidePercent);
@@ -67,43 +67,43 @@ function medalsForEach(callback)
67
67
 
68
68
  ///////////////////////////////////////////////////////////////////////////////
69
69
 
70
- /**
71
- * Medal - Tracks an unlockable medal
70
+ /**
71
+ * Medal - Tracks an unlockable medal
72
72
  * @example
73
73
  * // create a medal
74
74
  * const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
75
- *
75
+ *
76
76
  * // initialize medals
77
77
  * medalsInit('Example Game');
78
- *
78
+ *
79
79
  * // unlock the medal
80
80
  * medal_example.unlock();
81
81
  */
82
82
  class Medal
83
83
  {
84
84
  /** Create a medal object and adds it to the list of medals
85
- * @param {Number} id - The unique identifier of the medal
86
- * @param {String} name - Name of the medal
87
- * @param {String} [description] - Description of the medal
88
- * @param {String} [icon] - Icon for the medal
89
- * @param {String} [src] - Image location for the medal
85
+ * @param {number} id - The unique identifier of the medal
86
+ * @param {string} name - Name of the medal
87
+ * @param {string} [description] - Description of the medal
88
+ * @param {string} [icon] - Icon for the medal
89
+ * @param {string} [src] - Image location for the medal
90
90
  */
91
91
  constructor(id, name, description='', icon='🏆', src)
92
92
  {
93
93
  ASSERT(id >= 0 && !medals[id]);
94
-
95
- /** @property {Number} - The unique identifier of the medal */
94
+
95
+ /** @property {number} - The unique identifier of the medal */
96
96
  this.id = id;
97
-
98
- /** @property {String} - Name of the medal */
97
+
98
+ /** @property {string} - Name of the medal */
99
99
  this.name = name;
100
-
101
- /** @property {String} - Description of the medal */
100
+
101
+ /** @property {string} - Description of the medal */
102
102
  this.description = description;
103
-
104
- /** @property {String} - Icon for the medal */
103
+
104
+ /** @property {string} - Icon for the medal */
105
105
  this.icon = icon;
106
-
106
+
107
107
  /** @property {boolean} - Is the medal unlocked? */
108
108
  this.unlocked = false;
109
109
 
@@ -128,7 +128,7 @@ class Medal
128
128
  }
129
129
 
130
130
  /** Render a medal
131
- * @param {Number} [hidePercent] - How much to slide the medal off screen
131
+ * @param {number} [hidePercent] - How much to slide the medal off screen
132
132
  */
133
133
  render(hidePercent=0)
134
134
  {
@@ -169,7 +169,7 @@ class Medal
169
169
 
170
170
  /** Render the icon for a medal
171
171
  * @param {Vector2} pos - Screen space position
172
- * @param {Number} size - Screen space size
172
+ * @param {number} size - Screen space size
173
173
  */
174
174
  renderIcon(pos, size)
175
175
  {
@@ -179,7 +179,7 @@ class Medal
179
179
  else
180
180
  drawTextScreen(this.icon, pos, size*.7, BLACK);
181
181
  }
182
-
182
+
183
183
  // Get local storage key used by the medal
184
184
  storageKey() { return medalsSaveName + '_' + this.id; }
185
185
  }
@@ -1,10 +1,10 @@
1
- /**
1
+ /**
2
2
  * LittleJS Object System
3
3
  */
4
4
 
5
5
  'use strict';
6
6
 
7
- /**
7
+ /**
8
8
  * LittleJS Object Base Object Class
9
9
  * - Top level object class used by the engine
10
10
  * - Automatically adds self to object list
@@ -27,7 +27,7 @@
27
27
  * @example
28
28
  * // create an engine object, normally you would first extend the class with your own
29
29
  * const pos = vec2(2,3);
30
- * const object = new EngineObject(pos);
30
+ * const object = new EngineObject(pos);
31
31
  */
32
32
  class EngineObject
33
33
  {
@@ -45,9 +45,9 @@ class EngineObject
45
45
  ASSERT(isVector2(pos) && pos.isValid(), 'object pos should be a vec2');
46
46
  ASSERT(isVector2(size) && size.isValid(), 'object size should be a vec2');
47
47
  ASSERT(!tileInfo || tileInfo instanceof TileInfo, 'object tileInfo should be a TileInfo or undefined');
48
- ASSERT(typeof angle == 'number' && isFinite(angle), 'object angle should be a number');
48
+ ASSERT(typeof angle === 'number' && isFinite(angle), 'object angle should be a number');
49
49
  ASSERT(isColor(color) && color.isValid(), 'object color should be a valid rgba color');
50
- ASSERT(typeof renderOrder == 'number', 'object renderOrder should be a number');
50
+ ASSERT(typeof renderOrder === 'number', 'object renderOrder should be a number');
51
51
 
52
52
  /** @property {Vector2} - World space position of the object */
53
53
  this.pos = pos.copy();
@@ -115,7 +115,7 @@ class EngineObject
115
115
  // add to list of objects
116
116
  engineObjects.push(this);
117
117
  }
118
-
118
+
119
119
  /** Update the object transform, called automatically by engine even when paused */
120
120
  updateTransforms()
121
121
  {
@@ -184,7 +184,7 @@ class EngineObject
184
184
  for (const o of engineObjectsCollide)
185
185
  {
186
186
  // non solid objects don't collide with each other
187
- if (!this.isSolid && !o.isSolid || o.destroyed || o.parent || o == this)
187
+ if (!this.isSolid && !o.isSolid || o.destroyed || o.parent || o === this)
188
188
  continue;
189
189
 
190
190
  // check collision
@@ -207,7 +207,7 @@ class EngineObject
207
207
  this.velocity = this.velocity.add(velocity);
208
208
  if (o.mass) // push away if not fixed
209
209
  o.velocity = o.velocity.subtract(velocity);
210
-
210
+
211
211
  debugPhysics && debugOverlap(this.pos, this.size, o.pos, o.size, '#f00');
212
212
  continue;
213
213
  }
@@ -218,7 +218,7 @@ class EngineObject
218
218
  const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
219
219
  const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
220
220
  const restitution = max(this.restitution, o.restitution);
221
-
221
+
222
222
  if (smallStepUp || isBlockedY || !isBlockedX) // resolve y collision
223
223
  {
224
224
  // push outside object collision
@@ -306,7 +306,7 @@ class EngineObject
306
306
  {
307
307
  // move to previous position
308
308
  this.pos.y = oldPos.y;
309
- this.groundObject = undefined;
309
+ this.groundObject = undefined;
310
310
  }
311
311
  }
312
312
  if (blockedLayerX)
@@ -320,20 +320,20 @@ class EngineObject
320
320
  }
321
321
  }
322
322
  }
323
-
323
+
324
324
  /** Render the object, draws a tile by default, automatically called each frame, sorted by renderOrder */
325
325
  render()
326
326
  {
327
327
  // default object render
328
328
  drawTile(this.pos, this.drawSize || this.size, this.tileInfo, this.color, this.angle, this.mirror, this.additiveColor);
329
329
  }
330
-
330
+
331
331
  /** Destroy this object, destroy its children, detach it's parent, and mark it for removal */
332
332
  destroy()
333
- {
333
+ {
334
334
  if (this.destroyed)
335
335
  return;
336
-
336
+
337
337
  // disconnect from parent and destroy children
338
338
  this.destroyed = 1;
339
339
  this.parent && this.parent.removeChild(this);
@@ -359,7 +359,7 @@ class EngineObject
359
359
  /** Convert from world space to local space for a vector (rotation only)
360
360
  * @param {Vector2} vec - world space vector */
361
361
  worldToLocalVector(vec) { return vec.rotate(-this.angle); }
362
-
362
+
363
363
  /** Called to check if a tile collision should be resolved
364
364
  * @param {number} tileData - the value of the tile at the position
365
365
  * @param {Vector2} pos - tile where the collision occurred
@@ -378,16 +378,19 @@ class EngineObject
378
378
 
379
379
  /** Apply acceleration to this object (adjust velocity, not affected by mass)
380
380
  * @param {Vector2} acceleration */
381
- applyAcceleration(acceleration) { if (this.mass) this.velocity = this.velocity.add(acceleration); }
381
+ applyAcceleration(acceleration)
382
+ { if (this.mass) this.velocity = this.velocity.add(acceleration); }
382
383
 
383
- /** Apply angular acceleration to this object
384
+ /** Apply angular acceleration to this object
384
385
  * @param {number} acceleration */
385
- applyAngularAcceleration(acceleration) { if (this.mass) this.angleVelocity += acceleration; }
386
+ applyAngularAcceleration(acceleration)
387
+ { if (this.mass) this.angleVelocity += acceleration; }
386
388
 
387
389
  /** Apply force to this object (adjust velocity, affected by mass)
388
390
  * @param {Vector2} force */
389
- applyForce(force) { this.applyAcceleration(force.scale(1/this.mass)); }
390
-
391
+ applyForce(force)
392
+ { if (this.mass) this.applyAcceleration(force.scale(1/this.mass)); }
393
+
391
394
  /** Get the direction of the mirror
392
395
  * @return {number} -1 if this.mirror is true, or 1 if not mirrored */
393
396
  getMirrorSign() { return this.mirror ? -1 : 1; }
@@ -409,7 +412,7 @@ class EngineObject
409
412
  * @param {EngineObject} child */
410
413
  removeChild(child)
411
414
  {
412
- ASSERT(child.parent == this && this.children.includes(child));
415
+ ASSERT(child.parent === this && this.children.includes(child));
413
416
  this.children.splice(this.children.indexOf(child), 1);
414
417
  child.parent = 0;
415
418
  }
@@ -455,7 +458,7 @@ class EngineObject
455
458
  {
456
459
  if (!debug)
457
460
  return;
458
-
461
+
459
462
  // show object info for debugging
460
463
  const size = vec2(max(this.size.x, .2), max(this.size.y, .2));
461
464
  const color = rgb(this.collideTiles?1:0, this.collideSolidObjects?1:0, this.isSolid?1:0, .5);