littlejsengine 1.15.2 → 1.15.8

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 (42) hide show
  1. package/dist/littlejs.d.ts +190 -63
  2. package/dist/littlejs.esm.js +1267 -605
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +1261 -604
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +1179 -552
  7. package/examples/electron/index.html +2 -2
  8. package/examples/index.html +4 -3
  9. package/examples/particles/index.html +22 -6
  10. package/examples/shorts/base.html +2 -1
  11. package/examples/shorts/box2dCar.js +1 -1
  12. package/examples/shorts/box2dPool.js +9 -10
  13. package/examples/shorts/empty.js +1 -1
  14. package/examples/shorts/input.js +30 -25
  15. package/examples/shorts/music.js +1 -0
  16. package/examples/shorts/musicPlayer.js +1 -0
  17. package/examples/shorts/sequencer.js +2 -0
  18. package/examples/shorts/sound.js +1 -0
  19. package/examples/shorts/tileLayer.js +2 -2
  20. package/examples/shorts/tiles.png +0 -0
  21. package/examples/shorts/timers.js +1 -0
  22. package/examples/shorts/uiSystem.js +26 -14
  23. package/examples/shorts/videoPlayer.js +2 -1
  24. package/examples/starter/index.html +3 -2
  25. package/examples/uiSystem/game.js +28 -15
  26. package/package.json +1 -1
  27. package/plugins/box2d.js +1 -1
  28. package/plugins/desktop.ini +2 -0
  29. package/plugins/pluginExport.js +2 -0
  30. package/plugins/uiSystem.js +503 -91
  31. package/src/engine.js +2 -169
  32. package/src/engineAudio.js +0 -1
  33. package/src/engineBuild.js +1 -0
  34. package/src/engineDebug.js +84 -54
  35. package/src/engineDraw.js +81 -40
  36. package/src/engineExport.js +4 -1
  37. package/src/engineInput.js +526 -381
  38. package/src/engineObject.js +27 -23
  39. package/src/engineSettings.js +11 -6
  40. package/src/engineSplash.js +173 -0
  41. package/src/engineTileLayer.js +3 -3
  42. package/src/engineUtilities.js +17 -1
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.15.2';
33
+ const engineVersion = '1.15.8';
34
34
 
