littlejsengine 1.18.1 → 1.18.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.
- package/.github/workflows/test.yml +17 -0
- package/AI.md +11 -0
- package/LICENSE +5 -27
- package/README.md +2 -2
- package/dist/littlejs.d.ts +237 -10
- package/dist/littlejs.esm.js +748 -32
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +732 -30
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +732 -30
- package/examples/index.html +62 -800
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/textureWrapped.js +12 -0
- package/examples/shorts/tween.js +24 -0
- package/examples/shorts.js +743 -0
- package/examples/starter/index.html +2 -2
- package/examples/tweenSystem/game.js +171 -0
- package/examples/tweenSystem/index.html +10 -0
- package/examples/tweenSystem/tiles.png +0 -0
- package/package.json +3 -2
- package/plugins/box2d.js +4 -2
- package/plugins/pluginExport.js +7 -0
- package/plugins/tween.js +509 -0
- package/plugins/uiSystem.js +1 -1
- package/reference.md +1 -0
- package/src/engine.js +9 -6
- package/src/engineBuild.mjs +1 -0
- package/src/engineDraw.js +133 -2
- package/src/engineExport.js +9 -2
- package/src/engineInput.js +43 -4
- package/src/engineObject.js +1 -0
- package/src/engineSettings.js +30 -8
- package/src/engineWebGL.js +3 -7
- package/test/math.test.mjs +774 -0
- package/test/setup.mjs +22 -0
- package/test/smoke.test.mjs +274 -0
- package/test/tween.test.mjs +576 -0
- package/test/util.test.mjs +80 -0
package/src/engineDraw.js
CHANGED
|
@@ -72,6 +72,12 @@ let textureInfos = [];
|
|
|
72
72
|
* @memberof Draw */
|
|
73
73
|
let drawCount;
|
|
74
74
|
|
|
75
|
+
// internal predicates for tint short-circuiting in canvas2D draw paths
|
|
76
|
+
// isWhite ignores alpha because alpha is applied via globalAlpha, not multiply
|
|
77
|
+
// isBlack includes alpha so additive colors that only contribute alpha are not skipped
|
|
78
|
+
/** @param {Color} c */ function isWhite(c) { return c.r >= 1 && c.g >= 1 && c.b >= 1; }
|
|
79
|
+
/** @param {Color} c */ function isBlack(c) { return c.r <= 0 && c.g <= 0 && c.b <= 0 && c.a <= 0; }
|
|
80
|
+
|
|
75
81
|
///////////////////////////////////////////////////////////////////////////////
|
|
76
82
|
|
|
77
83
|
/**
|
|
@@ -401,6 +407,96 @@ function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0,
|
|
|
401
407
|
}
|
|
402
408
|
}
|
|
403
409
|
|
|
410
|
+
/** Draw a texture tiled (wrapped) across a rectangle in world space.
|
|
411
|
+
* Useful for backgrounds, repeating patterns, and seamless fills.
|
|
412
|
+
* The whole texture is tiled — sub-region (TileInfo) wrapping is not supported.
|
|
413
|
+
* @param {Vector2} pos - Center of the rect in world space
|
|
414
|
+
* @param {Vector2} size - Size of the rect in world space
|
|
415
|
+
* @param {Vector2} wrapCount - How many times the texture repeats (x, y)
|
|
416
|
+
* @param {TextureInfo|number} [texture=0] - TextureInfo or texture index into textureInfos
|
|
417
|
+
* @param {Color} [color=WHITE] - Color to modulate with
|
|
418
|
+
* @param {number} [angle=0] - Angle to rotate by
|
|
419
|
+
* @param {Color} [additiveColor] - Additive color to be applied if any
|
|
420
|
+
* @param {boolean} [useWebGL=glEnable] - Use accelerated WebGL rendering?
|
|
421
|
+
* @param {boolean} [screenSpace=false] - Are pos and size in screen space?
|
|
422
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas 2D context to draw to
|
|
423
|
+
* @memberof Draw */
|
|
424
|
+
function drawTextureWrapped(pos, size, wrapCount, texture=0, color=WHITE,
|
|
425
|
+
angle=0, additiveColor, useWebGL=glEnable, screenSpace=false, context)
|
|
426
|
+
{
|
|
427
|
+
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
428
|
+
ASSERT(isVector2(size), 'size must be a vec2');
|
|
429
|
+
ASSERT(isVector2(wrapCount), 'wrapCount must be a vec2');
|
|
430
|
+
ASSERT(isColor(color), 'color is invalid');
|
|
431
|
+
ASSERT(isNumber(angle), 'angle must be a number');
|
|
432
|
+
ASSERT(!additiveColor || isColor(additiveColor), 'additiveColor must be a color');
|
|
433
|
+
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
434
|
+
ASSERT(!(texture instanceof TileInfo),
|
|
435
|
+
'pass a TextureInfo or texture index, not a TileInfo — use tileInfo.textureInfo');
|
|
436
|
+
|
|
437
|
+
// short-circuit before texture lookup — textureInfos[0] is undefined in headless mode
|
|
438
|
+
if (headlessMode) return;
|
|
439
|
+
|
|
440
|
+
// resolve texture argument: TextureInfo or index
|
|
441
|
+
const textureInfo = typeof texture === 'number' ? textureInfos[texture] : texture;
|
|
442
|
+
ASSERT(textureInfo instanceof TextureInfo, 'texture not loaded');
|
|
443
|
+
ASSERT(textureInfo.size.x > 0, 'texture not loaded');
|
|
444
|
+
|
|
445
|
+
if (useWebGL && glEnable)
|
|
446
|
+
{
|
|
447
|
+
ASSERT(!!glContext, 'WebGL is not enabled!');
|
|
448
|
+
if (screenSpace)
|
|
449
|
+
[pos, size, angle] = screenToWorldTransform(pos, size, angle);
|
|
450
|
+
glSetTexture(textureInfo.glTexture);
|
|
451
|
+
glDraw(pos.x, pos.y, size.x, size.y, angle,
|
|
452
|
+
0, 0, wrapCount.x, wrapCount.y,
|
|
453
|
+
color.rgbaInt(), additiveColor && additiveColor.rgbaInt());
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Canvas2D path — increment drawCount here (WebGL batch counts via glBatchCount)
|
|
458
|
+
++drawCount;
|
|
459
|
+
|
|
460
|
+
if (!screenSpace)
|
|
461
|
+
{
|
|
462
|
+
pos = worldToScreen(pos);
|
|
463
|
+
size = size.scale(cameraScale);
|
|
464
|
+
angle -= cameraAngle;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// pick image source: raw, or tinted bake. Match drawImageColor's
|
|
468
|
+
// "no tint needed" predicate so behavior stays consistent.
|
|
469
|
+
const noTint = !canvasColorTiles ||
|
|
470
|
+
(additiveColor
|
|
471
|
+
? isWhite(color.add(additiveColor)) && additiveColor.a <= 0
|
|
472
|
+
: isWhite(color));
|
|
473
|
+
// alpha is baked into pixels by bakeTintedImage's additive branch;
|
|
474
|
+
// in that case globalAlpha must NOT also apply color.a
|
|
475
|
+
const alphaBaked = !noTint && additiveColor && !isBlack(additiveColor);
|
|
476
|
+
const source = noTint
|
|
477
|
+
? textureInfo.image
|
|
478
|
+
: bakeTintedImage(textureInfo.image, color, additiveColor);
|
|
479
|
+
|
|
480
|
+
context = context || drawContext;
|
|
481
|
+
context.save();
|
|
482
|
+
context.translate(pos.x + .5, pos.y + .5);
|
|
483
|
+
context.rotate(angle);
|
|
484
|
+
context.globalAlpha = alphaBaked ? 1 : color.a;
|
|
485
|
+
|
|
486
|
+
const pattern = context.createPattern(source, 'repeat');
|
|
487
|
+
// map pattern-source pixels into user space so the rect contains
|
|
488
|
+
// wrapCount.x × wrapCount.y repeats
|
|
489
|
+
const m = new DOMMatrix()
|
|
490
|
+
.translate(-size.x/2, -size.y/2)
|
|
491
|
+
.scale(size.x / (wrapCount.x * source.width),
|
|
492
|
+
size.y / (wrapCount.y * source.height));
|
|
493
|
+
pattern.setTransform(m);
|
|
494
|
+
context.fillStyle = pattern;
|
|
495
|
+
context.fillRect(-size.x/2, -size.y/2, size.x, size.y);
|
|
496
|
+
context.globalAlpha = 1;
|
|
497
|
+
context.restore();
|
|
498
|
+
}
|
|
499
|
+
|
|
404
500
|
/** Draw connected lines between a series of points
|
|
405
501
|
* @param {Array<Vector2>} points
|
|
406
502
|
* @param {number} [width]
|
|
@@ -924,6 +1020,43 @@ function combineCanvases()
|
|
|
924
1020
|
mainContext.drawImage(workCanvas, 0, 0);
|
|
925
1021
|
}
|
|
926
1022
|
|
|
1023
|
+
// Internal: bake a color/additive-color tint into workReadCanvas at the
|
|
1024
|
+
// image's native resolution. Returns the work canvas, suitable for
|
|
1025
|
+
// passing to context.createPattern. Used by drawTextureWrapped's
|
|
1026
|
+
// Canvas2D path. Caller is responsible for short-circuiting when no
|
|
1027
|
+
// tint is needed (i.e. color is white and additiveColor is black/none).
|
|
1028
|
+
function bakeTintedImage(image, color, additiveColor)
|
|
1029
|
+
{
|
|
1030
|
+
const w = image.width|0, h = image.height|0;
|
|
1031
|
+
workReadCanvas.width = w;
|
|
1032
|
+
workReadCanvas.height = h;
|
|
1033
|
+
workReadContext.drawImage(image, 0, 0);
|
|
1034
|
+
|
|
1035
|
+
const imageData = workReadContext.getImageData(0, 0, w, h);
|
|
1036
|
+
const data = imageData.data;
|
|
1037
|
+
if (additiveColor && !isBlack(additiveColor))
|
|
1038
|
+
{
|
|
1039
|
+
// multiply + additive (slower)
|
|
1040
|
+
const colorMultiply = [color.r, color.g, color.b, color.a];
|
|
1041
|
+
const colorAdd = [additiveColor.r * 255, additiveColor.g * 255,
|
|
1042
|
+
additiveColor.b * 255, additiveColor.a * 255];
|
|
1043
|
+
for (let i = 0; i < data.length; ++i)
|
|
1044
|
+
data[i] = data[i] * colorMultiply[i&3] + colorAdd[i&3] |0;
|
|
1045
|
+
}
|
|
1046
|
+
else
|
|
1047
|
+
{
|
|
1048
|
+
// RGB only, faster — alpha left intact for the caller
|
|
1049
|
+
for (let i = 0; i < data.length; i+=4)
|
|
1050
|
+
{
|
|
1051
|
+
data[i ] *= color.r;
|
|
1052
|
+
data[i+1] *= color.g;
|
|
1053
|
+
data[i+2] *= color.b;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
workReadContext.putImageData(imageData, 0, 0);
|
|
1057
|
+
return workReadCanvas;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
927
1060
|
/** Helper function to draw an image with color and additive color applied
|
|
928
1061
|
* This is slower then normal drawImage when color is applied
|
|
929
1062
|
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context
|
|
@@ -942,8 +1075,6 @@ function combineCanvases()
|
|
|
942
1075
|
* @memberof Draw */
|
|
943
1076
|
function drawImageColor(context, image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, color, additiveColor, bleed=0)
|
|
944
1077
|
{
|
|
945
|
-
function isWhite(c) { return c.r >= 1 && c.g >= 1 && c.b >= 1; }
|
|
946
|
-
function isBlack(c) { return c.r <= 0 && c.g <= 0 && c.b <= 0 && c.a <= 0; }
|
|
947
1078
|
const sx2 = bleed;
|
|
948
1079
|
const sy2 = bleed;
|
|
949
1080
|
sWidth = max(1,sWidth|0);
|
package/src/engineExport.js
CHANGED
|
@@ -51,6 +51,7 @@ export
|
|
|
51
51
|
cameraPos,
|
|
52
52
|
cameraAngle,
|
|
53
53
|
cameraScale,
|
|
54
|
+
timeScale,
|
|
54
55
|
canvasColorTiles,
|
|
55
56
|
canvasClearColor,
|
|
56
57
|
canvasMaxSize,
|
|
@@ -80,7 +81,7 @@ export
|
|
|
80
81
|
gamepadDirectionEmulateStick,
|
|
81
82
|
inputWASDEmulateDirection,
|
|
82
83
|
touchGamepadEnable,
|
|
83
|
-
|
|
84
|
+
touchGamepadCenterButtonSize,
|
|
84
85
|
touchGamepadAnalog,
|
|
85
86
|
touchGamepadSize,
|
|
86
87
|
touchGamepadAlpha,
|
|
@@ -98,6 +99,7 @@ export
|
|
|
98
99
|
setCameraPos,
|
|
99
100
|
setCameraAngle,
|
|
100
101
|
setCameraScale,
|
|
102
|
+
setTimeScale,
|
|
101
103
|
setCanvasColorTiles,
|
|
102
104
|
setCanvasClearColor,
|
|
103
105
|
setCanvasMaxSize,
|
|
@@ -128,7 +130,7 @@ export
|
|
|
128
130
|
setGamepadDirectionEmulateStick,
|
|
129
131
|
setInputWASDEmulateDirection,
|
|
130
132
|
setTouchGamepadEnable,
|
|
131
|
-
|
|
133
|
+
setTouchGamepadCenterButtonSize,
|
|
132
134
|
setTouchGamepadButtonCount,
|
|
133
135
|
setTouchGamepadAnalog,
|
|
134
136
|
setTouchGamepadSize,
|
|
@@ -168,10 +170,12 @@ export
|
|
|
168
170
|
distanceAngle,
|
|
169
171
|
lerpAngle,
|
|
170
172
|
lerp,
|
|
173
|
+
percentLerp,
|
|
171
174
|
smoothStep,
|
|
172
175
|
nearestPowerOfTwo,
|
|
173
176
|
isOverlapping,
|
|
174
177
|
isIntersecting,
|
|
178
|
+
lineTest,
|
|
175
179
|
oscillate,
|
|
176
180
|
|
|
177
181
|
// Utilities
|
|
@@ -244,6 +248,7 @@ export
|
|
|
244
248
|
drawTile,
|
|
245
249
|
drawRect,
|
|
246
250
|
drawRectGradient,
|
|
251
|
+
drawTextureWrapped,
|
|
247
252
|
drawLineList,
|
|
248
253
|
drawLine,
|
|
249
254
|
drawPoly,
|
|
@@ -310,6 +315,8 @@ export
|
|
|
310
315
|
gamepadStick,
|
|
311
316
|
gamepadDpad,
|
|
312
317
|
gamepadConnected,
|
|
318
|
+
gamepadVibrate,
|
|
319
|
+
gamepadVibrateStop,
|
|
313
320
|
vibrate,
|
|
314
321
|
vibrateStop,
|
|
315
322
|
pointerLockRequest,
|
package/src/engineInput.js
CHANGED
|
@@ -260,6 +260,32 @@ function gamepadStickCount(gamepad=gamepadPrimary)
|
|
|
260
260
|
return gamepadStickData[gamepad]?.length ?? 0;
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
/** Pulse a gamepad's vibration hardware using the dual-rumble effect if it exists
|
|
264
|
+
* Strong magnitude is usually the left side motor, weak magnitude is usually the right side motor
|
|
265
|
+
* @param {number} [gamepad] - gamepad index
|
|
266
|
+
* @param {number} [duration] - effect duration in ms
|
|
267
|
+
* @param {number} [strongMagnitude] - strong (left) motor intensity, 0 to 1
|
|
268
|
+
* @param {number} [weakMagnitude] - weak (right) motor intensity, 0 to 1
|
|
269
|
+
* @param {number} [startDelay] - delay in ms before the effect starts
|
|
270
|
+
* @memberof Input */
|
|
271
|
+
function gamepadVibrate(gamepad=gamepadPrimary, duration=200, strongMagnitude=1, weakMagnitude=1, startDelay=0)
|
|
272
|
+
{
|
|
273
|
+
ASSERT(isNumber(gamepad), 'gamepad must be a number');
|
|
274
|
+
if (!vibrateEnable || headlessMode) return;
|
|
275
|
+
const pad = navigator?.getGamepads?.()[gamepad];
|
|
276
|
+
pad?.vibrationActuator?.playEffect?.('dual-rumble', {duration, strongMagnitude, weakMagnitude, startDelay});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Stop vibration on a gamepad
|
|
280
|
+
* @memberof Input */
|
|
281
|
+
function gamepadVibrateStop(gamepad=gamepadPrimary)
|
|
282
|
+
{
|
|
283
|
+
ASSERT(isNumber(gamepad), 'gamepad must be a number');
|
|
284
|
+
if (!vibrateEnable || headlessMode) return;
|
|
285
|
+
const pad = navigator?.getGamepads?.()[gamepad];
|
|
286
|
+
pad?.vibrationActuator?.reset?.();
|
|
287
|
+
}
|
|
288
|
+
|
|
263
289
|
///////////////////////////////////////////////////////////////////////////////
|
|
264
290
|
|
|
265
291
|
/** Pulse the vibration hardware if it exists
|
|
@@ -497,7 +523,7 @@ function inputInit()
|
|
|
497
523
|
if (touching)
|
|
498
524
|
{
|
|
499
525
|
touchGamepadTimer.set();
|
|
500
|
-
if (
|
|
526
|
+
if (touchGamepadCenterButtonSize && !wasTouching && paused)
|
|
501
527
|
{
|
|
502
528
|
// touch anywhere to press start when paused
|
|
503
529
|
touchGamepadButtons[9] = 1;
|
|
@@ -522,6 +548,7 @@ function inputInit()
|
|
|
522
548
|
// virtual analog stick
|
|
523
549
|
const delta = touchPos.subtract(stickCenter);
|
|
524
550
|
touchGamepadSticks[0] = delta.scale(2/touchGamepadSize).clampLength();
|
|
551
|
+
touchGamepadButtons[10] = 1; // also press a button when touching stick
|
|
525
552
|
}
|
|
526
553
|
else if (buttonCenter.distance(touchPos) < touchGamepadSize)
|
|
527
554
|
{
|
|
@@ -530,6 +557,7 @@ function inputInit()
|
|
|
530
557
|
// virtual right analog stick
|
|
531
558
|
const delta = touchPos.subtract(buttonCenter);
|
|
532
559
|
touchGamepadSticks[1] = delta.scale(2/touchGamepadSize).clampLength();
|
|
560
|
+
touchGamepadButtons[11] = 1; // also press a button when touching right stick
|
|
533
561
|
}
|
|
534
562
|
// virtual face buttons
|
|
535
563
|
let button = buttonCenter.subtract(touchPos).direction();
|
|
@@ -546,8 +574,7 @@ function inputInit()
|
|
|
546
574
|
if (button < touchGamepadButtonCount)
|
|
547
575
|
touchGamepadButtons[button] = 1;
|
|
548
576
|
}
|
|
549
|
-
else if (
|
|
550
|
-
startCenter.distance(touchPos) < touchGamepadSize)
|
|
577
|
+
else if (startCenter.distance(touchPos) < touchGamepadCenterButtonSize)
|
|
551
578
|
{
|
|
552
579
|
// virtual start button in center
|
|
553
580
|
touchGamepadButtons[9] = 1;
|
|
@@ -596,6 +623,18 @@ function inputUpdate()
|
|
|
596
623
|
// update touch gamepad if enabled
|
|
597
624
|
if (touchGamepadEnable && isTouchDevice)
|
|
598
625
|
{
|
|
626
|
+
if (debugGamepads)
|
|
627
|
+
{
|
|
628
|
+
const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
|
|
629
|
+
const buttonCenter = touchGamepadButtonCenter();
|
|
630
|
+
const startCenter = mainCanvasSize.scale(.5);
|
|
631
|
+
|
|
632
|
+
debugCircle(stickCenter, 2*touchGamepadSize, 'cyan', 0, false, true);
|
|
633
|
+
debugCircle(buttonCenter, 2*touchGamepadSize, 'cyan', 0, false, true);
|
|
634
|
+
if (touchGamepadCenterButtonSize)
|
|
635
|
+
debugCircle(startCenter, 2*touchGamepadCenterButtonSize, 'cyan', 0, false, true);
|
|
636
|
+
}
|
|
637
|
+
|
|
599
638
|
if (!touchGamepadTimer.isSet()) return;
|
|
600
639
|
|
|
601
640
|
// read virtual analog stick
|
|
@@ -623,7 +662,7 @@ function inputUpdate()
|
|
|
623
662
|
|
|
624
663
|
// read virtual gamepad buttons
|
|
625
664
|
const data = inputData[1] ?? (inputData[1] = []);
|
|
626
|
-
for (let i=
|
|
665
|
+
for (let i=12; i--;)
|
|
627
666
|
{
|
|
628
667
|
const wasDown = gamepadIsDown(i,0);
|
|
629
668
|
data[i] = touchGamepadButtons[i] ? wasDown ? 1 : 3 : wasDown ? 4 : 0;
|
package/src/engineObject.js
CHANGED
package/src/engineSettings.js
CHANGED
|
@@ -27,6 +27,18 @@ let cameraAngle = 0;
|
|
|
27
27
|
* @memberof Settings */
|
|
28
28
|
let cameraScale = 32;
|
|
29
29
|
|
|
30
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
31
|
+
// Time settings
|
|
32
|
+
|
|
33
|
+
/** Scale applied to engine time, can be used for slow motion or fast forward
|
|
34
|
+
* - 1 is normal speed, 2 is double speed, 0.5 is half speed
|
|
35
|
+
* - 0 freezes the simulation without setting the paused flag
|
|
36
|
+
* - Should be >= 0; stacks multiplicatively with the debug +/- shortcut
|
|
37
|
+
* @type {number}
|
|
38
|
+
* @default
|
|
39
|
+
* @memberof Settings */
|
|
40
|
+
let timeScale = 1;
|
|
41
|
+
|
|
30
42
|
///////////////////////////////////////////////////////////////////////////////
|
|
31
43
|
// Display settings
|
|
32
44
|
|
|
@@ -230,18 +242,22 @@ let touchInputEnable = true;
|
|
|
230
242
|
|
|
231
243
|
/** True if touch gamepad should appear on mobile devices
|
|
232
244
|
* - Supports left analog stick, 4 face buttons and start button (button 9)
|
|
245
|
+
* - setTouchGamepadButtonCount(1) to use face buttons as right analog stick
|
|
246
|
+
* - Analog stick buttons 10 and 11 are also activated when virtual sticks are touched
|
|
247
|
+
|
|
233
248
|
* @type {boolean}
|
|
234
249
|
* @default
|
|
235
250
|
* @memberof Settings */
|
|
236
251
|
let touchGamepadEnable = false;
|
|
237
252
|
|
|
238
253
|
/** True if touch gamepad should have start button in the center
|
|
254
|
+
* - Prevents activating if overlappng with virtual stick or buttons if they are enabled
|
|
239
255
|
* - When the game is paused, any touch will press the button
|
|
240
|
-
* -
|
|
241
|
-
* @type {
|
|
256
|
+
* - Set size to enable the center button
|
|
257
|
+
* @type {number}
|
|
242
258
|
* @default
|
|
243
259
|
* @memberof Settings */
|
|
244
|
-
let
|
|
260
|
+
let touchGamepadCenterButtonSize = 300;
|
|
245
261
|
|
|
246
262
|
/** Number of buttons on touch gamepad (0-4), if 1 also acts as right analog stick
|
|
247
263
|
* @type {number}
|
|
@@ -259,7 +275,7 @@ let touchGamepadAnalog = true;
|
|
|
259
275
|
* @type {number}
|
|
260
276
|
* @default
|
|
261
277
|
* @memberof Settings */
|
|
262
|
-
let touchGamepadSize =
|
|
278
|
+
let touchGamepadSize = 100;
|
|
263
279
|
|
|
264
280
|
/** Transparency of touch gamepad overlay
|
|
265
281
|
* @type {number}
|
|
@@ -351,6 +367,11 @@ function setCameraAngle(angle) { cameraAngle = angle; }
|
|
|
351
367
|
* @memberof Settings */
|
|
352
368
|
function setCameraScale(scale) { cameraScale = scale; }
|
|
353
369
|
|
|
370
|
+
/** Set scale applied to engine time
|
|
371
|
+
* @param {number} scale
|
|
372
|
+
* @memberof Settings */
|
|
373
|
+
function setTimeScale(scale) { timeScale = scale; }
|
|
374
|
+
|
|
354
375
|
/** Set if tiles should be colorized when using canvas2d
|
|
355
376
|
* This can be slower but results should look nearly identical to WebGL rendering
|
|
356
377
|
* It can be enabled/disabled at any time
|
|
@@ -527,11 +548,12 @@ function setTouchInputEnable(enable) { touchInputEnable = enable; }
|
|
|
527
548
|
* @memberof Settings */
|
|
528
549
|
function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
|
|
529
550
|
|
|
530
|
-
/**
|
|
531
|
-
* -
|
|
532
|
-
*
|
|
551
|
+
/** Set if touch gamepad should have start button in the center
|
|
552
|
+
* - Set size to enable the center button
|
|
553
|
+
* - When the game is paused, any touch will press the button
|
|
554
|
+
* @param {number} size
|
|
533
555
|
* @memberof Settings */
|
|
534
|
-
function
|
|
556
|
+
function setTouchGamepadCenterButtonSize(size) { touchGamepadCenterButtonSize = size; }
|
|
535
557
|
|
|
536
558
|
/** Set number of buttons on touch gamepad (0-4), if 1 also acts as right analog stick
|
|
537
559
|
* @param {number} count
|
package/src/engineWebGL.js
CHANGED
|
@@ -304,9 +304,8 @@ function glClearCanvas()
|
|
|
304
304
|
/** Set the WebGL texture, called automatically if using multiple textures
|
|
305
305
|
* - This may also flush the gl buffer resulting in more draw calls and worse performance
|
|
306
306
|
* @param {WebGLTexture} texture
|
|
307
|
-
* @param {boolean} [wrap] - Should the texture wrap or clamp
|
|
308
307
|
* @memberof WebGL */
|
|
309
|
-
function glSetTexture(texture
|
|
308
|
+
function glSetTexture(texture)
|
|
310
309
|
{
|
|
311
310
|
// must flush cache with the old texture to set a new one
|
|
312
311
|
if (!glContext || texture === glActiveTexture) return;
|
|
@@ -314,11 +313,6 @@ function glSetTexture(texture, wrap=false)
|
|
|
314
313
|
glFlush();
|
|
315
314
|
glActiveTexture = texture;
|
|
316
315
|
glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
|
|
317
|
-
|
|
318
|
-
// set wrap mode
|
|
319
|
-
const wrapMode = wrap ? glContext.REPEAT : glContext.CLAMP_TO_EDGE;
|
|
320
|
-
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_S, wrapMode);
|
|
321
|
-
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_T, wrapMode);
|
|
322
316
|
}
|
|
323
317
|
|
|
324
318
|
/** Compile WebGL shader of the given type, will throw errors if in debug mode
|
|
@@ -393,6 +387,8 @@ function glCreateTexture(image)
|
|
|
393
387
|
const minFilter = mipMap ? glContext.LINEAR_MIPMAP_LINEAR : magFilter;
|
|
394
388
|
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, magFilter);
|
|
395
389
|
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, minFilter);
|
|
390
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_S, glContext.REPEAT);
|
|
391
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_T, glContext.REPEAT);
|
|
396
392
|
if (mipMap)
|
|
397
393
|
glContext.generateMipmap(glContext.TEXTURE_2D);
|
|
398
394
|
|