littlejsengine 1.6.4 → 1.6.6
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/README.md +13 -9
- package/build/littlejs.d.ts +92 -88
- package/build/littlejs.esm.js +312 -251
- package/build/littlejs.esm.min.js +1 -1
- package/build/littlejs.js +270 -206
- package/build/littlejs.min.js +1 -1
- package/build/littlejs.release.js +271 -203
- package/examples/breakout/index.html +3 -3
- package/examples/breakoutTutorial/index.html +2 -2
- package/examples/favicon.png +0 -0
- package/examples/module/index.html +1 -1
- package/examples/particles/index.html +1 -1
- package/examples/platformer/index.html +6 -6
- package/examples/puzzle/game.js +1 -1
- package/examples/puzzle/index.html +2 -2
- package/examples/starter/index.html +13 -13
- package/examples/stress/index.html +1 -1
- package/examples/typescript/index.html +1 -1
- package/package.json +2 -2
- package/src/engine.js +29 -30
- package/src/engineAudio.js +42 -18
- package/src/engineDebug.js +17 -22
- package/src/engineDraw.js +24 -24
- package/src/engineExport.js +42 -45
- package/src/engineInput.js +32 -19
- package/src/engineMedals.js +31 -8
- package/src/engineObject.js +21 -21
- package/src/engineParticles.js +3 -6
- package/src/engineRelease.js +18 -19
- package/src/engineSettings.js +4 -4
- package/src/engineTileLayer.js +18 -14
- package/src/engineUtilities.js +41 -32
- package/src/engineWebGL.js +8 -8
package/build/littlejs.esm.js
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
/*
|
|
2
|
-
LittleJS - Debug Build
|
|
3
|
-
MIT License - Copyright 2021 Frank Force
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* LittleJS Debug System
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
3
|
+
* - Press ~ to show debug overlay with mouse pick
|
|
4
|
+
* - Number keys toggle debug functions
|
|
5
|
+
* - +/- apply time scale
|
|
6
|
+
* - Debug primitive rendering
|
|
7
|
+
* - Save a 2d canvas as an image
|
|
13
8
|
* @namespace Debug
|
|
14
9
|
*/
|
|
15
10
|
|
|
@@ -62,7 +57,7 @@ debugParticles = 0, debugGamepads = 0, debugMedals = 0, debugTakeScreenshot, dow
|
|
|
62
57
|
* @param {Boolean} assertion
|
|
63
58
|
* @param {Object} output
|
|
64
59
|
* @memberof Debug */
|
|
65
|
-
|
|
60
|
+
function ASSERT(...assert) { enableAsserts && console.assert(...assert); }
|
|
66
61
|
|
|
67
62
|
/** Draw a debug rectangle in world space
|
|
68
63
|
* @param {Vector2} pos
|
|
@@ -72,7 +67,7 @@ const ASSERT = enableAsserts ? (...assert)=> console.assert(...assert) : ()=>{};
|
|
|
72
67
|
* @param {Number} [angle=0]
|
|
73
68
|
* @param {Boolean} [fill=false]
|
|
74
69
|
* @memberof Debug */
|
|
75
|
-
|
|
70
|
+
function debugRect(pos, size=vec2(), color='#fff', time=0, angle=0, fill=false)
|
|
76
71
|
{
|
|
77
72
|
ASSERT(typeof color == 'string'); // pass in regular html strings as colors
|
|
78
73
|
debugPrimitives.push({pos, size:vec2(size), color, time:new Timer(time), angle, fill});
|
|
@@ -85,7 +80,7 @@ const debugRect = (pos, size=vec2(), color='#fff', time=0, angle=0, fill=false)=
|
|
|
85
80
|
* @param {Number} [time=0]
|
|
86
81
|
* @param {Boolean} [fill=false]
|
|
87
82
|
* @memberof Debug */
|
|
88
|
-
|
|
83
|
+
function debugCircle(pos, radius=0, color='#fff', time=0, fill=false)
|
|
89
84
|
{
|
|
90
85
|
ASSERT(typeof color == 'string'); // pass in regular html strings as colors
|
|
91
86
|
debugPrimitives.push({pos, size:radius, color, time:new Timer(time), angle:0, fill});
|
|
@@ -97,7 +92,7 @@ const debugCircle = (pos, radius=0, color='#fff', time=0, fill=false)=>
|
|
|
97
92
|
* @param {Number} [time=0]
|
|
98
93
|
* @param {Number} [angle=0]
|
|
99
94
|
* @memberof Debug */
|
|
100
|
-
|
|
95
|
+
function debugPoint(pos, color, time, angle) {debugRect(pos, 0, color, time, angle);}
|
|
101
96
|
|
|
102
97
|
/** Draw a debug line in world space
|
|
103
98
|
* @param {Vector2} posA
|
|
@@ -106,7 +101,7 @@ const debugPoint = (pos, color, time, angle)=> debugRect(pos, 0, color, time, an
|
|
|
106
101
|
* @param {Number} [thickness=.1]
|
|
107
102
|
* @param {Number} [time=0]
|
|
108
103
|
* @memberof Debug */
|
|
109
|
-
|
|
104
|
+
function debugLine(posA, posB, color, thickness=.1, time)
|
|
110
105
|
{
|
|
111
106
|
const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
|
|
112
107
|
const size = vec2(thickness, halfDelta.length()*2);
|
|
@@ -120,7 +115,7 @@ const debugLine = (posA, posB, color, thickness=.1, time)=>
|
|
|
120
115
|
* @param {Vector2} sizeB
|
|
121
116
|
* @param {String} [color='#fff']
|
|
122
117
|
* @memberof Debug */
|
|
123
|
-
|
|
118
|
+
function debugAABB(pA, sA, pB, sB, color)
|
|
124
119
|
{
|
|
125
120
|
const minPos = vec2(min(pA.x - sA.x/2, pB.x - sB.x/2), min(pA.y - sA.y/2, pB.y - sB.y/2));
|
|
126
121
|
const maxPos = vec2(max(pA.x + sA.x/2, pB.x + sB.x/2), max(pA.y + sA.y/2, pB.y + sB.y/2));
|
|
@@ -136,7 +131,7 @@ const debugAABB = (pA, sA, pB, sB, color)=>
|
|
|
136
131
|
* @param {Number} [angle=0]
|
|
137
132
|
* @param {String} [font='monospace']
|
|
138
133
|
* @memberof Debug */
|
|
139
|
-
|
|
134
|
+
function debugText(text, pos, size=1, color='#fff', time=0, angle=0, font='monospace')
|
|
140
135
|
{
|
|
141
136
|
ASSERT(typeof color == 'string'); // pass in regular html strings as colors
|
|
142
137
|
debugPrimitives.push({text, pos, size, color, time:new Timer(time), angle, font});
|
|
@@ -144,13 +139,13 @@ const debugText = (text, pos, size=1, color='#fff', time=0, angle=0, font='monos
|
|
|
144
139
|
|
|
145
140
|
/** Clear all debug primitives in the list
|
|
146
141
|
* @memberof Debug */
|
|
147
|
-
|
|
142
|
+
function debugClear() { debugPrimitives = []; }
|
|
148
143
|
|
|
149
144
|
/** Save a canvas to disk
|
|
150
145
|
* @param {HTMLCanvasElement} canvas
|
|
151
146
|
* @param {String} [filename]
|
|
152
147
|
* @memberof Debug */
|
|
153
|
-
|
|
148
|
+
function debugSaveCanvas(canvas, filename = engineName + '.png')
|
|
154
149
|
{
|
|
155
150
|
downloadLink.download = 'screenshot.png';
|
|
156
151
|
downloadLink.href = canvas.toDataURL('image/png').replace('image/png','image/octet-stream');
|
|
@@ -160,14 +155,14 @@ const debugSaveCanvas = (canvas, filename = engineName + '.png') =>
|
|
|
160
155
|
///////////////////////////////////////////////////////////////////////////////
|
|
161
156
|
// Engine debug function (called automatically)
|
|
162
157
|
|
|
163
|
-
|
|
158
|
+
function debugInit()
|
|
164
159
|
{
|
|
165
160
|
// create link for saving screenshots
|
|
166
161
|
document.body.appendChild(downloadLink = document.createElement('a'));
|
|
167
162
|
downloadLink.style.display = 'none';
|
|
168
163
|
}
|
|
169
164
|
|
|
170
|
-
|
|
165
|
+
function debugUpdate()
|
|
171
166
|
{
|
|
172
167
|
if (!debug)
|
|
173
168
|
return;
|
|
@@ -195,7 +190,7 @@ const debugUpdate = ()=>
|
|
|
195
190
|
}
|
|
196
191
|
}
|
|
197
192
|
|
|
198
|
-
|
|
193
|
+
function debugRender()
|
|
199
194
|
{
|
|
200
195
|
glCopyToContext(mainContext);
|
|
201
196
|
|
|
@@ -399,10 +394,10 @@ const debugRender = ()=>
|
|
|
399
394
|
}
|
|
400
395
|
/**
|
|
401
396
|
* LittleJS Utility Classes and Functions
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
397
|
+
* - General purpose math library
|
|
398
|
+
* - Vector2 - fast, simple, easy 2D vector class
|
|
399
|
+
* - Color - holds a rgba color with some math functions
|
|
400
|
+
* - Timer - tracks time automatically
|
|
406
401
|
* @namespace Utilities
|
|
407
402
|
*/
|
|
408
403
|
|
|
@@ -418,34 +413,34 @@ const PI = Math.PI;
|
|
|
418
413
|
* @param {Number} value
|
|
419
414
|
* @return {Number}
|
|
420
415
|
* @memberof Utilities */
|
|
421
|
-
|
|
416
|
+
function abs(a) { return a < 0 ? -a : a; }
|
|
422
417
|
|
|
423
418
|
/** Returns lowest of two values passed in
|
|
424
419
|
* @param {Number} valueA
|
|
425
420
|
* @param {Number} valueB
|
|
426
421
|
* @return {Number}
|
|
427
422
|
* @memberof Utilities */
|
|
428
|
-
|
|
423
|
+
function min(a, b) { return a < b ? a : b; }
|
|
429
424
|
|
|
430
425
|
/** Returns highest of two values passed in
|
|
431
426
|
* @param {Number} valueA
|
|
432
427
|
* @param {Number} valueB
|
|
433
428
|
* @return {Number}
|
|
434
429
|
* @memberof Utilities */
|
|
435
|
-
|
|
430
|
+
function max(a, b) { return a > b ? a : b; }
|
|
436
431
|
|
|
437
432
|
/** Returns the sign of value passed in (also returns 1 if 0)
|
|
438
433
|
* @param {Number} value
|
|
439
434
|
* @return {Number}
|
|
440
435
|
* @memberof Utilities */
|
|
441
|
-
|
|
436
|
+
function sign(a) { return a < 0 ? -1 : 1; }
|
|
442
437
|
|
|
443
438
|
/** Returns first parm modulo the second param, but adjusted so negative numbers work as expected
|
|
444
439
|
* @param {Number} dividend
|
|
445
440
|
* @param {Number} [divisor=1]
|
|
446
441
|
* @return {Number}
|
|
447
442
|
* @memberof Utilities */
|
|
448
|
-
|
|
443
|
+
function mod(a, b=1) { return ((a % b) + b) % b; }
|
|
449
444
|
|
|
450
445
|
/** Clamps the value beween max and min
|
|
451
446
|
* @param {Number} value
|
|
@@ -453,7 +448,8 @@ const mod = (a, b=1)=> ((a % b) + b) % b;
|
|
|
453
448
|
* @param {Number} [max=1]
|
|
454
449
|
* @return {Number}
|
|
455
450
|
* @memberof Utilities */
|
|
456
|
-
|
|
451
|
+
function clamp(v, min=0, max=1)
|
|
452
|
+
{ return v < min ? min : v > max ? max : v; }
|
|
457
453
|
|
|
458
454
|
/** Returns what percentage the value is between max and min
|
|
459
455
|
* @param {Number} value
|
|
@@ -461,7 +457,8 @@ const clamp = (v, min=0, max=1)=> v < min ? min : v > max ? max : v;
|
|
|
461
457
|
* @param {Number} [max=1]
|
|
462
458
|
* @return {Number}
|
|
463
459
|
* @memberof Utilities */
|
|
464
|
-
|
|
460
|
+
function percent(v, min=0, max=1)
|
|
461
|
+
{ return max-min ? clamp((v-min) / (max-min)) : 0; }
|
|
465
462
|
|
|
466
463
|
/** Linearly interpolates the percent value between max and min
|
|
467
464
|
* @param {Number} percent
|
|
@@ -469,19 +466,19 @@ const percent = (v, min=0, max=1)=> max-min ? clamp((v-min) / (max-min)) : 0;
|
|
|
469
466
|
* @param {Number} [max=1]
|
|
470
467
|
* @return {Number}
|
|
471
468
|
* @memberof Utilities */
|
|
472
|
-
|
|
469
|
+
function lerp(p, min=0, max=1){ return min + clamp(p) * (max-min); }
|
|
473
470
|
|
|
474
471
|
/** Applies smoothstep function to the percentage value
|
|
475
472
|
* @param {Number} value
|
|
476
473
|
* @return {Number}
|
|
477
474
|
* @memberof Utilities */
|
|
478
|
-
|
|
475
|
+
function smoothStep(p) { return p * p * (3 - 2 * p); }
|
|
479
476
|
|
|
480
477
|
/** Returns the nearest power of two not less then the value
|
|
481
478
|
* @param {Number} value
|
|
482
479
|
* @return {Number}
|
|
483
480
|
* @memberof Utilities */
|
|
484
|
-
|
|
481
|
+
function nearestPowerOfTwo(v) { return 2**Math.ceil(Math.log2(v)); }
|
|
485
482
|
|
|
486
483
|
/** Returns true if two axis aligned bounding boxes are overlapping
|
|
487
484
|
* @param {Vector2} pointA - Center of box A
|
|
@@ -490,7 +487,8 @@ const nearestPowerOfTwo = (v)=> 2**Math.ceil(Math.log2(v));
|
|
|
490
487
|
* @param {Vector2} [sizeB] - Size of box B
|
|
491
488
|
* @return {Boolean} - True if overlapping
|
|
492
489
|
* @memberof Utilities */
|
|
493
|
-
|
|
490
|
+
function isOverlapping(pA, sA, pB, sB)
|
|
491
|
+
{ return abs(pA.x - pB.x)*2 < sA.x + sB.x && abs(pA.y - pB.y)*2 < sA.y + sB.y; }
|
|
494
492
|
|
|
495
493
|
/** Returns an oscillating wave between 0 and amplitude with frequency of 1 Hz by default
|
|
496
494
|
* @param {Number} [frequency=1] - Frequency of the wave in Hz
|
|
@@ -498,13 +496,14 @@ const isOverlapping = (pA, sA, pB, sB)=> abs(pA.x - pB.x)*2 < sA.x + sB.x && abs
|
|
|
498
496
|
* @param {Number} [t=time] - Value to use for time of the wave
|
|
499
497
|
* @return {Number} - Value waving between 0 and amplitude
|
|
500
498
|
* @memberof Utilities */
|
|
501
|
-
|
|
499
|
+
function wave(frequency=1, amplitude=1, t=time)
|
|
500
|
+
{ return amplitude/2 * (1 - Math.cos(t*frequency*2*PI)); }
|
|
502
501
|
|
|
503
502
|
/** Formats seconds to mm:ss style for display purposes
|
|
504
503
|
* @param {Number} t - time in seconds
|
|
505
504
|
* @return {String}
|
|
506
505
|
* @memberof Utilities */
|
|
507
|
-
|
|
506
|
+
function formatTime(t) { return (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0); }
|
|
508
507
|
|
|
509
508
|
///////////////////////////////////////////////////////////////////////////////
|
|
510
509
|
|
|
@@ -516,32 +515,33 @@ const formatTime = (t)=> (t/60|0) + ':' + (t%60<10?'0':'') + (t%60|0);
|
|
|
516
515
|
* @param {Number} [valueB=0]
|
|
517
516
|
* @return {Number}
|
|
518
517
|
* @memberof Random */
|
|
519
|
-
|
|
518
|
+
function rand(a=1, b=0) { return b + (a-b)*Math.random(); }
|
|
520
519
|
|
|
521
520
|
/** Returns a floored random value the two values passed in
|
|
522
521
|
* @param {Number} [valueA=1]
|
|
523
522
|
* @param {Number} [valueB=0]
|
|
524
523
|
* @return {Number}
|
|
525
524
|
* @memberof Random */
|
|
526
|
-
|
|
525
|
+
function randInt(a=1, b=0) { return rand(a,b)|0; }
|
|
527
526
|
|
|
528
527
|
/** Randomly returns either -1 or 1
|
|
529
528
|
* @return {Number}
|
|
530
529
|
* @memberof Random */
|
|
531
|
-
|
|
530
|
+
function randSign() { return randInt(2) * 2 - 1; }
|
|
532
531
|
|
|
533
532
|
/** Returns a random Vector2 within a circular shape
|
|
534
533
|
* @param {Number} [radius=1]
|
|
535
534
|
* @param {Number} [minRadius=0]
|
|
536
535
|
* @return {Vector2}
|
|
537
536
|
* @memberof Random */
|
|
538
|
-
|
|
537
|
+
function randInCircle(radius=1, minRadius=0)
|
|
538
|
+
{ return radius > 0 ? randVector(radius * rand(minRadius / radius, 1)**.5) : new Vector2; }
|
|
539
539
|
|
|
540
540
|
/** Returns a random Vector2 with the passed in length
|
|
541
541
|
* @param {Number} [length=1]
|
|
542
542
|
* @return {Vector2}
|
|
543
543
|
* @memberof Random */
|
|
544
|
-
|
|
544
|
+
function randVector(length=1) { return new Vector2().setAngle(rand(2*PI), length); }
|
|
545
545
|
|
|
546
546
|
/** Returns a random color between the two passed in colors, combine components if linear
|
|
547
547
|
* @param {Color} [colorA=Color()]
|
|
@@ -549,8 +549,8 @@ const randVector = (length=1)=> new Vector2().setAngle(rand(2*PI), length);
|
|
|
549
549
|
* @param {Boolean} [linear]
|
|
550
550
|
* @return {Color}
|
|
551
551
|
* @memberof Random */
|
|
552
|
-
|
|
553
|
-
|
|
552
|
+
function randColor(cA = new Color, cB = new Color(0,0,0,1), linear)
|
|
553
|
+
{ return linear ? cA.lerp(cB, rand()) : new Color(rand(cA.r,cB.r),rand(cA.g,cB.g),rand(cA.b,cB.b),rand(cA.a,cB.a)); }
|
|
554
554
|
|
|
555
555
|
/** Seed used by the randSeeded function
|
|
556
556
|
* @type {Number}
|
|
@@ -561,16 +561,19 @@ let randSeed = 1;
|
|
|
561
561
|
/** Set seed used by the randSeeded function, should not be 0
|
|
562
562
|
* @param {Number} seed
|
|
563
563
|
* @memberof Random */
|
|
564
|
-
|
|
564
|
+
function setRandSeed(seed) { randSeed = seed; }
|
|
565
565
|
|
|
566
566
|
/** Returns a seeded random value between the two values passed in using randSeed
|
|
567
567
|
* @param {Number} [valueA=1]
|
|
568
568
|
* @param {Number} [valueB=0]
|
|
569
569
|
* @return {Number}
|
|
570
570
|
* @memberof Random */
|
|
571
|
-
|
|
571
|
+
function randSeeded(a=1, b=0)
|
|
572
572
|
{
|
|
573
|
-
|
|
573
|
+
// xorshift algorithm
|
|
574
|
+
randSeed ^= randSeed << 13;
|
|
575
|
+
randSeed ^= randSeed >>> 17;
|
|
576
|
+
randSeed ^= randSeed << 5;
|
|
574
577
|
return b + (a-b) * abs(randSeed % 1e9) / 1e9;
|
|
575
578
|
}
|
|
576
579
|
|
|
@@ -588,7 +591,8 @@ const randSeeded = (a=1, b=0)=>
|
|
|
588
591
|
* b = vec2(); // set b to (0, 0)
|
|
589
592
|
* @memberof Utilities
|
|
590
593
|
*/
|
|
591
|
-
|
|
594
|
+
function vec2(x=0, y)
|
|
595
|
+
{ return x.x == undefined ? new Vector2(x, y == undefined? x : y) : new Vector2(x.x, x.y); }
|
|
592
596
|
|
|
593
597
|
/**
|
|
594
598
|
* Check if object is a valid Vector2
|
|
@@ -596,11 +600,11 @@ const vec2 = (x=0, y)=> x.x == undefined ? new Vector2(x, y == undefined? x : y)
|
|
|
596
600
|
* @return {Boolean}
|
|
597
601
|
* @memberof Utilities
|
|
598
602
|
*/
|
|
599
|
-
|
|
603
|
+
function isVector2(v) { return !isNaN(v.x) && !isNaN(v.y); }
|
|
600
604
|
|
|
601
605
|
/**
|
|
602
606
|
* 2D Vector object with vector math library
|
|
603
|
-
*
|
|
607
|
+
* - Functions do not change this so they can be chained together
|
|
604
608
|
* @example
|
|
605
609
|
* let a = new Vector2(2, 3); // vector with coordinates (2, 3)
|
|
606
610
|
* let b = new Vector2; // vector with coordinates (0, 0)
|
|
@@ -747,7 +751,7 @@ class Vector2
|
|
|
747
751
|
* @return {Color}
|
|
748
752
|
* @memberof Utilities
|
|
749
753
|
*/
|
|
750
|
-
|
|
754
|
+
function rgb(r, g, b, a) { return new Color(r, g, b, a); }
|
|
751
755
|
|
|
752
756
|
/**
|
|
753
757
|
* Create a color object with HSLA values
|
|
@@ -758,7 +762,7 @@ const rgb = (r, g, b, a)=> new Color(r, g, b, a);
|
|
|
758
762
|
* @return {Color}
|
|
759
763
|
* @memberof Utilities
|
|
760
764
|
*/
|
|
761
|
-
|
|
765
|
+
function hsl(h, s, l, a) { return new Color().setHSLA(h, s, l, a); }
|
|
762
766
|
|
|
763
767
|
/**
|
|
764
768
|
* Color object (red, green, blue, alpha) with some helpful functions
|
|
@@ -1017,11 +1021,11 @@ let canvasMaxSize = vec2(1920, 1200);
|
|
|
1017
1021
|
* @memberof Settings */
|
|
1018
1022
|
let canvasFixedSize = vec2();
|
|
1019
1023
|
|
|
1020
|
-
/** Disables
|
|
1024
|
+
/** Disables filtering for crisper pixel art if true
|
|
1021
1025
|
* @type {Boolean}
|
|
1022
1026
|
* @default
|
|
1023
1027
|
* @memberof Settings */
|
|
1024
|
-
let
|
|
1028
|
+
let canvasPixelated = 1;
|
|
1025
1029
|
|
|
1026
1030
|
/** Default font used for text rendering
|
|
1027
1031
|
* @type {String}
|
|
@@ -1138,8 +1142,8 @@ let gamepadDirectionEmulateStick = 1;
|
|
|
1138
1142
|
let inputWASDEmulateDirection = 1;
|
|
1139
1143
|
|
|
1140
1144
|
/** True if touch gamepad should appear on mobile devices
|
|
1141
|
-
*
|
|
1142
|
-
*
|
|
1145
|
+
* - Supports left analog stick, 4 face buttons and start button (button 9)
|
|
1146
|
+
* - Must be set by end of gameInit to be activated
|
|
1143
1147
|
* @type {Boolean}
|
|
1144
1148
|
* @default 0
|
|
1145
1149
|
* @memberof Settings */
|
|
@@ -1228,32 +1232,32 @@ let medalDisplayIconSize = 50;
|
|
|
1228
1232
|
* @default 0
|
|
1229
1233
|
* @memberof Settings */
|
|
1230
1234
|
let medalsPreventUnlock;
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
*/
|
|
1235
|
+
/**
|
|
1236
|
+
* LittleJS Object System
|
|
1237
|
+
*/
|
|
1234
1238
|
|
|
1235
1239
|
'use strict';
|
|
1236
1240
|
|
|
1237
1241
|
/**
|
|
1238
1242
|
* LittleJS Object Base Object Class
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1243
|
-
*
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
*
|
|
1248
|
-
*
|
|
1249
|
-
*
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1243
|
+
* - Base object class used by the engine
|
|
1244
|
+
* - Automatically adds self to object list
|
|
1245
|
+
* - Will be updated and rendered each frame
|
|
1246
|
+
* - Renders as a sprite from a tilesheet by default
|
|
1247
|
+
* - Can have color and addtive color applied
|
|
1248
|
+
* - 2d Physics and collision system
|
|
1249
|
+
* - Sorted by renderOrder
|
|
1250
|
+
* - Objects can have children attached
|
|
1251
|
+
* - Parents are updated before children, and set child transform
|
|
1252
|
+
* - Call destroy() to get rid of objects
|
|
1253
|
+
*
|
|
1254
|
+
* The physics system used by objects is simple and fast with some caveats...
|
|
1255
|
+
* - Collision uses the axis aligned size, the object's rotation angle is only for rendering
|
|
1256
|
+
* - Objects are guaranteed to not intersect tile collision from physics
|
|
1257
|
+
* - If an object starts or is moved inside tile collision, it will not collide with that tile
|
|
1258
|
+
* - Collision for objects can be set to be solid to block other objects
|
|
1259
|
+
* - Objects may get pushed into overlapping other solid objects, if so they will push away
|
|
1260
|
+
* - Solid objects are more performance intensive and should be used sparingly
|
|
1257
1261
|
* @example
|
|
1258
1262
|
* // create an engine object, normally you would first extend the class with your own
|
|
1259
1263
|
* const pos = vec2(2,3);
|
|
@@ -1606,23 +1610,23 @@ class EngineObject
|
|
|
1606
1610
|
}
|
|
1607
1611
|
/**
|
|
1608
1612
|
* LittleJS Drawing System
|
|
1609
|
-
*
|
|
1610
|
-
*
|
|
1611
|
-
*
|
|
1612
|
-
*
|
|
1613
|
-
*
|
|
1614
|
-
*
|
|
1615
|
-
*
|
|
1616
|
-
*
|
|
1617
|
-
*
|
|
1618
|
-
*
|
|
1619
|
-
*
|
|
1620
|
-
*
|
|
1621
|
-
*
|
|
1622
|
-
*
|
|
1623
|
-
*
|
|
1624
|
-
*
|
|
1625
|
-
*
|
|
1613
|
+
* - Hybrid with both Canvas2D and WebGL available
|
|
1614
|
+
* - Super fast tile sheet rendering with WebGL
|
|
1615
|
+
* - Can apply rotation, mirror, color and additive color
|
|
1616
|
+
* - Many useful utility functions
|
|
1617
|
+
*
|
|
1618
|
+
* LittleJS uses a hybrid rendering solution with the best of both Canvas2D and WebGL.
|
|
1619
|
+
* There are 3 canvas/contexts available to draw to...
|
|
1620
|
+
* mainCanvas - 2D background canvas, non WebGL stuff like tile layers are drawn here.
|
|
1621
|
+
* glCanvas - Used by the accelerated WebGL batch rendering system.
|
|
1622
|
+
* overlayCanvas - Another 2D canvas that appears on top of the other 2 canvases.
|
|
1623
|
+
*
|
|
1624
|
+
* The WebGL rendering system is very fast with some caveats...
|
|
1625
|
+
* - The default setup supports only 1 tile sheet, to support more call glCreateTexture and glSetTexture
|
|
1626
|
+
* - Switching blend modes (additive) or textures causes another draw call which is expensive in excess
|
|
1627
|
+
* - Group additive rendering together using renderOrder to mitigate this issue
|
|
1628
|
+
*
|
|
1629
|
+
* The LittleJS rendering solution is intentionally simple, feel free to adjust it for your needs!
|
|
1626
1630
|
* @namespace Draw
|
|
1627
1631
|
*/
|
|
1628
1632
|
|
|
@@ -1666,7 +1670,7 @@ let tileImageSize, tileImageFixBleed, drawCount;
|
|
|
1666
1670
|
* @param {Vector2} screenPos
|
|
1667
1671
|
* @return {Vector2}
|
|
1668
1672
|
* @memberof Draw */
|
|
1669
|
-
|
|
1673
|
+
function screenToWorld(screenPos)
|
|
1670
1674
|
{
|
|
1671
1675
|
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1672
1676
|
return screenPos.add(vec2(.5)).subtract(mainCanvasSize.scale(.5)).multiply(vec2(1/cameraScale,-1/cameraScale)).add(cameraPos);
|
|
@@ -1677,7 +1681,7 @@ const screenToWorld = (screenPos)=>
|
|
|
1677
1681
|
* @param {Vector2} worldPos
|
|
1678
1682
|
* @return {Vector2}
|
|
1679
1683
|
* @memberof Draw */
|
|
1680
|
-
|
|
1684
|
+
function worldToScreen(worldPos)
|
|
1681
1685
|
{
|
|
1682
1686
|
ASSERT(mainCanvasSize.x && mainCanvasSize.y, 'mainCanvasSize is invalid');
|
|
1683
1687
|
return worldPos.subtract(cameraPos).multiply(vec2(cameraScale,-cameraScale)).add(mainCanvasSize.scale(.5)).subtract(vec2(.5));
|
|
@@ -1886,9 +1890,9 @@ let engineFontImage;
|
|
|
1886
1890
|
|
|
1887
1891
|
/**
|
|
1888
1892
|
* Font Image Object - Draw text on a 2D canvas by using characters in an image
|
|
1889
|
-
*
|
|
1890
|
-
*
|
|
1891
|
-
*
|
|
1893
|
+
* - 96 characters (from space to tilde) are stored in an image
|
|
1894
|
+
* - Uses a default 8x8 font if none is supplied
|
|
1895
|
+
* - You can also use fonts from the main tile sheet
|
|
1892
1896
|
* @example
|
|
1893
1897
|
* // use built in font
|
|
1894
1898
|
* const font = new ImageFont;
|
|
@@ -1928,7 +1932,7 @@ class FontImage
|
|
|
1928
1932
|
{
|
|
1929
1933
|
const context = this.context;
|
|
1930
1934
|
context.save();
|
|
1931
|
-
context.imageSmoothingEnabled = !
|
|
1935
|
+
context.imageSmoothingEnabled = !canvasPixelated;
|
|
1932
1936
|
|
|
1933
1937
|
const size = this.tileSize;
|
|
1934
1938
|
const drawSize = size.add(this.paddingSize).scale(scale);
|
|
@@ -1974,7 +1978,7 @@ class FontImage
|
|
|
1974
1978
|
/** Returns true if fullscreen mode is active
|
|
1975
1979
|
* @return {Boolean}
|
|
1976
1980
|
* @memberof Draw */
|
|
1977
|
-
|
|
1981
|
+
function isFullscreen() { return document.fullscreenElement; }
|
|
1978
1982
|
|
|
1979
1983
|
/** Toggle fullsceen mode
|
|
1980
1984
|
* @memberof Draw */
|
|
@@ -1991,10 +1995,10 @@ function toggleFullscreen()
|
|
|
1991
1995
|
|
|
1992
1996
|
/**
|
|
1993
1997
|
* LittleJS Input System
|
|
1994
|
-
*
|
|
1995
|
-
*
|
|
1996
|
-
*
|
|
1997
|
-
*
|
|
1998
|
+
* - Tracks key down, pressed, and released
|
|
1999
|
+
* - Also tracks mouse buttons, position, and wheel
|
|
2000
|
+
* - Supports multiple gamepads
|
|
2001
|
+
* - Virtual gamepad for touch devices with touchGamepadSize
|
|
1998
2002
|
* @namespace Input
|
|
1999
2003
|
*/
|
|
2000
2004
|
|
|
@@ -2005,25 +2009,28 @@ function toggleFullscreen()
|
|
|
2005
2009
|
* @param {Number} [device=0]
|
|
2006
2010
|
* @return {Boolean}
|
|
2007
2011
|
* @memberof Input */
|
|
2008
|
-
|
|
2012
|
+
function keyIsDown(key, device=0)
|
|
2013
|
+
{ return inputData[device] && inputData[device][key] & 1; }
|
|
2009
2014
|
|
|
2010
2015
|
/** Returns true if device key was pressed this frame
|
|
2011
2016
|
* @param {Number} key
|
|
2012
2017
|
* @param {Number} [device=0]
|
|
2013
2018
|
* @return {Boolean}
|
|
2014
2019
|
* @memberof Input */
|
|
2015
|
-
|
|
2020
|
+
function keyWasPressed(key, device=0)
|
|
2021
|
+
{ return inputData[device] && inputData[device][key] & 2 ? 1 : 0; }
|
|
2016
2022
|
|
|
2017
2023
|
/** Returns true if device key was released this frame
|
|
2018
2024
|
* @param {Number} key
|
|
2019
2025
|
* @param {Number} [device=0]
|
|
2020
2026
|
* @return {Boolean}
|
|
2021
2027
|
* @memberof Input */
|
|
2022
|
-
|
|
2028
|
+
function keyWasReleased(key, device=0)
|
|
2029
|
+
{ return inputData[device] && inputData[device][key] & 4 ? 1 : 0; }
|
|
2023
2030
|
|
|
2024
2031
|
/** Clears all input
|
|
2025
2032
|
* @memberof Input */
|
|
2026
|
-
|
|
2033
|
+
function clearInput() { inputData = [[]]; }
|
|
2027
2034
|
|
|
2028
2035
|
/** Returns true if mouse button is down
|
|
2029
2036
|
* @function
|
|
@@ -2076,28 +2083,32 @@ let preventDefaultInput = 0;
|
|
|
2076
2083
|
* @param {Number} [gamepad=0]
|
|
2077
2084
|
* @return {Boolean}
|
|
2078
2085
|
* @memberof Input */
|
|
2079
|
-
|
|
2086
|
+
function gamepadIsDown(button, gamepad=0)
|
|
2087
|
+
{ return keyIsDown(button, gamepad+1); }
|
|
2080
2088
|
|
|
2081
2089
|
/** Returns true if gamepad button was pressed
|
|
2082
2090
|
* @param {Number} button
|
|
2083
2091
|
* @param {Number} [gamepad=0]
|
|
2084
2092
|
* @return {Boolean}
|
|
2085
2093
|
* @memberof Input */
|
|
2086
|
-
|
|
2094
|
+
function gamepadWasPressed(button, gamepad=0)
|
|
2095
|
+
{ return keyWasPressed(button, gamepad+1); }
|
|
2087
2096
|
|
|
2088
2097
|
/** Returns true if gamepad button was released
|
|
2089
2098
|
* @param {Number} button
|
|
2090
2099
|
* @param {Number} [gamepad=0]
|
|
2091
2100
|
* @return {Boolean}
|
|
2092
2101
|
* @memberof Input */
|
|
2093
|
-
|
|
2102
|
+
function gamepadWasReleased(button, gamepad=0)
|
|
2103
|
+
{ return keyWasReleased(button, gamepad+1); }
|
|
2094
2104
|
|
|
2095
2105
|
/** Returns gamepad stick value
|
|
2096
2106
|
* @param {Number} stick
|
|
2097
2107
|
* @param {Number} [gamepad=0]
|
|
2098
2108
|
* @return {Vector2}
|
|
2099
2109
|
* @memberof Input */
|
|
2100
|
-
|
|
2110
|
+
function gamepadStick(stick, gamepad=0)
|
|
2111
|
+
{ return stickData[gamepad] ? stickData[gamepad][stick] || vec2() : vec2(); }
|
|
2101
2112
|
|
|
2102
2113
|
///////////////////////////////////////////////////////////////////////////////
|
|
2103
2114
|
// Input update called by engine
|
|
@@ -2136,12 +2147,18 @@ onkeydown = (e)=>
|
|
|
2136
2147
|
e.repeat || (inputData[isUsingGamepad = 0][remapKey(e.which)] = 3);
|
|
2137
2148
|
preventDefaultInput && e.preventDefault();
|
|
2138
2149
|
}
|
|
2150
|
+
|
|
2139
2151
|
onkeyup = (e)=>
|
|
2140
2152
|
{
|
|
2141
2153
|
if (debug && e.target != document.body) return;
|
|
2142
2154
|
inputData[0][remapKey(e.which)] = 4;
|
|
2143
2155
|
}
|
|
2144
|
-
|
|
2156
|
+
|
|
2157
|
+
function remapKey(c)
|
|
2158
|
+
{
|
|
2159
|
+
return inputWASDEmulateDirection ?
|
|
2160
|
+
c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
|
|
2161
|
+
}
|
|
2145
2162
|
|
|
2146
2163
|
///////////////////////////////////////////////////////////////////////////////
|
|
2147
2164
|
// Mouse event handlers
|
|
@@ -2150,10 +2167,10 @@ onmousedown = (e)=> {inputData[isUsingGamepad = 0][e.button] = 3; onmousemove(e)
|
|
|
2150
2167
|
onmouseup = (e)=> inputData[0][e.button] = inputData[0][e.button] & 2 | 4;
|
|
2151
2168
|
onmousemove = (e)=> mousePosScreen = mouseToScreen(e);
|
|
2152
2169
|
onwheel = (e)=> e.ctrlKey || (mouseWheel = sign(e.deltaY));
|
|
2153
|
-
oncontextmenu = (e)=>
|
|
2170
|
+
oncontextmenu = (e)=> false; // prevent right click menu
|
|
2154
2171
|
|
|
2155
2172
|
// convert a mouse or touch event position to screen space
|
|
2156
|
-
|
|
2173
|
+
function mouseToScreen(mousePos)
|
|
2157
2174
|
{
|
|
2158
2175
|
if (!mainCanvas)
|
|
2159
2176
|
return vec2(); // fix bug that can occur if user clicks before page loads
|
|
@@ -2199,8 +2216,7 @@ function gamepadsUpdate()
|
|
|
2199
2216
|
if (gamepad)
|
|
2200
2217
|
{
|
|
2201
2218
|
// read clamp dead zone of analog sticks
|
|
2202
|
-
const deadZone = .3, deadZoneMax = .8
|
|
2203
|
-
const applyDeadZone = (v)=>
|
|
2219
|
+
const deadZone = .3, deadZoneMax = .8, applyDeadZone = (v)=>
|
|
2204
2220
|
v > deadZone ? percent( v, deadZone, deadZoneMax) :
|
|
2205
2221
|
v < -deadZone ? -percent(-v, deadZone, deadZoneMax) : 0;
|
|
2206
2222
|
|
|
@@ -2233,11 +2249,12 @@ function gamepadsUpdate()
|
|
|
2233
2249
|
/** Pulse the vibration hardware if it exists
|
|
2234
2250
|
* @param {Number} [pattern=100] - a single value in miliseconds or vibration interval array
|
|
2235
2251
|
* @memberof Input */
|
|
2236
|
-
|
|
2252
|
+
function vibrate(pattern)
|
|
2253
|
+
{ vibrateEnable && navigator && navigator.vibrate && navigator.vibrate(pattern); }
|
|
2237
2254
|
|
|
2238
2255
|
/** Cancel any ongoing vibration
|
|
2239
2256
|
* @memberof Input */
|
|
2240
|
-
|
|
2257
|
+
function vibrateStop() { vibrate(0); }
|
|
2241
2258
|
|
|
2242
2259
|
///////////////////////////////////////////////////////////////////////////////
|
|
2243
2260
|
// Touch input
|
|
@@ -2422,20 +2439,21 @@ function touchGamepadRender()
|
|
|
2422
2439
|
}
|
|
2423
2440
|
/**
|
|
2424
2441
|
* LittleJS Audio System
|
|
2425
|
-
*
|
|
2426
|
-
*
|
|
2427
|
-
*
|
|
2428
|
-
*
|
|
2429
|
-
*
|
|
2430
|
-
*
|
|
2442
|
+
* - <a href=https://killedbyapixel.github.io/ZzFX/>ZzFX Sound Effects</a> - Sound Effect Generator
|
|
2443
|
+
* - <a href=https://keithclark.github.io/ZzFXM/>ZzFXM Music</a> - Music System
|
|
2444
|
+
* - Caches sounds and music for fast playback
|
|
2445
|
+
* - Can attenuate and apply stereo panning to sounds
|
|
2446
|
+
* - Ability to play mp3, ogg, and wave files
|
|
2447
|
+
* - Speech synthesis wrapper functions
|
|
2448
|
+
* @namespace Audio
|
|
2431
2449
|
*/
|
|
2432
2450
|
|
|
2433
2451
|
'use strict';
|
|
2434
2452
|
|
|
2435
2453
|
/**
|
|
2436
2454
|
* Sound Object - Stores a zzfx sound for later use and can be played positionally
|
|
2437
|
-
*
|
|
2438
|
-
* <
|
|
2455
|
+
*
|
|
2456
|
+
* <a href=https://killedbyapixel.github.io/ZzFX/>Create sounds using the ZzFX Sound Designer.</a>
|
|
2439
2457
|
* @example
|
|
2440
2458
|
* // create a sound
|
|
2441
2459
|
* const sound_example = new Sound([.5,.5]);
|
|
@@ -2519,8 +2537,8 @@ class Sound
|
|
|
2519
2537
|
|
|
2520
2538
|
/**
|
|
2521
2539
|
* Music Object - Stores a zzfx music track for later use
|
|
2522
|
-
*
|
|
2523
|
-
* <
|
|
2540
|
+
*
|
|
2541
|
+
* <a href=https://keithclark.github.io/ZzFXM/>Create music with the ZzFXM tracker.</a>
|
|
2524
2542
|
* @example
|
|
2525
2543
|
* // create some music
|
|
2526
2544
|
* const music_example = new Music(
|
|
@@ -2630,14 +2648,15 @@ function speak(text, language='', volume=1, rate=1, pitch=1)
|
|
|
2630
2648
|
|
|
2631
2649
|
/** Stop all queued speech
|
|
2632
2650
|
* @memberof Audio */
|
|
2633
|
-
|
|
2651
|
+
function speakStop() {speechSynthesis && speechSynthesis.cancel();}
|
|
2634
2652
|
|
|
2635
2653
|
/** Get frequency of a note on a musical scale
|
|
2636
2654
|
* @param {Number} semitoneOffset - How many semitones away from the root note
|
|
2637
2655
|
* @param {Number} [rootNoteFrequency=220] - Frequency at semitone offset 0
|
|
2638
2656
|
* @return {Number} - The frequency of the note
|
|
2639
2657
|
* @memberof Audio */
|
|
2640
|
-
|
|
2658
|
+
function getNoteFrequency(semitoneOffset, rootFrequency=220)
|
|
2659
|
+
{ return rootFrequency * 2**(semitoneOffset/12); }
|
|
2641
2660
|
|
|
2642
2661
|
///////////////////////////////////////////////////////////////////////////////
|
|
2643
2662
|
|
|
@@ -2695,12 +2714,12 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=0)
|
|
|
2695
2714
|
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.2.0 by Frank Force
|
|
2696
2715
|
|
|
2697
2716
|
/** Generate and play a ZzFX sound
|
|
2698
|
-
*
|
|
2699
|
-
* <
|
|
2717
|
+
*
|
|
2718
|
+
* <a href=https://killedbyapixel.github.io/ZzFX/>Create sounds using the ZzFX Sound Designer.</a>
|
|
2700
2719
|
* @param {Array} zzfxSound - Array of ZzFX parameters, ex. [.5,.5]
|
|
2701
|
-
* @return {
|
|
2720
|
+
* @return {AudioBufferSourceNode} - The audio node of the sound played
|
|
2702
2721
|
* @memberof Audio */
|
|
2703
|
-
|
|
2722
|
+
function zzfx(...zzfxSound) { return playSamples([zzfxG(...zzfxSound)]); }
|
|
2704
2723
|
|
|
2705
2724
|
/** Sample rate used for all ZzFX sounds
|
|
2706
2725
|
* @default 44100
|
|
@@ -2708,7 +2727,29 @@ const zzfx = (...zzfxSound) => playSamples([zzfxG(...zzfxSound)]);
|
|
|
2708
2727
|
const zzfxR = 44100;
|
|
2709
2728
|
|
|
2710
2729
|
/** Generate samples for a ZzFX sound
|
|
2711
|
-
* @
|
|
2730
|
+
* @param {Number} [volume=1] - Volume scale (percent)
|
|
2731
|
+
* @param {Number} [randomness=.05] - How much to randomize frequency (percent Hz)
|
|
2732
|
+
* @param {Number} [frequency=220] - Frequency of sound (Hz)
|
|
2733
|
+
* @param {Number} [attack=0] - Attack time, how fast sound starts (seconds)
|
|
2734
|
+
* @param {Number} [sustain=0] - Sustain time, how long sound holds (seconds)
|
|
2735
|
+
* @param {Number} [release=.1] - Release time, how fast sound fades out (seconds)
|
|
2736
|
+
* @param {Number} [shape=0] - Shape of the sound wave
|
|
2737
|
+
* @param {Number} [shapeCurve=1] - Squarenes of wave (0=square, 1=normal, 2=pointy)
|
|
2738
|
+
* @param {Number} [slide=0] - How much to slide frequency (kHz/s)
|
|
2739
|
+
* @param {Number} [deltaSlide=0] - How much to change slide (kHz/s/s)
|
|
2740
|
+
* @param {Number} [pitchJump=0] - Frequency of pitch jump (Hz)
|
|
2741
|
+
* @param {Number} [pitchJumpTime=0] - Time of pitch jump (seconds)
|
|
2742
|
+
* @param {Number} [repeatTime=0] - Resets some parameters periodically (seconds)
|
|
2743
|
+
* @param {Number} [noise=0] - How much random noise to add (percent)
|
|
2744
|
+
* @param {Number} [modulation=0] - Frequency of modulation wave, negative flips phase (Hz)
|
|
2745
|
+
* @param {Number} [bitCrush=0] - Resamples at a lower frequency in (samples*100)
|
|
2746
|
+
* @param {Number} [delay=0] - Overlap sound with itself for reverb and flanger effects (seconds)
|
|
2747
|
+
* @param {Number} [sustainVolume=1] - Volume level for sustain (percent)
|
|
2748
|
+
* @param {Number} [decay=0] - Decay time, how long to reach sustain after attack (seconds)
|
|
2749
|
+
* @param {Number} [tremolo=0] - Trembling effect, rate controlled by repeat time (precent)
|
|
2750
|
+
* @return {Array} - Array of audio samples
|
|
2751
|
+
* @memberof Audio
|
|
2752
|
+
*/
|
|
2712
2753
|
function zzfxG
|
|
2713
2754
|
(
|
|
2714
2755
|
// parameters
|
|
@@ -2798,7 +2839,7 @@ function zzfxG
|
|
|
2798
2839
|
* @param {Array} patterns - Array of pattern data
|
|
2799
2840
|
* @param {Array} sequence - Array of pattern indexes
|
|
2800
2841
|
* @param {Number} [BPM=125] - Playback speed of the song in BPM
|
|
2801
|
-
* @
|
|
2842
|
+
* @return {Array} - Left and right channel sample data
|
|
2802
2843
|
* @memberof Audio */
|
|
2803
2844
|
function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
2804
2845
|
{
|
|
@@ -2896,13 +2937,13 @@ function zzfxM(instruments, patterns, sequence, BPM = 125)
|
|
|
2896
2937
|
}
|
|
2897
2938
|
/**
|
|
2898
2939
|
* LittleJS Tile Layer System
|
|
2899
|
-
*
|
|
2900
|
-
*
|
|
2901
|
-
*
|
|
2902
|
-
*
|
|
2903
|
-
*
|
|
2904
|
-
*
|
|
2905
|
-
*
|
|
2940
|
+
* - Caches arrays of tiles to off screen canvas for fast rendering
|
|
2941
|
+
* - Unlimted numbers of layers, allocates canvases as needed
|
|
2942
|
+
* - Interfaces with EngineObject for collision
|
|
2943
|
+
* - Collision layer is separate from visible layers
|
|
2944
|
+
* - It is recommended to have a visible layer that matches the collision
|
|
2945
|
+
* - Tile layers can be drawn to using their context with canvas2d
|
|
2946
|
+
* - Drawn directly to the main canvas without using WebGL
|
|
2906
2947
|
* @namespace TileCollision
|
|
2907
2948
|
*/
|
|
2908
2949
|
|
|
@@ -2933,15 +2974,19 @@ function initTileCollision(size)
|
|
|
2933
2974
|
* @param {Vector2} pos
|
|
2934
2975
|
* @param {Number} [data=0]
|
|
2935
2976
|
* @memberof TileCollision */
|
|
2936
|
-
|
|
2977
|
+
function setTileCollisionData(pos, data=0)
|
|
2978
|
+
{
|
|
2937
2979
|
pos.arrayCheck(tileCollisionSize) && (tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] = data);
|
|
2980
|
+
}
|
|
2938
2981
|
|
|
2939
2982
|
/** Get tile collision data
|
|
2940
2983
|
* @param {Vector2} pos
|
|
2941
2984
|
* @return {Number}
|
|
2942
2985
|
* @memberof TileCollision */
|
|
2943
|
-
|
|
2944
|
-
|
|
2986
|
+
function getTileCollisionData(pos)
|
|
2987
|
+
{
|
|
2988
|
+
return pos.arrayCheck(tileCollisionSize) ? tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] : 0;
|
|
2989
|
+
}
|
|
2945
2990
|
|
|
2946
2991
|
/** Check if collision with another object should occur
|
|
2947
2992
|
* @param {Vector2} pos
|
|
@@ -3035,10 +3080,10 @@ class TileLayerData
|
|
|
3035
3080
|
|
|
3036
3081
|
/**
|
|
3037
3082
|
* Tile layer object - cached rendering system for tile layers
|
|
3038
|
-
*
|
|
3039
|
-
*
|
|
3040
|
-
*
|
|
3041
|
-
*
|
|
3083
|
+
* - Each Tile layer is rendered to an off screen canvas
|
|
3084
|
+
* - To allow dynamic modifications, layers are rendered using canvas 2d
|
|
3085
|
+
* - Some devices like mobile phones are limited to 4k texture resolution
|
|
3086
|
+
* - So with 16x16 tiles this limits layers to 256x256 on mobile devices
|
|
3042
3087
|
* @extends EngineObject
|
|
3043
3088
|
* @example
|
|
3044
3089
|
* // create tile collision and visible tile layer
|
|
@@ -3238,12 +3283,9 @@ constructor(pos, size=tileCollisionSize, tileSize=tileSizeDefault, scale=vec2(1)
|
|
|
3238
3283
|
drawRect(pos, size, color, angle)
|
|
3239
3284
|
{ this.drawTile(pos, size, -1, 0, color, angle); }
|
|
3240
3285
|
}
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
- Updates particle physics
|
|
3245
|
-
- Fast particle rendering
|
|
3246
|
-
*/
|
|
3286
|
+
/**
|
|
3287
|
+
* LittleJS Particle System
|
|
3288
|
+
*/
|
|
3247
3289
|
|
|
3248
3290
|
'use strict';
|
|
3249
3291
|
|
|
@@ -3549,9 +3591,9 @@ class Particle extends EngineObject
|
|
|
3549
3591
|
}
|
|
3550
3592
|
/**
|
|
3551
3593
|
* LittleJS Medal System
|
|
3552
|
-
*
|
|
3553
|
-
*
|
|
3554
|
-
*
|
|
3594
|
+
* - Tracks and displays medals
|
|
3595
|
+
* - Saves medals to local storage
|
|
3596
|
+
* - Newgrounds integration
|
|
3555
3597
|
* @namespace Medals
|
|
3556
3598
|
*/
|
|
3557
3599
|
|
|
@@ -3568,8 +3610,8 @@ let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
|
|
|
3568
3610
|
///////////////////////////////////////////////////////////////////////////////
|
|
3569
3611
|
|
|
3570
3612
|
/** Initialize medals with a save name used for storage
|
|
3571
|
-
*
|
|
3572
|
-
*
|
|
3613
|
+
* - Call this after creating all medals
|
|
3614
|
+
* - Checks if medals are unlocked
|
|
3573
3615
|
* @param {String} saveName
|
|
3574
3616
|
* @memberof Medals */
|
|
3575
3617
|
function medalsInit(saveName)
|
|
@@ -3839,20 +3881,43 @@ class Newgrounds
|
|
|
3839
3881
|
CryptoJS()
|
|
3840
3882
|
{
|
|
3841
3883
|
///////////////////////////////////////////////////////////////////////////////
|
|
3842
|
-
// Crypto-JS - https://github.com/brix/crypto-js
|
|
3843
|
-
//
|
|
3844
|
-
|
|
3884
|
+
// Crypto-JS - https://github.com/brix/crypto-js - MIT License
|
|
3885
|
+
//
|
|
3886
|
+
// [The MIT License (MIT)](http://opensource.org/licenses/MIT)
|
|
3887
|
+
//
|
|
3888
|
+
// Copyright (c) 2009-2013 Jeff Mott
|
|
3889
|
+
// Copyright (c) 2013-2016 Evan Vosberg
|
|
3890
|
+
//
|
|
3891
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
3892
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
3893
|
+
// in the Software without restriction, including without limitation the rights
|
|
3894
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
3895
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
3896
|
+
// furnished to do so, subject to the following conditions:
|
|
3897
|
+
//
|
|
3898
|
+
// The above copyright notice and this permission notice shall be included in
|
|
3899
|
+
// all copies or substantial portions of the Software.
|
|
3900
|
+
//
|
|
3901
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
3902
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
3903
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
3904
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
3905
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
3906
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
3907
|
+
// THE SOFTWARE.
|
|
3845
3908
|
return eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
|
|
3909
|
+
// end of Crypto-JS
|
|
3910
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
3846
3911
|
}
|
|
3847
3912
|
}
|
|
3848
3913
|
/**
|
|
3849
3914
|
* LittleJS WebGL Interface
|
|
3850
|
-
*
|
|
3851
|
-
*
|
|
3852
|
-
*
|
|
3853
|
-
*
|
|
3854
|
-
*
|
|
3855
|
-
*
|
|
3915
|
+
* - All webgl used by the engine is wrapped up here
|
|
3916
|
+
* - For normal stuff you won't need to see or call anything in this file
|
|
3917
|
+
* - For advanced stuff there are helper functions to create shaders, textures, etc
|
|
3918
|
+
* - Can be disabled with glEnable to revert to 2D canvas rendering
|
|
3919
|
+
* - Batches sprite rendering on GPU for incredibly fast performance
|
|
3920
|
+
* - Sprite transform math is done in the shader where possible
|
|
3856
3921
|
* @namespace WebGL
|
|
3857
3922
|
*/
|
|
3858
3923
|
|
|
@@ -3927,7 +3992,7 @@ function glSetBlendMode(additive)
|
|
|
3927
3992
|
}
|
|
3928
3993
|
|
|
3929
3994
|
/** Set the WebGl texture, not normally necessary unless multiple tile sheets are used
|
|
3930
|
-
*
|
|
3995
|
+
* - This may also flush the gl buffer resulting in more draw calls and worse performance
|
|
3931
3996
|
* @param {WebGLTexture} [texture=glTileTexture]
|
|
3932
3997
|
* @memberof WebGL */
|
|
3933
3998
|
function glSetTexture(texture=glTileTexture)
|
|
@@ -3988,7 +4053,7 @@ function glCreateTexture(image)
|
|
|
3988
4053
|
image && image.width && glContext.texImage2D(gl_TEXTURE_2D, 0, gl_RGBA, gl_RGBA, gl_UNSIGNED_BYTE, image);
|
|
3989
4054
|
|
|
3990
4055
|
// use point filtering for pixelated rendering
|
|
3991
|
-
const filter =
|
|
4056
|
+
const filter = canvasPixelated ? gl_NEAREST : gl_LINEAR;
|
|
3992
4057
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, filter);
|
|
3993
4058
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, filter);
|
|
3994
4059
|
glContext.texParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_S, gl_CLAMP_TO_EDGE);
|
|
@@ -4239,27 +4304,23 @@ gl_INDICIES_PER_VERT = 6,
|
|
|
4239
4304
|
gl_MAX_BATCH = 1<<16,
|
|
4240
4305
|
gl_VERTEX_BYTE_STRIDE = (4 * 2) * 2 + (4) * 2, // vec2 * 2 + (char * 4) * 2
|
|
4241
4306
|
gl_VERTEX_BUFFER_SIZE = gl_MAX_BATCH * gl_VERTICES_PER_QUAD * gl_VERTEX_BYTE_STRIDE;
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
*/
|
|
4260
|
-
|
|
4261
|
-
/**
|
|
4262
|
-
* LittleJS Engine Globals
|
|
4307
|
+
/**
|
|
4308
|
+
* LittleJS - The Tiny JavaScript Game Engine That Can!
|
|
4309
|
+
* MIT License - Copyright 2021 Frank Force
|
|
4310
|
+
*
|
|
4311
|
+
* Engine Features
|
|
4312
|
+
* - Object oriented system with base class engine object
|
|
4313
|
+
* - Base class object handles update, physics, collision, rendering, etc
|
|
4314
|
+
* - Engine helper classes and functions like Vector2, Color, and Timer
|
|
4315
|
+
* - Super fast rendering system for tile sheets
|
|
4316
|
+
* - Sound effects audio with zzfx and music with zzfxm
|
|
4317
|
+
* - Input processing system with gamepad and touchscreen support
|
|
4318
|
+
* - Tile layer rendering and collision system
|
|
4319
|
+
* - Particle effect system
|
|
4320
|
+
* - Medal system tracks and displays achievements
|
|
4321
|
+
* - Debug tools and debug rendering system
|
|
4322
|
+
* - Post processing effects
|
|
4323
|
+
* - Call engineInit() to start it up!
|
|
4263
4324
|
* @namespace Engine
|
|
4264
4325
|
*/
|
|
4265
4326
|
|
|
@@ -4275,7 +4336,7 @@ const engineName = 'LittleJS';
|
|
|
4275
4336
|
* @type {String}
|
|
4276
4337
|
* @default
|
|
4277
4338
|
* @memberof Engine */
|
|
4278
|
-
const engineVersion = '1.6.
|
|
4339
|
+
const engineVersion = '1.6.6';
|
|
4279
4340
|
|
|
4280
4341
|
/** Frames per second to update objects
|
|
4281
4342
|
* @type {Number}
|
|
@@ -4345,10 +4406,11 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4345
4406
|
debug && (tileImage.onload=()=>ASSERT(1)); // tile sheet can not reloaded
|
|
4346
4407
|
|
|
4347
4408
|
// setup html
|
|
4348
|
-
const styleBody = 'margin:0;overflow:hidden;
|
|
4349
|
-
';
|
|
4350
|
-
'
|
|
4351
|
-
'
|
|
4409
|
+
const styleBody = 'margin:0;overflow:hidden;' + // fill the window
|
|
4410
|
+
'background:#000;' + // set background color
|
|
4411
|
+
'touch-action:none;' + // prevent mobile pinch to resize
|
|
4412
|
+
'user-select:none;' + // prevent mobile hold to select
|
|
4413
|
+
'-webkit-user-select:none'; // compatibility for ios
|
|
4352
4414
|
document.body.style = styleBody;
|
|
4353
4415
|
document.body.appendChild(mainCanvas = document.createElement('canvas'));
|
|
4354
4416
|
mainContext = mainCanvas.getContext('2d');
|
|
@@ -4361,8 +4423,10 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
4361
4423
|
document.body.appendChild(overlayCanvas = document.createElement('canvas'));
|
|
4362
4424
|
overlayContext = overlayCanvas.getContext('2d');
|
|
4363
4425
|
|
|
4364
|
-
// set canvas style
|
|
4365
|
-
const styleCanvas = 'position:absolute;
|
|
4426
|
+
// set canvas style
|
|
4427
|
+
const styleCanvas = 'position:absolute;' +
|
|
4428
|
+
'top:50%;left:50%;transform:translate(-50%,-50%);' + // center the canvas
|
|
4429
|
+
(canvasPixelated?'image-rendering:pixelated':''); // set pixelated rendering
|
|
4366
4430
|
(glCanvas||mainCanvas).style = mainCanvas.style = overlayCanvas.style = styleCanvas;
|
|
4367
4431
|
|
|
4368
4432
|
gameInit();
|
|
@@ -4495,7 +4559,7 @@ function enginePreRender()
|
|
|
4495
4559
|
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
4496
4560
|
|
|
4497
4561
|
// disable smoothing for pixel art
|
|
4498
|
-
mainContext.imageSmoothingEnabled = !
|
|
4562
|
+
mainContext.imageSmoothingEnabled = !canvasPixelated;
|
|
4499
4563
|
|
|
4500
4564
|
// setup gl rendering if enabled
|
|
4501
4565
|
glEnable && glPreRender();
|
|
@@ -4509,7 +4573,7 @@ function engineObjectsUpdate()
|
|
|
4509
4573
|
engineObjectsCollide = engineObjects.filter(o=>o.collideSolidObjects);
|
|
4510
4574
|
|
|
4511
4575
|
// recursive object update
|
|
4512
|
-
|
|
4576
|
+
function updateObject(o)
|
|
4513
4577
|
{
|
|
4514
4578
|
if (!o.destroyed)
|
|
4515
4579
|
{
|
|
@@ -4565,206 +4629,203 @@ function engineObjectsCallback(pos, size, callbackFunction, objects=engineObject
|
|
|
4565
4629
|
|
|
4566
4630
|
/**
|
|
4567
4631
|
* LittleJS Module Export
|
|
4568
|
-
*
|
|
4632
|
+
* - Export engine as a module with extra functions where necessary
|
|
4569
4633
|
*/
|
|
4570
4634
|
|
|
4571
|
-
// Setters for all variables that devs will need to modify
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
4635
|
/** Set position of camera in world space
|
|
4575
4636
|
* @param {Vector2} pos
|
|
4576
4637
|
* @memberof Settings */
|
|
4577
|
-
|
|
4638
|
+
function setCameraPos(pos) { cameraPos = pos; }
|
|
4578
4639
|
|
|
4579
4640
|
/** Set scale of camera in world space
|
|
4580
4641
|
* @param {Number} scale
|
|
4581
4642
|
* @memberof Settings */
|
|
4582
|
-
|
|
4643
|
+
function setCameraScale(scale) { cameraScale = scale; }
|
|
4583
4644
|
|
|
4584
4645
|
/** Set max size of the canvas
|
|
4585
4646
|
* @param {Vector2} size
|
|
4586
4647
|
* @memberof Settings */
|
|
4587
|
-
|
|
4648
|
+
function setCanvasMaxSize(size) { canvasMaxSize = size; }
|
|
4588
4649
|
|
|
4589
4650
|
/** Set fixed size of the canvas
|
|
4590
4651
|
* @param {Vector2} size
|
|
4591
4652
|
* @memberof Settings */
|
|
4592
|
-
|
|
4653
|
+
function setCanvasFixedSize(size) { canvasFixedSize = size; }
|
|
4593
4654
|
|
|
4594
4655
|
/** Disables anti aliasing for pixel art if true
|
|
4595
4656
|
* @param {Boolean} pixelated
|
|
4596
4657
|
* @memberof Settings */
|
|
4597
|
-
|
|
4658
|
+
function setCanvasPixelated(pixelated) { canvasPixelated = pixelated; }
|
|
4598
4659
|
|
|
4599
4660
|
/** Set default font used for text rendering
|
|
4600
4661
|
* @param {String} font
|
|
4601
4662
|
* @memberof Settings */
|
|
4602
|
-
|
|
4663
|
+
function setFontDefault(font) { fontDefault = font; }
|
|
4603
4664
|
|
|
4604
4665
|
/** Set if webgl rendering is enabled
|
|
4605
4666
|
* @param {Boolean} enable
|
|
4606
4667
|
* @memberof Settings */
|
|
4607
|
-
|
|
4668
|
+
function setGlEnable(enable) { glEnable = enable; }
|
|
4608
4669
|
|
|
4609
4670
|
/** Set to not composite the WebGL canvas
|
|
4610
4671
|
* @param {Boolean} overlay
|
|
4611
4672
|
* @memberof Settings */
|
|
4612
|
-
|
|
4673
|
+
function setGlOverlay(overlay) { glOverlay = overlay; }
|
|
4613
4674
|
|
|
4614
4675
|
/** Set default size of tiles in pixels
|
|
4615
4676
|
* @param {Vector2} size
|
|
4616
4677
|
* @memberof Settings */
|
|
4617
|
-
|
|
4678
|
+
function setTileSizeDefault(size) { tileSizeDefault = size; }
|
|
4618
4679
|
|
|
4619
4680
|
/** Set to prevent tile bleeding from neighbors in pixels
|
|
4620
4681
|
* @param {Number} scale
|
|
4621
4682
|
* @memberof Settings */
|
|
4622
|
-
|
|
4683
|
+
function setTileFixBleedScale(scale) { tileFixBleedScale = scale; }
|
|
4623
4684
|
|
|
4624
4685
|
/** Set if collisions between objects are enabled
|
|
4625
4686
|
* @param {Boolean} enable
|
|
4626
4687
|
* @memberof Settings */
|
|
4627
|
-
|
|
4688
|
+
function setEnablePhysicsSolver(enable) { enablePhysicsSolver = enable; }
|
|
4628
4689
|
|
|
4629
4690
|
/** Set default object mass for collison calcuations
|
|
4630
4691
|
* @param {Number} mass
|
|
4631
4692
|
* @memberof Settings */
|
|
4632
|
-
|
|
4693
|
+
function setObjectDefaultMass(mass) { objectDefaultMass = mass; }
|
|
4633
4694
|
|
|
4634
4695
|
/** Set how much to slow velocity by each frame
|
|
4635
4696
|
* @param {Number} damping
|
|
4636
4697
|
* @memberof Settings */
|
|
4637
|
-
|
|
4698
|
+
function setObjectDefaultDamping(damp) { objectDefaultDamping = damp; }
|
|
4638
4699
|
|
|
4639
4700
|
/** Set how much to slow angular velocity each frame
|
|
4640
4701
|
* @param {Number} damping
|
|
4641
4702
|
* @memberof Settings */
|
|
4642
|
-
|
|
4703
|
+
function setObjectDefaultAngleDamping(damp) { objectDefaultAngleDamping = damp; }
|
|
4643
4704
|
|
|
4644
4705
|
/** Set how much to bounce when a collision occur
|
|
4645
4706
|
* @param {Number} elasticity
|
|
4646
4707
|
* @memberof Settings */
|
|
4647
|
-
|
|
4708
|
+
function setObjectDefaultElasticity(elasticity) { objectDefaultElasticity = elasticity; }
|
|
4648
4709
|
|
|
4649
4710
|
/** Set how much to slow when touching
|
|
4650
4711
|
* @param {Number} friction
|
|
4651
4712
|
* @memberof Settings */
|
|
4652
|
-
|
|
4713
|
+
function setObjectDefaultFriction(friction) { objectDefaultFriction = friction; }
|
|
4653
4714
|
|
|
4654
4715
|
/** Set max speed to avoid fast objects missing collisions
|
|
4655
4716
|
* @param {Number} speed
|
|
4656
4717
|
* @memberof Settings */
|
|
4657
|
-
|
|
4718
|
+
function setObjectMaxSpeed(speed) { objectMaxSpeed = speed; }
|
|
4658
4719
|
|
|
4659
4720
|
/** Set how much gravity to apply to objects along the Y axis
|
|
4660
4721
|
* @param {Number} gravity
|
|
4661
4722
|
* @memberof Settings */
|
|
4662
|
-
|
|
4723
|
+
function setGravity(g) { gravity = g; }
|
|
4663
4724
|
|
|
4664
4725
|
/** Set to scales emit rate of particles
|
|
4665
4726
|
* @param {Number} scale
|
|
4666
4727
|
* @memberof Settings */
|
|
4667
|
-
|
|
4728
|
+
function setParticleEmitRateScale(scale) { particleEmitRateScale = scale; }
|
|
4668
4729
|
|
|
4669
4730
|
/** Set if gamepads are enabled
|
|
4670
4731
|
* @param {Boolean} enable
|
|
4671
4732
|
* @memberof Settings */
|
|
4672
|
-
|
|
4733
|
+
function setGamepadsEnable(enable) { gamepadsEnable = enable; }
|
|
4673
4734
|
|
|
4674
4735
|
/** Set if the dpad input is also routed to the left analog stick
|
|
4675
4736
|
* @param {Boolean} enable
|
|
4676
4737
|
* @memberof Settings */
|
|
4677
|
-
|
|
4738
|
+
function setGamepadDirectionEmulateStick(enable) { gamepadDirectionEmulateStick = enable; }
|
|
4678
4739
|
|
|
4679
4740
|
/** Set if true the WASD keys are also routed to the direction keys
|
|
4680
4741
|
* @param {Boolean} enable
|
|
4681
4742
|
* @memberof Settings */
|
|
4682
|
-
|
|
4743
|
+
function setInputWASDEmulateDirection(enable) { inputWASDEmulateDirection = enable; }
|
|
4683
4744
|
|
|
4684
4745
|
/** Set if touch gamepad should appear on mobile devices
|
|
4685
4746
|
* @param {Boolean} enable
|
|
4686
4747
|
* @memberof Settings */
|
|
4687
|
-
|
|
4748
|
+
function setTouchGamepadEnable(enable) { touchGamepadEnable = enable; }
|
|
4688
4749
|
|
|
4689
4750
|
/** Set if touch gamepad should be analog stick or 8 way dpad
|
|
4690
4751
|
* @param {Boolean} analog
|
|
4691
4752
|
* @memberof Settings */
|
|
4692
|
-
|
|
4753
|
+
function setTouchGamepadAnalog(analog) { touchGamepadAnalog = analog; }
|
|
4693
4754
|
|
|
4694
4755
|
/** Set size of virutal gamepad for touch devices in pixels
|
|
4695
4756
|
* @param {Number} size
|
|
4696
4757
|
* @memberof Settings */
|
|
4697
|
-
|
|
4758
|
+
function setTouchGamepadSize(size) { touchGamepadSize = size; }
|
|
4698
4759
|
|
|
4699
4760
|
/** Set transparency of touch gamepad overlay
|
|
4700
4761
|
* @param {Number} alpha
|
|
4701
4762
|
* @memberof Settings */
|
|
4702
|
-
|
|
4763
|
+
function setTouchGamepadAlpha(alpha) { touchGamepadAlpha = alpha; }
|
|
4703
4764
|
|
|
4704
4765
|
/** Set to allow vibration hardware if it exists
|
|
4705
4766
|
* @param {Boolean} enable
|
|
4706
4767
|
* @memberof Settings */
|
|
4707
|
-
|
|
4768
|
+
function setVibrateEnable(enable) { vibrateEnable = enable; }
|
|
4708
4769
|
|
|
4709
4770
|
/** Set to disable all audio code
|
|
4710
4771
|
* @param {Boolean} enable
|
|
4711
4772
|
* @memberof Settings */
|
|
4712
|
-
|
|
4773
|
+
function setSoundEnable(enable) { soundEnable = enable; }
|
|
4713
4774
|
|
|
4714
4775
|
/** Set volume scale to apply to all sound, music and speech
|
|
4715
4776
|
* @param {Number} volume
|
|
4716
4777
|
* @memberof Settings */
|
|
4717
|
-
|
|
4778
|
+
function setSoundVolume(volume) { soundVolume = volume; }
|
|
4718
4779
|
|
|
4719
4780
|
/** Set default range where sound no longer plays
|
|
4720
4781
|
* @param {Number} range
|
|
4721
4782
|
* @memberof Settings */
|
|
4722
|
-
|
|
4783
|
+
function setSoundDefaultRange(range) { soundDefaultRange = range; }
|
|
4723
4784
|
|
|
4724
4785
|
/** Set default range percent to start tapering off sound
|
|
4725
4786
|
* @param {Number} taper
|
|
4726
4787
|
* @memberof Settings */
|
|
4727
|
-
|
|
4788
|
+
function setSoundDefaultTaper(taper) { soundDefaultTaper = taper; }
|
|
4728
4789
|
|
|
4729
4790
|
/** Set how long to show medals for in seconds
|
|
4730
4791
|
* @param {Number} time
|
|
4731
4792
|
* @memberof Settings */
|
|
4732
|
-
|
|
4793
|
+
function setMedalDisplayTime(time) { medalDisplayTime = time; }
|
|
4733
4794
|
|
|
4734
4795
|
/** Set how quickly to slide on/off medals in seconds
|
|
4735
4796
|
* @param {Number} time
|
|
4736
4797
|
* @memberof Settings */
|
|
4737
|
-
|
|
4798
|
+
function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
|
|
4738
4799
|
|
|
4739
4800
|
/** Set size of medal display
|
|
4740
4801
|
* @param {Vector2} size
|
|
4741
4802
|
* @memberof Settings */
|
|
4742
|
-
|
|
4803
|
+
function setMedalDisplaySize(size) { medalDisplaySize = size; }
|
|
4743
4804
|
|
|
4744
4805
|
/** Set size of icon in medal display
|
|
4745
4806
|
* @param {Number} size
|
|
4746
4807
|
* @memberof Settings */
|
|
4747
|
-
|
|
4808
|
+
function setMedalDisplayIconSize(size) { medalDisplayIconSize = size; }
|
|
4748
4809
|
|
|
4749
4810
|
/** Set to stop medals from being unlockable
|
|
4750
4811
|
* @param {Boolean} preventUnlock
|
|
4751
4812
|
* @memberof Settings */
|
|
4752
|
-
|
|
4813
|
+
function setMedalsPreventUnlock(prevent) { medalsPreventUnlock = prevent; }
|
|
4753
4814
|
|
|
4754
4815
|
/** Set if watermark with FPS should be shown
|
|
4755
4816
|
* @param {Boolean} show
|
|
4756
4817
|
* @memberof Debug */
|
|
4757
|
-
|
|
4818
|
+
function setShowWatermark(show) { showWatermark = show; }
|
|
4758
4819
|
|
|
4759
4820
|
/** Set if god mode is enabled
|
|
4760
4821
|
* @param {Boolean} enable
|
|
4761
4822
|
* @memberof Debug */
|
|
4762
|
-
|
|
4823
|
+
function setGodMode(enable) { godMode = enable; }
|
|
4763
4824
|
|
|
4764
4825
|
/** Set key code used to toggle debug mode, Esc by default
|
|
4765
4826
|
* @param {Number} key
|
|
4766
4827
|
* @memberof Debug */
|
|
4767
|
-
|
|
4828
|
+
function setDebugKey(key) { debugKey = key; }
|
|
4768
4829
|
|
|
4769
4830
|
export {
|
|
4770
4831
|
// Setters for global variables
|
|
@@ -4772,7 +4833,7 @@ export {
|
|
|
4772
4833
|
setCameraScale,
|
|
4773
4834
|
setCanvasMaxSize,
|
|
4774
4835
|
setCanvasFixedSize,
|
|
4775
|
-
|
|
4836
|
+
setCanvasPixelated,
|
|
4776
4837
|
setFontDefault,
|
|
4777
4838
|
setGlEnable,
|
|
4778
4839
|
setGlOverlay,
|
|
@@ -4811,7 +4872,7 @@ export {
|
|
|
4811
4872
|
// Settings
|
|
4812
4873
|
canvasMaxSize,
|
|
4813
4874
|
canvasFixedSize,
|
|
4814
|
-
|
|
4875
|
+
canvasPixelated,
|
|
4815
4876
|
fontDefault,
|
|
4816
4877
|
tileSizeDefault,
|
|
4817
4878
|
tileFixBleedScale,
|