35
35
  /** Frames per second to update
36
36
  * @type {number}
@@ -276,7 +276,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
276
276
  o.destroyed || o.render();
277
277
  gameRenderPost();
278
278
  pluginList.forEach(plugin=>plugin.render?.());
279
- touchGamepadRender();
279
+ inputRender();
280
280
  debugRender();
281
281
  glFlush();
282
282
  debugVideoCaptureUpdate();
@@ -549,171 +549,4 @@ function engineObjectsRaycast(start, end, objects=engineObjects)
549
549
 
550
550
  debugRaycast && debugLine(start, end, hitObjects.length ? '#f00' : '#00f', .02);
551
551
  return hitObjects;
552
- }
553
-
554
- ///////////////////////////////////////////////////////////////////////////////
555
- // LittleJS splash screen and logo
556
-
557
- function drawEngineSplashScreen(t)
558
- {
559
- const x = overlayContext;
560
- const w = overlayCanvas.width = innerWidth;
561
- const h = overlayCanvas.height = innerHeight;
562
-
563
- {
564
- // background
565
- const p3 = percent(t, 1, .8);
566
- const p4 = percent(t, 0, .5);
567
- const g = x.createRadialGradient(w/2,h/2,0,w/2,h/2,hypot(w,h)*.7);
568
- g.addColorStop(0,hsl(0,0,lerp(0,p3/2,p4),p3).toString());
569
- g.addColorStop(1,hsl(0,0,0,p3).toString());
570
- x.save();
571
- x.fillStyle = g;
572
- x.fillRect(0,0,w,h);
573
- }
574
-
575
- // draw LittleJS logo...
576
- const rect = (X, Y, W, H, C)=>
577
- {
578
- x.beginPath();
579
- x.rect(X,Y,W,C?H*p:H);
580
- x.fillStyle = C;
581
- C ? x.fill() : x.stroke();
582
- };
583
- const line = (X, Y, Z, W)=>
584
- {
585
- x.beginPath();
586
- x.lineTo(X,Y);
587
- x.lineTo(Z,W);
588
- x.stroke();
589
- };
590
- const circle = (X, Y, R, A=0, B=2*PI, C, F)=>
591
- {
592
- const D = (A+B)/2, E = p*(B-A)/2;
593
- x.beginPath();
594
- F && x.lineTo(X,Y);
595
- x.arc(X,Y,R,D-E,D+E);
596
- x.fillStyle = C;
597
- C ? x.fill() : x.stroke();
598
- };
599
- const color = (c=0, l=0) =>
600
- hsl([.98,.3,.57,.14][c%4]-10,.8,[0,.3,.5,.8,.9][l]).toString();
601
- const alpha = wave(1,1,t);
602
- const p = percent(alpha, .1, .5);
603
-
604
- // setup
605
- x.translate(w/2,h/2);
606
- const size = min(6, min(w,h)/99); // fit to screen
607
- x.scale(size,size);
608
- x.translate(-40,-35);
609
- x.lineJoin = x.lineCap = 'round';
610
- x.lineWidth = .1 + p*1.9;
611
-
612
- // drawing effect
613
- const p2 = percent(alpha,.1,1);
614
- x.setLineDash([99*p2,99]);
615
-
616
- // cab top
617
- rect(7,16,18,-8,color(2,2));
618
- rect(7,8,18,4,color(2,3));
619
- rect(25,8,8,8,color(2,1));
620
- rect(25,8,-18,8);
621
- rect(25,8,8,8);
622
-
623
- // cab
624
- rect(25,16,7,23,color());
625
- rect(11,39,14,-23,color(1,1));
626
- rect(11,16,14,18,color(1,2));
627
- rect(11,16,14,8,color(1,3));
628
- rect(25,16,-14,24);
629
-
630
- // cab window
631
- rect(15,29,6,-9,color(2,2));
632
- circle(15,21,5,0,PI/2,color(2,4),1);
633
- rect(21,21,-6,9);
634
-
635
- // little stack
636
- rect(37,14,9,6,color(3,2));
637
- rect(37,14,4.5,6,color(3,3));
638
- rect(37,14,9,6);
639
-
640
- // big stack
641
- rect(50,20,10,-8,color(0,1));
642
- rect(50,20,6.5,-8,color(0,2));
643
- rect(50,20,3.5,-8,color(0,3));
644
- rect(50,20,10,-8);
645
- circle(55,2,11.4,.5,PI-.5,color(3,3));
646
- circle(55,2,11.4,.5,PI/2,color(3,2),1);
647
- circle(55,2,11.4,.5,PI-.5);
648
- rect(45,7,20,-7,color(0,2));
649
- rect(45,-1,20,4,color(0,3));
650
- rect(45,-1,20,8);
651
-
652
- // engine
653
- for (let i=5; i--;)
654
- {
655
- // stagger radius to fix slight seam
656
- circle(60-i*6,30, 9.9,0,2*PI,color(i+2,3));
657
- circle(60-i*6,30,10.0,-.5,PI+.5,color(i+2,2));
658
- circle(60-i*6,30,10.1,.5,PI-.5,color(i+2,1));
659
- }
660
-
661
- // engine outline
662
- circle(36,30,10,PI/2,PI*3/2);
663
- circle(48,30,10,PI/2,PI*3/2);
664
- circle(60,30,10);
665
- line(36,20,60,20);
666
-
667
- // engine front light
668
- circle(60,30,4,PI,3*PI,color(3,2));
669
- circle(60,30,4,PI,2*PI,color(3,3));
670
- circle(60,30,4,PI,3*PI);
671
-
672
- // front brush
673
- for (let i=6; i--;)
674
- {
675
- x.beginPath();
676
- x.lineTo(53,54);
677
- x.lineTo(53,40);
678
- x.lineTo(53+(1+i*2.9)*p,40);
679
- x.lineTo(53+(4+i*3.5)*p,54);
680
- x.fillStyle = color(0,i%2+2);
681
- x.fill();
682
- i%2 && x.stroke();
683
- }
684
-
685
- // wheels
686
- rect(6,40,5,5);
687
- rect(6,40,5,5,color());
688
- rect(15,54,38,-14,color());
689
- for (let i=3; i--;)
690
- for (let j=2; j--;)
691
- {
692
- circle(15*i+15,47,j?7:1,PI,3*PI,color(i,3));
693
- x.stroke();
694
- circle(15*i+15,47,j?7:1,0,PI,color(i,2));
695
- x.stroke();
696
- }
697
- line(6,40,68,40); // center
698
- line(77,54,4,54); // bottom
699
-
700
- // draw engine name
701
- const s = engineName;
702
- x.font = '900 16px arial';
703
- x.textAlign = 'center';
704
- x.textBaseline = 'top';
705
- x.lineWidth = .1+p*3.9;
706
- let w2 = 0;
707
- for (let i=0; i<s.length; ++i)
708
- w2 += x.measureText(s[i]).width;
709
- for (let j=2; j--;)
710
- for (let i=0, X=41-w2/2; i<s.length; ++i)
711
- {
712
- x.fillStyle = color(i,2);
713
- const w = x.measureText(s[i]).width;
714
- x[j?'strokeText':'fillText'](s[i],X+w/2,55.5,17*p);
715
- X += w;
716
- }
717
-
718
- x.restore();
719
552
  }
@@ -113,7 +113,6 @@ class Sound
113
113
  ASSERT(isNumber(pitch), 'pitch must be a number');
114
114
  ASSERT(isNumber(randomnessScale), 'randomnessScale must be a number');
115
115
 
116
-
117
116
  if (!soundEnable || headlessMode) return;
118
117
  if (!this.sampleChannels) return;
119
118
 
@@ -26,6 +26,7 @@ const engineSourceFiles =
26
26
  `${SOURCE_FOLDER}/engineParticles.js`,
27
27
  `${SOURCE_FOLDER}/engineMedals.js`,
28
28
  `${SOURCE_FOLDER}/engineWebGL.js`,
29
+ `${SOURCE_FOLDER}/engineSplash.js`,
29
30
  ];
30
31
  const enginePluginFiles =
31
32
  [
@@ -70,8 +70,9 @@ function LOG(...output) { console.log(...output); }
70
70
  * @param {number} [time]
71
71
  * @param {number} [angle]
72
72
  * @param {boolean} [fill]
73
+ * @param {boolean} [screenSpace]
73
74
  * @memberof Debug */
