littlejsengine 1.14.9 → 1.14.11

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.
@@ -78,12 +78,12 @@ declare module "littlejsengine" {
78
78
  * @example
79
79
  * // Basic engine startup
80
80
  * engineInit(
81
- * () => { console.log('Game initialized!'); }, // gameInit
82
- * () => { updateGameLogic(); }, // gameUpdate
83
- * () => { updateUI(); }, // gameUpdatePost
84
- * () => { drawBackground(); }, // gameRender
85
- * () => { drawHUD(); }, // gameRenderPost
86
- * ['tiles.png', 'tilesLevel.png'] // images to load
81
+ * () => { LOG('Game initialized!'); }, // gameInit
82
+ * () => { updateGameLogic(); }, // gameUpdate
83
+ * () => { updateUI(); }, // gameUpdatePost
84
+ * () => { drawBackground(); }, // gameRender
85
+ * () => { drawHUD(); }, // gameRenderPost
86
+ * ['tiles.png', 'tilesLevel.png'] // images to load
87
87
  * );
88
88
  * @memberof Engine */
89
89
  export function engineInit(gameInit: Function | (() => Promise<any>), gameUpdate: Function, gameUpdatePost: Function, gameRender: Function, gameRenderPost: Function, imageSources?: Array<string>, rootElement?: HTMLElement): Promise<void>;
@@ -143,11 +143,15 @@ declare module "littlejsengine" {
143
143
  * @default
144
144
  * @memberof Debug */
145
145
  export let showWatermark: boolean;
146
- /** Asserts if the expression is false, does not do anything in release builds
146
+ /** Asserts if the expression is false, does nothing in release builds
147
147
  * @param {boolean} assert
148
148
  * @param {...Object} [output] - error message output
149
149
  * @memberof Debug */
150
150
  export function ASSERT(assert: boolean, ...output?: any[]): void;
151
+ /** Log to console if debug is enabled, does nothing in release builds
152
+ * @param {...Object} [output] - message output
153
+ * @memberof Debug */
154
+ export function LOG(...output?: any[]): void;
151
155
  /** Draw a debug rectangle in world space
152
156
  * @param {Vector2} pos
153
157
  * @param {Vector2} [size=Vector2()]
@@ -952,10 +956,7 @@ declare module "littlejsengine" {
952
956
  /** Returns the integer direction of this vector, corresponding to multiples of 90 degree rotation (0-3)
953
957
  * @return {number} */
954
958
  direction(): number;
955
- /** Returns a copy of this vector that has been inverted
956
- * @return {Vector2} */
957
- invert(): Vector2;
958
- /** Returns a copy of this vector absolute values
959
+ /** Returns a copy of this vector with absolute values
959
960
  * @return {Vector2} */
960
961
  abs(): Vector2;
961
962
  /** Returns a copy of this vector with each axis floored
@@ -33,7 +33,7 @@ const engineName = 'LittleJS';
33
33
  * @type {string}
34
34
  * @default
35
35
  * @memberof Engine */
36
- const engineVersion = '1.14.9';
36
+ const engineVersion = '1.14.11';
37
37
 
38
38
  /** Frames per second to update
39
39
  * @type {number}
@@ -122,12 +122,12 @@ function engineAddPlugin(updateFunction, renderFunction)
122
122
  * @example
123
123
  * // Basic engine startup
124
124
  * engineInit(
125
- * () => { console.log('Game initialized!'); }, // gameInit
126
- * () => { updateGameLogic(); }, // gameUpdate
127
- * () => { updateUI(); }, // gameUpdatePost
128
- * () => { drawBackground(); }, // gameRender
129
- * () => { drawHUD(); }, // gameRenderPost
130
- * ['tiles.png', 'tilesLevel.png'] // images to load
125
+ * () => { LOG('Game initialized!'); }, // gameInit
126
+ * () => { updateGameLogic(); }, // gameUpdate
127
+ * () => { updateUI(); }, // gameUpdatePost
128
+ * () => { drawBackground(); }, // gameRender
129
+ * () => { drawHUD(); }, // gameRenderPost
130
+ * ['tiles.png', 'tilesLevel.png'] // images to load
131
131
  * );
132
132
  * @memberof Engine */
133
133
  async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources=[], rootElement=document.body)
@@ -173,16 +173,20 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
173
173
  if (!debugSpeedUp)
174
174
  frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp min framerate
175
175
 
176
+ let wasUpdated = false;
176
177
  if (paused)
177
178
  {
179
+ // update everything except the game and objects
180
+ wasUpdated = true;
178
181
  updateCanvas();
182
+ inputUpdate();
183
+ pluginUpdateList.forEach(f=>f());
179
184
 
180
185
  // update object transforms even when paused
181
186
  for (const o of engineObjects)
182
187
  o.parent || o.updateTransforms();
183
188
 
184
- inputUpdate();
185
- pluginUpdateList.forEach(f=>f());
189
+ // do post update
186
190
  debugUpdate();
187
191
  gameUpdatePost();
188
192
  inputUpdatePost();
@@ -199,12 +203,13 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
199
203
  }
200
204
 
201
205
  // update multiple frames if necessary in case of slow framerate
202
- for (;frameTimeBufferMS >= 0; frameTimeBufferMS -= 1e3 / frameRate)
206
+ for (; frameTimeBufferMS >= 0; frameTimeBufferMS -= 1e3 / frameRate)
203
207
  {
204
208
  // increment frame and update time
205
209
  time = frame++ / frameRate;
206
210
 
207
211
  // update game and objects
212
+ wasUpdated = true;
208
213
  updateCanvas();
209
214
  inputUpdate();
210
215
  gameUpdate();
@@ -215,7 +220,6 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
215
220
  debugUpdate();
216
221
  gameUpdatePost();
217
222
  inputUpdatePost();
218
-
219
223
  if (debugVideoCaptureIsActive())
220
224
  renderFrame();
221
225
  }
@@ -232,6 +236,10 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
232
236
  {
233
237
  if (headlessMode) return;
234
238
 
239
+ // canvas must be updated before rendering
240
+ if (!wasUpdated)
241
+ updateCanvas();
242
+
235
243
  // render sort then render while removing destroyed objects
236
244
  enginePreRender();
237
245
  gameRender();
@@ -391,7 +399,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
391
399
  promises.push(new Promise(resolve =>
392
400
  {
393
401
  let t = 0;
394
- console.log(`${engineName} Engine v${engineVersion}`);
402
+ LOG(`${engineName} Engine v${engineVersion}`);
395
403
  updateSplash();
396
404
  function updateSplash()
397
405
  {
@@ -688,12 +696,6 @@ function drawEngineSplashScreen(t)
688
696
  * @memberof Debug */
689
697
  const debug = true;
690
698
 
691
- /** True if asserts are enabled
692
- * @type {boolean}
693
- * @default
694
- * @memberof Debug */
695
- const enableAsserts = true;
696
-
697
699
  /** Size to render debug points by default
698
700
  * @type {number}
699
701
  * @default
@@ -724,15 +726,16 @@ let debugPrimitives = [], debugPhysics = false, debugRaycast = false, debugParti
724
726
  ///////////////////////////////////////////////////////////////////////////////
725
727
  // Debug helper functions
726
728
 
727
- /** Asserts if the expression is false, does not do anything in release builds
729
+ /** Asserts if the expression is false, does nothing in release builds
728
730
  * @param {boolean} assert
729
731
  * @param {...Object} [output] - error message output
730
732
  * @memberof Debug */
731
- function ASSERT(assert, ...output)
732
- {
733
- if (enableAsserts)
734
- console.assert(assert, ...output);
735
- }
733
+ function ASSERT(assert, ...output) { console.assert(assert, ...output); }
734
+
735
+ /** Log to console if debug is enabled, does nothing in release builds
736
+ * @param {...Object} [output] - message output
737
+ * @memberof Debug */
738
+ function LOG(...output) { console.log(...output); }
736
739
 
737
740
  /** Draw a debug rectangle in world space
738
741
  * @param {Vector2} pos
@@ -1127,7 +1130,8 @@ function debugRender()
1127
1130
  {
1128
1131
  overlayContext.fillText(`${engineName} v${engineVersion}`, x, y += h/2 );
1129
1132
  overlayContext.fillText('Time: ' + formatTime(time), x, y += h);
1130
- overlayContext.fillText('FPS: ' + averageFPS.toFixed(1), x, y += h);
1133
+ overlayContext.fillText('FPS: ' + averageFPS.toFixed(1) + (glEnable?' WebGL':' Canvas2D'),
1134
+ x, y += h);
1131
1135
  overlayContext.fillText('Objects: ' + engineObjects.length, x, y += h);
1132
1136
  overlayContext.fillText('Draw Count: ' + drawCount, x, y += h);
1133
1137
  overlayContext.fillText('---------', x, y += h);
@@ -1146,12 +1150,18 @@ function debugRender()
1146
1150
  overlayContext.fillText('6: Toggle Video Capture', x, y += h);
1147
1151
 
1148
1152
  let keysPressed = '';
1153
+ let mousePressed = '';
1149
1154
  for (const i in inputData[0])
1150
1155
  {
1151
- if (keyIsDown(i, 0))
1156
+ if (!keyIsDown(i, 0))
1157
+ continue;
1158
+ if (parseInt(i) < 3)
1159
+ mousePressed += i + ' ' ;
1160
+ else if (keyIsDown(i, 0))
1152
1161
  keysPressed += i + ' ' ;
1153
1162
  }
1154
- keysPressed && overlayContext.fillText('Keys Down: ' + keysPressed, x, y += h);
1163
+ mousePressed && overlayContext.fillText('Mouse: ' + mousePressed, x, y += h);
1164
+ keysPressed && overlayContext.fillText('Keys: ' + keysPressed, x, y += h);
1155
1165
 
1156
1166
  let buttonsPressed = '';
1157
1167
  if (inputData[1])
@@ -1219,7 +1229,7 @@ function debugVideoCaptureStart()
1219
1229
  }
1220
1230
 
1221
1231
  // start recording
1222
- console.log('Video capture started.');
1232
+ LOG('Video capture started.');
1223
1233
  debugVideoCapture.start();
1224
1234
  debugVideoCaptureTimer = new Timer(0);
1225
1235
 
@@ -1246,7 +1256,7 @@ function debugVideoCaptureStop()
1246
1256
  return; // not recording
1247
1257
 
1248
1258
  // stop recording
1249
- console.log(`Video capture ended. ${debugVideoCaptureTimer.get().toFixed(2)} seconds recorded.`);
1259
+ LOG(`Video capture ended. ${debugVideoCaptureTimer.get().toFixed(2)} seconds recorded.`);
1250
1260
  debugVideoCapture.stop();
1251
1261
  debugVideoCapture = 0;
1252
1262
  debugVideoCaptureIcon.style.display = 'none';
@@ -1480,7 +1490,12 @@ function wave(frequency=1, amplitude=1, t=time, offset=0)
1480
1490
  * @param {number} t - time in seconds
1481
1491
  * @return {string}
1482
1492
  * @memberof Utilities */
1483
- function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
1493
+ function formatTime(t)
1494
+ {
1495
+ const sign = t < 0 ? '-' : '';
1496
+ t = abs(t)|0;
1497
+ return sign + (t/60|0) + ':' + (t%60<10?'0':'') + t%60;
1498
+ }
1484
1499
 
1485
1500
  /** Fetches a JSON file from a URL and returns the parsed JSON object. Must be used with await!
1486
1501
  * @param {string} url - URL of JSON file
@@ -1816,11 +1831,7 @@ class Vector2
1816
1831
  direction()
1817
1832
  { return abs(this.x) > abs(this.y) ? this.x < 0 ? 3 : 1 : this.y < 0 ? 2 : 0; }
1818
1833
 
1819
- /** Returns a copy of this vector that has been inverted
1820
- * @return {Vector2} */
1821
- invert() { return new Vector2(this.y, -this.x); }
1822
-
1823
- /** Returns a copy of this vector absolute values
1834
+ /** Returns a copy of this vector with absolute values
1824
1835
  * @return {Vector2} */
1825
1836
  abs() { return new Vector2(abs(this.x), abs(this.y)); }
1826
1837
 
@@ -1862,13 +1873,10 @@ class Vector2
1862
1873
  toString(digits=3)
1863
1874
  {
1864
1875
  ASSERT_NUMBER_VALID(digits);
1865
- if (debug)
1866
- {
1867
- if (this.isValid())
1868
- return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`;
1869
- else
1870
- return `(${this.x}, ${this.y})`;
1871
- }
1876
+ if (this.isValid())
1877
+ return `(${(this.x<0?'':' ') + this.x.toFixed(digits)},${(this.y<0?'':' ') + this.y.toFixed(digits)} )`;
1878
+ else
1879
+ return `(${this.x}, ${this.y})`;
1872
1880
  }
1873
1881
 
1874
1882
  /** Checks if this is a valid vector
@@ -2257,7 +2265,7 @@ class Timer
2257
2265
 
2258
2266
  /** Returns this timer expressed as a string
2259
2267
  * @return {string} */
2260
- toString() { if (debug) { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }}
2268
+ toString() { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }
2261
2269
 
2262
2270
  /** Get how long since elapsed, returns 0 if not set (returns negative if currently active)
2263
2271
  * @return {number} */
@@ -2485,6 +2493,12 @@ let touchGamepadEnable = false;
2485
2493
  * @memberof Settings */
2486
2494
  let touchGamepadAnalog = true;
2487
2495
 
2496
+ /** Number of buttons on touch gamepad
2497
+ * @type {number}
2498
+ * @default
2499
+ * @memberof Settings */
2500
+ let touchGamepadButtonCount = 4;
2501
+
2488
2502
  /** Size of virtual gamepad for touch devices in pixels
2489
2503
  * @type {number}
2490
2504
  * @default
@@ -4515,7 +4529,7 @@ function inputInit()
4515
4529
  function onMouseLeave()
4516
4530
  {
4517
4531
  // set mouse position and delta when leaving canvas
4518
- mousePosScreen = vec2(Infinity);
4532
+ mousePosScreen = vec2(-1);
4519
4533
  mouseDeltaScreen = vec2(0);
4520
4534
  }
4521
4535
  }
@@ -4570,10 +4584,12 @@ function gamepadsUpdate()
4570
4584
  const data = inputData[1] || (inputData[1] = []);
4571
4585
  for (let i=10; i--;)
4572
4586
  {
4573
- const j = i === 3 ? 2 : i === 2 ? 3 : i; // fix button locations
4574
- const wasDown = gamepadIsDown(j,0);
4575
- data[j] = touchGamepadButtons[i] ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
4587
+ const wasDown = gamepadIsDown(i,0);
4588
+ data[i] = touchGamepadButtons[i] ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
4576
4589
  }
4590
+
4591
+ // disable normal gamepads when touch gamepad is active
4592
+ return;
4577
4593
  }
4578
4594
 
4579
4595
  // return if gamepads are disabled or not supported
@@ -4648,6 +4664,15 @@ const isTouchDevice = !headlessMode && window.ontouchstart !== undefined;
4648
4664
  // touch gamepad internal variables
4649
4665
  let touchGamepadTimer = new Timer, touchGamepadButtons = [], touchGamepadStick = vec2();
4650
4666
 
4667
+ function touchGamepadButtonCenter()
4668
+ {
4669
+ // draw right face buttons
4670
+ let center = vec2(mainCanvasSize.x-touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
4671
+ if (touchGamepadButtonCount <= 2)
4672
+ center.x += touchGamepadSize/2;
4673
+ return center;
4674
+ }
4675
+
4651
4676
  // enable touch input mouse passthrough
4652
4677
  function touchInputInit()
4653
4678
  {
@@ -4695,8 +4720,8 @@ function touchInputInit()
4695
4720
  // set was touching
4696
4721
  wasTouching = touching;
4697
4722
 
4698
- // prevent default handling like copy and magnifier lens
4699
- if (inputPreventDefault && document.hasFocus()) // allow document to get focus
4723
+ // prevent default handling like copy, magnifier lens, and scrolling
4724
+ if (inputPreventDefault && document.hasFocus() && e.cancelable)
4700
4725
  e.preventDefault();
4701
4726
 
4702
4727
  // must return true so the document will get focus
@@ -4725,25 +4750,36 @@ function touchInputInit()
4725
4750
 
4726
4751
  // get center of left and right sides
4727
4752
  const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
4728
- const buttonCenter = mainCanvasSize.subtract(vec2(touchGamepadSize, touchGamepadSize));
4753
+ const buttonCenter = touchGamepadButtonCenter();
4729
4754
  const startCenter = mainCanvasSize.scale(.5);
4730
4755
 
4731
4756
  // check each touch point
4732
4757
  for (const touch of e.touches)
4733
4758
  {
4734
4759
  const touchPos = mouseEventToScreen(vec2(touch.clientX, touch.clientY));
4735
- if (touchPos.distance(stickCenter) < touchGamepadSize)
4760
+ if (stickCenter.distance(touchPos) < touchGamepadSize)
4736
4761
  {
4737
4762
  // virtual analog stick
4738
4763
  touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
4739
4764
  }
4740
- else if (touchPos.distance(buttonCenter) < touchGamepadSize)
4765
+ else if (buttonCenter.distance(touchPos) < touchGamepadSize)
4741
4766
  {
4742
4767
  // virtual face buttons
4743
- const button = touchPos.subtract(buttonCenter).direction();
4744
- touchGamepadButtons[button] = 1;
4768
+ let button = buttonCenter.subtract(touchPos).direction();
4769
+ button = mod(button+2, 4);
4770
+ if (touchGamepadButtonCount === 1)
4771
+ button = 0;
4772
+ else if (touchGamepadButtonCount === 2)
4773
+ {
4774
+ const delta = buttonCenter.subtract(touchPos);
4775
+ button = -delta.x < delta.y ? 1 : 0;
4776
+ }
4777
+ // fix button locations (swap 2 and 3 to match gamepad layout)
4778
+ button = button === 3 ? 2 : button === 2 ? 3 : button;
4779
+ if (button < touchGamepadButtonCount)
4780
+ touchGamepadButtons[button] = 1;
4745
4781
  }
4746
- else if (touchPos.distance(startCenter) < touchGamepadSize && !wasTouching)
4782
+ else if (startCenter.distance(touchPos) < touchGamepadSize && !wasTouching)
4747
4783
  {
4748
4784
  // virtual start button in center
4749
4785
  touchGamepadButtons[9] = 1;
@@ -4774,11 +4810,10 @@ function touchGamepadRender()
4774
4810
  // draw left analog stick
4775
4811
  context.fillStyle = touchGamepadStick.lengthSquared() > 0 ? '#fff' : '#000';
4776
4812
  context.beginPath();
4777
-
4778
- const leftCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
4813
+ const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
4779
4814
  if (touchGamepadAnalog) // draw circle shaped gamepad
4780
4815
  {
4781
- context.arc(leftCenter.x, leftCenter.y, touchGamepadSize/2, 0, 9);
4816
+ context.arc(stickCenter.x, stickCenter.y, touchGamepadSize/2, 0, 9);
4782
4817
  context.fill();
4783
4818
  context.stroke();
4784
4819
  }
@@ -4787,21 +4822,27 @@ function touchGamepadRender()
4787
4822
  for (let i=10; i--;)
4788
4823
  {
4789
4824
  const angle = i*PI/4;
4790
- context.arc(leftCenter.x, leftCenter.y,touchGamepadSize*.6, angle + PI/8, angle + PI/8);
4791
- i%2 && context.arc(leftCenter.x, leftCenter.y, touchGamepadSize*.33, angle, angle);
4825
+ context.arc(stickCenter.x, stickCenter.y,touchGamepadSize*.6, angle + PI/8, angle + PI/8);
4826
+ i%2 && context.arc(stickCenter.x, stickCenter.y, touchGamepadSize*.33, angle, angle);
4792
4827
  i===1 && context.fill();
4793
4828
  }
4794
4829
  context.stroke();
4795
4830
  }
4796
4831
 
4797
4832
  // draw right face buttons
4798
- const rightCenter = vec2(mainCanvasSize.x-touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
4799
- for (let i=4; i--;)
4800
- {
4801
- const pos = rightCenter.add(vec2().setDirection(i, touchGamepadSize/2));
4802
- context.fillStyle = touchGamepadButtons[i] ? '#fff' : '#000';
4833
+ const buttonCenter = touchGamepadButtonCenter();
4834
+ const buttonSize = touchGamepadButtonCount > 1 ? touchGamepadSize/4 : touchGamepadSize/2;
4835
+ for (let i=0; i<touchGamepadButtonCount; i++)
4836
+ {
4837
+ let j = mod(i-1, 4);
4838
+ let button = touchGamepadButtonCount > 2 ?
4839
+ j : min(j, touchGamepadButtonCount-1);
4840
+ // fix button locations (swap 2 and 3 to match gamepad layout)
4841
+ button = button === 3 ? 2 : button === 2 ? 3 : button;
4842
+ const pos = buttonCenter.add(vec2().setDirection(j, touchGamepadSize/2));
4843
+ context.fillStyle = touchGamepadButtons[button] ? '#fff' : '#000';
4803
4844
  context.beginPath();
4804
- context.arc(pos.x, pos.y, touchGamepadSize/4, 0,9);
4845
+ context.arc(pos.x, pos.y, buttonSize, 0,9);
4805
4846
  context.fill();
4806
4847
  context.stroke();
4807
4848
  }
@@ -5591,6 +5632,12 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
5591
5632
  const tileLayer = new TileCollisionLayer(vec2(), levelSize, tileInfo, layerRenderOrder);
5592
5633
  tileLayers[layerIndex] = tileLayer;
5593
5634
 
5635
+ // apply layer color
5636
+ const layerColor = dataLayer.color || WHITE;
5637
+ if (dataLayer.tintcolor)
5638
+ layerColor.setHex(dataLayer.tintcolor);
5639
+ ASSERT(isColor(layerColor), 'layer color is not a color');
5640
+
5594
5641
  for (let x=levelSize.x; x--;)
5595
5642
  for (let y=levelSize.y; y--;)
5596
5643
  {
@@ -5598,7 +5645,7 @@ function tileCollisionLoad(tileMapData, tileInfo=tile(), renderOrder=0, collisio
5598
5645
  const data = dataLayer.data[x + y*levelSize.x];
5599
5646
  if (data)
5600
5647
  {
5601
- const layerData = new TileLayerData(data-1);
5648
+ const layerData = new TileLayerData(data-1, 0, false, layerColor);
5602
5649
  tileLayer.setData(pos, layerData);
5603
5650
 
5604
5651
  // set collision for top layer
@@ -7492,7 +7539,7 @@ class NewgroundsPlugin
7492
7539
  // get medals
7493
7540
  const medalsResult = this.call('Medal.getList');
7494
7541
  this.medals = medalsResult ? medalsResult.result.data['medals'] : [];
7495
- debugMedals && console.log(this.medals);
7542
+ debugMedals && LOG(this.medals);
7496
7543
  for (const newgroundsMedal of this.medals)
7497
7544
  {
7498
7545
  const medal = medals[newgroundsMedal['id']];
@@ -7515,7 +7562,7 @@ class NewgroundsPlugin
7515
7562
  // get scoreboards
7516
7563
  const scoreboardResult = this.call('ScoreBoard.getBoards');
7517
7564
  this.scoreboards = scoreboardResult ? scoreboardResult.result.data.scoreboards : [];
7518
- debugMedals && console.log(this.scoreboards);
7565
+ debugMedals && LOG(this.scoreboards);
7519
7566
 
7520
7567
  // keep the session alive with a ping every minute
7521
7568
  const keepAliveMS = 60 * 1e3;
@@ -7584,10 +7631,10 @@ class NewgroundsPlugin
7584
7631
  try { xmlHttp.send(formData); }
7585
7632
  catch(e)
7586
7633
  {
7587
- debugMedals && console.log('newgrounds call failed', e);
7634
+ debugMedals && LOG('newgrounds call failed', e);
7588
7635
  return;
7589
7636
  }
7590
- debugMedals && console.log(xmlHttp.responseText);
7637
+ debugMedals && LOG(xmlHttp.responseText);
7591
7638
  return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
7592
7639
  }
7593
7640
  }
@@ -8157,7 +8204,7 @@ class UIObject
8157
8204
  const mouseDown = mouseIsDown(0);
8158
8205
  const mousePress = this.dragActivate ? mouseDown : mouseWasPressed(0);
8159
8206
  if (!uiSystem.hoverObject)
8160
- if (mousePress || !mouseDown || isActive)
8207
+ if (mousePress || isActive || (!mouseDown && !isTouchDevice))
8161
8208
  {
8162
8209
  const size = this.size.add(vec2(isTouchDevice && this.extraTouchSize || 0));
8163
8210
  if (isOverlapping(this.pos, size, mousePosScreen))
@@ -10184,7 +10231,7 @@ async function box2dInit()
10184
10231
  }
10185
10232
  function box2dRender()
10186
10233
  {
10187
- if (box2dDebug || debugPhysics && debugOverlay)
10234
+ if (box2dDebug || debugPhysics)
10188
10235
  box2d.world.DrawDebugData();
10189
10236
  }
10190
10237
 
@@ -10421,6 +10468,7 @@ export
10421
10468
 
10422
10469
  // Debug
10423
10470
  ASSERT,
10471
+ LOG,
10424
10472
  debugRect,
10425
10473
  debugPoly,
10426
10474
  debugCircle,