74
- function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false)
75
+ function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false, screenSpace=false)
75
76
  {
76
77
  ASSERT(isVector2(pos), 'pos must be a vec2');
77
78
  ASSERT(isVector2(size), 'size must be a vec2');
@@ -86,7 +87,7 @@ function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false)
86
87
  pos = pos.copy();
87
88
  size = size.copy();
88
89
  const timer = new Timer(time);
89
- debugPrimitives.push({pos:pos.copy(), size:size.copy(), color, timer, angle, fill});
90
+ debugPrimitives.push({pos:pos.copy(), size:size.copy(), color, timer, angle, fill, screenSpace});
90
91
  }
91
92
 
92
93
  /** Draw a debug poly in world space
@@ -96,8 +97,9 @@ function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false)
96
97
  * @param {number} [time]
97
98
  * @param {number} [angle]
98
99
  * @param {boolean} [fill]
100
+ * @param {boolean} [screenSpace]
99
101
  * @memberof Debug */
100
- function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false)
102
+ function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false, screenSpace=false)
101
103
  {
102
104
  ASSERT(isVector2(pos), 'pos must be a vec2');
103
105
  ASSERT(isArray(points), 'points must be an array');
@@ -110,7 +112,7 @@ function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false)
110
112
  pos = pos.copy();
111
113
  points = points.map(p=>p.copy());
112
114
  const timer = new Timer(time);
113
- debugPrimitives.push({pos, points, color, timer, angle, fill});
115
+ debugPrimitives.push({pos, points, color, timer, angle, fill, screenSpace});
114
116
  }
115
117
 
116
118
  /** Draw a debug circle in world space
@@ -119,8 +121,9 @@ function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false)
119
121
  * @param {Color|string} [color]
120
122
  * @param {number} [time]
121
123
  * @param {boolean} [fill]
124
+ * @param {boolean} [screenSpace]
122
125
  * @memberof Debug */
123
- function debugCircle(pos, size=0, color=WHITE, time=0, fill=false)
126
+ function debugCircle(pos, size=0, color=WHITE, time=0, fill=false, screenSpace=false)
124
127
  {
125
128
  ASSERT(isVector2(pos), 'pos must be a vec2');
126
129
  ASSERT(isNumber(size), 'size must be a number');
@@ -131,7 +134,7 @@ function debugCircle(pos, size=0, color=WHITE, time=0, fill=false)
131
134
  color = color.toString();
132
135
  pos = pos.copy();
133
136
  const timer = new Timer(time);
134
- debugPrimitives.push({pos, size, color, timer, angle:0, fill});
137
+ debugPrimitives.push({pos, size, color, timer, angle:0, fill, screenSpace});
135
138
  }
136
139
 
137
140
  /** Draw a debug point in world space
@@ -139,9 +142,10 @@ function debugCircle(pos, size=0, color=WHITE, time=0, fill=false)
139
142
  * @param {Color|string} [color]
140
143
  * @param {number} [time]
141
144
  * @param {number} [angle]
145
+ * @param {boolean} [screenSpace]
142
146
  * @memberof Debug */
143
- function debugPoint(pos, color, time, angle)
144
- { debugRect(pos, undefined, color, time, angle); }
147
+ function debugPoint(pos, color, time, angle, screenSpace=false)
148
+ { debugRect(pos, undefined, color, time, angle, false, screenSpace); }
145
149
 
146
150
  /** Draw a debug line in world space
147
151
  * @param {Vector2} posA
@@ -149,8 +153,9 @@ function debugPoint(pos, color, time, angle)
149
153
  * @param {Color|string} [color]
150
154
  * @param {number} [width]
151
155
  * @param {number} [time]
156
+ * @param {boolean} [screenSpace]
152
157
  * @memberof Debug */
153
- function debugLine(posA, posB, color, width=.1, time)
158
+ function debugLine(posA, posB, color, width=.1, time, screenSpace=false)
154
159
  {
155
160
  ASSERT(isVector2(posA), 'posA must be a vec2');
156
161
  ASSERT(isVector2(posB), 'posB must be sa vec2');
@@ -158,7 +163,7 @@ function debugLine(posA, posB, color, width=.1, time)
158
163
 
159
164
  const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
160
165
  const size = vec2(width, halfDelta.length()*2);
161
- debugRect(posA.add(halfDelta), size, color, time, halfDelta.angle(), true);
166
+ debugRect(posA.add(halfDelta), size, color, time, halfDelta.angle(), true, screenSpace);
162
167
  }
163
168
 
164
169
  /** Draw a debug combined axis aligned bounding box in world space
@@ -167,8 +172,10 @@ function debugLine(posA, posB, color, width=.1, time)
167
172
  * @param {Vector2} posB
168
173
  * @param {Vector2} sizeB
169
174
  * @param {Color|string} [color]
175
+ * @param {number} [time]
176
+ * @param {boolean} [screenSpace]
170
177
  * @memberof Debug */
171
- function debugOverlap(posA, sizeA, posB, sizeB, color)
178
+ function debugOverlap(posA, sizeA, posB, sizeB, color, time, screenSpace=false)
172
179
  {
173
180
  ASSERT(isVector2(posA), 'posA must be a vec2');
174
181
  ASSERT(isVector2(posB), 'posB must be a vec2');
@@ -183,19 +190,20 @@ function debugOverlap(posA, sizeA, posB, sizeB, color)
183
190
  max(posA.x + sizeA.x/2, posB.x + sizeB.x/2),
184
191
  max(posA.y + sizeA.y/2, posB.y + sizeB.y/2)
185
192
  );
186
- debugRect(minPos.lerp(maxPos,.5), maxPos.subtract(minPos), color);
193
+ debugRect(minPos.lerp(maxPos,.5), maxPos.subtract(minPos), color, time, 0, false, screenSpace);
187
194
  }
188
195
 
189
196
  /** Draw a debug axis aligned bounding box in world space
190
- * @param {string} text
197
+ * @param {string|number} text
191
198
  * @param {Vector2} pos
192
199
  * @param {number} [size]
193
200
  * @param {Color|string} [color]
194
201
  * @param {number} [time]
195
202
  * @param {number} [angle]
196
203
  * @param {string} [font]
204
+ * @param {boolean} [screenSpace]
197
205
  * @memberof Debug */
198
- function debugText(text, pos, size=1, color=WHITE, time=0, angle=0, font='monospace')
206
+ function debugText(text, pos, size=1, color=WHITE, time=0, angle=0, font='monospace', screenSpace=false)
199
207
  {
200
208
  ASSERT(isString(text), 'text must be a string');
201
209
  ASSERT(isVector2(pos), 'pos must be a vec2');
@@ -209,7 +217,7 @@ function debugText(text, pos, size=1, color=WHITE, time=0, angle=0, font='monosp
209
217
  color = color.toString();
210
218
  pos = pos.copy();
211
219
  const timer = new Timer(time);
212
- debugPrimitives.push({text, pos, size, color, timer, angle, font});
220
+ debugPrimitives.push({text, pos, size, color, timer, angle, font, screenSpace});
213
221
  }
214
222
 
215
223
  /** Clear all debug primitives in the list
@@ -344,34 +352,46 @@ function debugRender()
344
352
  debugTakeScreenshot = 0;
345
353
  }
346
354
 
347
- if (debugGamepads && gamepadsEnable && navigator.getGamepads)
355
+ if (debugGamepads && gamepadsEnable)
348
356
  {
349
- // gamepad debug display
350
- const gamepads = navigator.getGamepads();
351
- for (let i = gamepads.length; i--;)
357
+ // draw gamepads
358
+ const maxGamepads = 8;
359
+ let gamepadConnectedCount = 0;
360
+ for (let i = 0; i < maxGamepads; i++)
361
+ gamepadConnected(i) && gamepadConnectedCount++;
362
+
363
+ for (let i = 0; i < maxGamepads; i++)
352
364
  {
353
- const gamepad = gamepads[i];
354
- if (gamepad)
365
+ if (!gamepadConnected(i))
366
+ continue;
367
+
368
+ const stickScale = 1;
369
+ const buttonScale = .2;
370
+ const cornerPos = cameraPos.add(vec2(-stickScale*2, ((gamepadConnectedCount-1)/2-i)*stickScale*3));
371
+ debugText(i, cornerPos.add(vec2(-stickScale, stickScale)), 1);
372
+ if (i === gamepadPrimary)
373
+ debugText('Main', cornerPos.add(vec2(-stickScale*2, 0)),1, '#0f0');
374
+
375
+ // read analog sticks
376
+ const stickCount = gamepadStickData[i].length;
377
+ for (let j = 0; j < stickCount; j++)
355
378
  {
356
- const stickScale = 1;
357
- const buttonScale = .2;
358
- const centerPos = cameraPos;
359
- const sticks = gamepadStickData[i];
360
- for (let j = sticks.length; j--;)
361
- {
362
- const drawPos = centerPos.add(vec2(j*stickScale*2, i*stickScale*3));
363
- const stickPos = drawPos.add(sticks[j].scale(stickScale));
364
- debugCircle(drawPos, stickScale*2, '#fff7',0,true);
365
- debugLine(drawPos, stickPos, '#f00');
366
- debugPoint(stickPos, '#f00');
367
- }
368
- for (let j = gamepad.buttons.length; j--;)
369
- {
370
- const drawPos = centerPos.add(vec2(j*buttonScale*2, i*stickScale*3-stickScale-buttonScale));
371
- const pressed = gamepad.buttons[j].pressed;
372
- debugCircle(drawPos, buttonScale*2, pressed ? '#f00' : '#fff7', 0, true);
373
- debugText(''+j, drawPos, .2);
374
- }
379
+ const stick = gamepadStick(j, i);
380
+ const drawPos = cornerPos.add(vec2(j*stickScale*2, 0));
381
+ const stickPos = drawPos.add(stick.scale(stickScale));
382
+ debugCircle(drawPos, stickScale*2, '#fff7',0,true);
383
+ debugLine(drawPos, stickPos, '#f00');
384
+ debugText(j, drawPos, .3);
385
+ debugPoint(stickPos, '#f00');
386
+ }
387
+
388
+ const buttonCount = inputData[i+1].length;
389
+ for (let j = 0; j < buttonCount; j++)
390
+ {
391
+ const drawPos = cornerPos.add(vec2(j*buttonScale*2, -stickScale-buttonScale*2));
392
+ const pressed = gamepadIsDown(j, i);
393
+ debugCircle(drawPos, buttonScale*2, pressed ? '#f00' : '#fff7', 0, true);
394
+ debugText(j, drawPos, .3);
375
395
  }
376
396
  }
377
397
  }
@@ -419,21 +439,26 @@ function debugRender()
419
439
  {
420
440
  // draw debug primitives
421
441
  overlayContext.lineWidth = 2;
422
- const pointSize = debugPointSize * cameraScale;
423
442
  debugPrimitives.forEach(p=>
424
443
  {
425
444
  overlayContext.save();
426
445
 
427
446
  // create canvas transform from world space to screen space
428
- const pos = worldToScreen(p.pos);
447
+ // without scaling because we want consistent pixel sizes
448
+ let pos = p.pos, scale = 1, angle = p.angle;
449
+ if (!p.screenSpace)
450
+ {
451
+ pos = worldToScreen(p.pos);
452
+ scale = cameraScale;
453
+ angle -= cameraAngle;
454
+ }
429
455
  overlayContext.translate(pos.x|0, pos.y|0);
430
- overlayContext.rotate(p.angle);
456
+ overlayContext.rotate(angle);
431
457
  overlayContext.scale(1, p.text ? 1 : -1);
432
458
  overlayContext.fillStyle = overlayContext.strokeStyle = p.color;
433
-
434
459
  if (p.text !== undefined)
435
460
  {
436
- overlayContext.font = p.size*cameraScale + 'px '+ p.font;
461
+ overlayContext.font = p.size*scale + 'px '+ p.font;
437
462
  overlayContext.textAlign = 'center';
438
463
  overlayContext.textBaseline = 'middle';
439
464
  overlayContext.fillText(p.text, 0, 0);
@@ -444,7 +469,7 @@ function debugRender()
444
469
  overlayContext.beginPath();
445
470
  for (const point of p.points)
446
471
  {
447
- const p2 = point.scale(cameraScale).floor();
472
+ const p2 = point.scale(scale).floor();
448
473
  overlayContext.lineTo(p2.x, p2.y);
449
474
  }
450
475
  overlayContext.closePath();
@@ -454,13 +479,14 @@ function debugRender()
454
479
  else if (p.size === 0 || (p.size.x === 0 && p.size.y === 0))
455
480
  {
456
481
  // point
482
+ const pointSize = debugPointSize * scale;
457
483
  overlayContext.fillRect(-pointSize/2, -1, pointSize, 3);
458
484
  overlayContext.fillRect(-1, -pointSize/2, 3, pointSize);
459
485
  }
460
486
  else if (p.size.x !== undefined)
461
487
  {
462
488
  // rect
463
- const s = p.size.scale(cameraScale).floor();
489
+ const s = p.size.scale(scale).floor();
464
490
  const w = s.x, h = s.y;
465
491
  p.fill && overlayContext.fillRect(-w/2|0, -h/2|0, w, h);
466
492
  overlayContext.strokeRect(-w/2|0, -h/2|0, w, h);
@@ -469,7 +495,7 @@ function debugRender()
469
495
  {
470
496
  // circle
471
497
  overlayContext.beginPath();
472
- overlayContext.arc(0, 0, p.size*cameraScale/2, 0, 9);
498
+ overlayContext.arc(0, 0, p.size*scale/2, 0, 9);
473
499
  p.fill && overlayContext.fill();
474
500
  overlayContext.stroke();
475
501
  }
@@ -547,14 +573,18 @@ function debugRender()
547
573
  mousePressed && overlayContext.fillText('Mouse: ' + mousePressed, x, y += h);
548
574
  keysPressed && overlayContext.fillText('Keys: ' + keysPressed, x, y += h);
549
575
 
550
- let buttonsPressed = '';
551
- if (inputData[1])
552
- for (const i in inputData[1])
576
+ // show gamepad buttons
577
+ for (let i = 1; i < inputData.length; i++)
553
578
  {
554
- if (keyIsDown(i, 1))
555
- buttonsPressed += i + ' ' ;
579
+ let buttonsPressed = '';
580
+ if (inputData[i])
581
+ for (const j in inputData[i])
582
+ {
583
+ if (keyIsDown(j, i))
584
+ buttonsPressed += j + ' ' ;
585
+ }
586
+ buttonsPressed && overlayContext.fillText(`Gamepad ${i-1}: ` + buttonsPressed, x, y += h);
556
587
  }
557
- buttonsPressed && overlayContext.fillText('Gamepad: ' + buttonsPressed, x, y += h);
558
588
  }
559
589
  else
560
590
  {