littlejsengine 1.18.7 → 1.18.12
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 +2 -4
- package/dist/littlejs.d.ts +76 -8
- package/dist/littlejs.esm.js +333 -73
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +327 -72
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +317 -64
- package/package.json +1 -1
- package/plugins/medalSystem.js +2 -1
- package/plugins/newgrounds.js +7 -0
- package/plugins/pathFinder.js +35 -6
- package/plugins/tweenSystem.js +9 -1
- package/plugins/uiSystem.js +36 -14
- package/src/engine.js +3 -2
- package/src/engineAudio.js +7 -9
- package/src/engineDebug.js +10 -8
- package/src/engineDraw.js +94 -14
- package/src/engineExport.js +6 -1
- package/src/engineInput.js +7 -7
- package/src/engineMath.js +5 -3
- package/src/engineUtilities.js +49 -6
- package/src/engineWebGL.js +63 -1
- package/plugins/tween.js +0 -509
package/src/engineInput.js
CHANGED
|
@@ -103,7 +103,7 @@ function inputClear()
|
|
|
103
103
|
* @memberof Input */
|
|
104
104
|
function keyIsDown(key, device=0)
|
|
105
105
|
{
|
|
106
|
-
ASSERT(
|
|
106
|
+
ASSERT(isStringLike(key), 'key must be a number or string');
|
|
107
107
|
ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
|
|
108
108
|
return !!(inputData[device]?.[key] & 1);
|
|
109
109
|
}
|
|
@@ -115,7 +115,7 @@ function keyIsDown(key, device=0)
|
|
|
115
115
|
* @memberof Input */
|
|
116
116
|
function keyWasPressed(key, device=0)
|
|
117
117
|
{
|
|
118
|
-
ASSERT(
|
|
118
|
+
ASSERT(isStringLike(key), 'key must be a number or string');
|
|
119
119
|
ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
|
|
120
120
|
return !!(inputData[device]?.[key] & 2);
|
|
121
121
|
}
|
|
@@ -127,7 +127,7 @@ function keyWasPressed(key, device=0)
|
|
|
127
127
|
* @memberof Input */
|
|
128
128
|
function keyWasReleased(key, device=0)
|
|
129
129
|
{
|
|
130
|
-
ASSERT(
|
|
130
|
+
ASSERT(isStringLike(key), 'key must be a number or string');
|
|
131
131
|
ASSERT(device > 0 || typeof key !== 'number' || key < 3, 'use code string for keyboard');
|
|
132
132
|
return !!(inputData[device]?.[key] & 4);
|
|
133
133
|
}
|
|
@@ -141,10 +141,10 @@ function keyWasReleased(key, device=0)
|
|
|
141
141
|
* @memberof Input */
|
|
142
142
|
function keyDirection(up='ArrowUp', down='ArrowDown', left='ArrowLeft', right='ArrowRight')
|
|
143
143
|
{
|
|
144
|
-
ASSERT(
|
|
145
|
-
ASSERT(
|
|
146
|
-
ASSERT(
|
|
147
|
-
ASSERT(
|
|
144
|
+
ASSERT(isStringLike(up), 'up key must be a string');
|
|
145
|
+
ASSERT(isStringLike(down), 'down key must be a string');
|
|
146
|
+
ASSERT(isStringLike(left), 'left key must be a string');
|
|
147
|
+
ASSERT(isStringLike(right), 'right key must be a string');
|
|
148
148
|
const k = (key)=> keyIsDown(key) ? 1 : 0;
|
|
149
149
|
return vec2(k(right) - k(left), k(up) - k(down));
|
|
150
150
|
}
|
package/src/engineMath.js
CHANGED
|
@@ -292,13 +292,15 @@ function oscillate(frequency=1, amplitude=1, t=time, offset=0, type=0)
|
|
|
292
292
|
function isNumber(n) { return typeof n === 'number' && !isNaN(n); }
|
|
293
293
|
|
|
294
294
|
/**
|
|
295
|
-
* Check if
|
|
295
|
+
* Check if a value is stringifiable — i.e. it has a toString that returns
|
|
296
|
+
* a string. Use this for ASSERTs and inputs that will be coerced to text;
|
|
297
|
+
* use `typeof x === 'string'` inline if you need strict-string semantics.
|
|
296
298
|
* - Returns true for strings, numbers, and most objects
|
|
297
299
|
* - Returns false for null and undefined
|
|
298
300
|
* @param {any} s
|
|
299
301
|
* @return {boolean}
|
|
300
302
|
* @memberof Math */
|
|
301
|
-
function
|
|
303
|
+
function isStringLike(s) { return s != null && typeof s?.toString() === 'string'; }
|
|
302
304
|
|
|
303
305
|
/**
|
|
304
306
|
* Check if object is an array
|
|
@@ -1042,7 +1044,7 @@ class Color
|
|
|
1042
1044
|
* @return {Color} */
|
|
1043
1045
|
setHex(hex)
|
|
1044
1046
|
{
|
|
1045
|
-
ASSERT(
|
|
1047
|
+
ASSERT(isStringLike(hex), 'Color hex code must be a string');
|
|
1046
1048
|
ASSERT(hex[0] === '#', 'Color hex code must start with #');
|
|
1047
1049
|
ASSERT([4,5,7,9].includes(hex.length), 'Invalid hex');
|
|
1048
1050
|
|
package/src/engineUtilities.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* - File saving (text, canvas, data URLs)
|
|
7
7
|
* - Native share dialog support
|
|
8
8
|
* - Local storage save data management
|
|
9
|
+
* - Gradient noise (1D and 2D)
|
|
9
10
|
* @namespace Utilities
|
|
10
11
|
*/
|
|
11
12
|
|
|
@@ -155,8 +156,8 @@ function saveCanvas(canvas, filename='screenshot', type='image/png')
|
|
|
155
156
|
* @memberof Utilities */
|
|
156
157
|
function saveDataURL(url, filename='download', revokeTime)
|
|
157
158
|
{
|
|
158
|
-
ASSERT(
|
|
159
|
-
ASSERT(
|
|
159
|
+
ASSERT(isStringLike(url), 'saveDataURL requires url string');
|
|
160
|
+
ASSERT(isStringLike(filename), 'saveDataURL requires filename string');
|
|
160
161
|
|
|
161
162
|
// create link for saving screenshots
|
|
162
163
|
const link = document.createElement('a');
|
|
@@ -174,8 +175,8 @@ function saveDataURL(url, filename='download', revokeTime)
|
|
|
174
175
|
* @memberof Utilities */
|
|
175
176
|
function shareURL(title, url, callback)
|
|
176
177
|
{
|
|
177
|
-
ASSERT(
|
|
178
|
-
ASSERT(
|
|
178
|
+
ASSERT(isStringLike(title), 'shareURL requires title string');
|
|
179
|
+
ASSERT(isStringLike(url), 'shareURL requires url string');
|
|
179
180
|
navigator.share?.({title, url}).then(()=>callback?.());
|
|
180
181
|
}
|
|
181
182
|
|
|
@@ -188,7 +189,7 @@ function shareURL(title, url, callback)
|
|
|
188
189
|
* @memberof Utilities */
|
|
189
190
|
function readSaveData(saveName, defaultSaveData)
|
|
190
191
|
{
|
|
191
|
-
ASSERT(
|
|
192
|
+
ASSERT(isStringLike(saveName), 'loadData requires saveName string');
|
|
192
193
|
|
|
193
194
|
// replace undefined values with defaults; tolerate corrupt JSON
|
|
194
195
|
const data = localStorage[saveName];
|
|
@@ -207,6 +208,48 @@ function readSaveData(saveName, defaultSaveData)
|
|
|
207
208
|
* @memberof Utilities */
|
|
208
209
|
function writeSaveData(saveName, saveData)
|
|
209
210
|
{
|
|
210
|
-
ASSERT(
|
|
211
|
+
ASSERT(isStringLike(saveName), 'saveData requires saveName string');
|
|
211
212
|
localStorage[saveName] = JSON.stringify(saveData);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
216
|
+
|
|
217
|
+
// Deterministic well-distributed hash of an integer lattice index to [0, 1).
|
|
218
|
+
// Murmur3 finalizer — adjacent integers produce uncorrelated outputs.
|
|
219
|
+
function noiseHash(i)
|
|
220
|
+
{
|
|
221
|
+
let h = (i | 0) ^ 0x9e3779b9;
|
|
222
|
+
h = Math.imul(h ^ (h >>> 16), 0x85ebca6b);
|
|
223
|
+
h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35);
|
|
224
|
+
h ^= h >>> 16;
|
|
225
|
+
return (h >>> 0) / 2**32;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** 1D gradient noise — returns a smooth value in [0, 1] for any real x.
|
|
229
|
+
* Integer inputs land on deterministic lattice values; non-integer inputs
|
|
230
|
+
* are interpolated with smoothStep for C1 continuity.
|
|
231
|
+
* @param {number} x
|
|
232
|
+
* @return {number}
|
|
233
|
+
* @memberof Utilities */
|
|
234
|
+
function noise1D(x)
|
|
235
|
+
{
|
|
236
|
+
const i = floor(x);
|
|
237
|
+
return lerp(noiseHash(i), noiseHash(i + 1), smoothStep(x - i));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** 2D gradient noise — returns a smooth value in [0, 1] for any real (x, y).
|
|
241
|
+
* @param {number} x
|
|
242
|
+
* @param {number} y
|
|
243
|
+
* @return {number}
|
|
244
|
+
* @memberof Utilities */
|
|
245
|
+
function noise2D(x, y)
|
|
246
|
+
{
|
|
247
|
+
const ix = floor(x), iy = floor(y);
|
|
248
|
+
const fx = smoothStep(x - ix), fy = smoothStep(y - iy);
|
|
249
|
+
// large prime decorrelates neighboring rows
|
|
250
|
+
const h = (a, b) => noiseHash(a + b * 374761393);
|
|
251
|
+
return lerp(
|
|
252
|
+
lerp(h(ix, iy ), h(ix + 1, iy ), fx),
|
|
253
|
+
lerp(h(ix, iy + 1), h(ix + 1, iy + 1), fx),
|
|
254
|
+
fy);
|
|
212
255
|
}
|
package/src/engineWebGL.js
CHANGED
|
@@ -505,7 +505,8 @@ function glFlush()
|
|
|
505
505
|
glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, glBatchCount);
|
|
506
506
|
else
|
|
507
507
|
glContext.drawArraysInstanced(glContext.TRIANGLE_STRIP, 0, 4, glBatchCount);
|
|
508
|
-
drawCount
|
|
508
|
+
++drawCount;
|
|
509
|
+
primitiveCount += glBatchCount;
|
|
509
510
|
glBatchCount = 0;
|
|
510
511
|
}
|
|
511
512
|
glBatchAdditive = glAdditive;
|
|
@@ -566,6 +567,67 @@ function glDraw(x, y, sizeX, sizeY, angle=0, uv0X=0, uv0Y=0, uv1X=1, uv1Y=1, rgb
|
|
|
566
567
|
glPositionData[offset++] = angle;
|
|
567
568
|
}
|
|
568
569
|
|
|
570
|
+
/** Add an untextured rect to the gl draw list
|
|
571
|
+
* Picks the optimal path: if already in poly mode, emits a tristrip rect
|
|
572
|
+
* so it batches with surrounding polys; otherwise uses the instanced path
|
|
573
|
+
* with uvs and rgba zeroed so the color falls through the additive slot.
|
|
574
|
+
* @param {number} x
|
|
575
|
+
* @param {number} y
|
|
576
|
+
* @param {number} sizeX
|
|
577
|
+
* @param {number} sizeY
|
|
578
|
+
* @param {number} angle
|
|
579
|
+
* @param {number} rgba - color as 32-bit integer
|
|
580
|
+
* @memberof WebGL */
|
|
581
|
+
function glDrawUntextured(x, y, sizeX, sizeY, angle, rgba)
|
|
582
|
+
{
|
|
583
|
+
if (glPolyMode)
|
|
584
|
+
{
|
|
585
|
+
// batch with surrounding polys as a 4-vertex tristrip rect
|
|
586
|
+
const vertCount = 6; // 4 corners + 2 degenerate verts
|
|
587
|
+
if (glBatchCount+vertCount >= gl_MAX_POLY_VERTEXES || glBatchAdditive !== glAdditive)
|
|
588
|
+
glFlush();
|
|
589
|
+
|
|
590
|
+
// compute rotated corners in world space (matches glDrawPointsTransform rotation)
|
|
591
|
+
const hx = sizeX*.5, hy = sizeY*.5;
|
|
592
|
+
const c = cos(angle), s = sin(angle);
|
|
593
|
+
const chx = c*hx, shx = s*hx, chy = c*hy, shy = s*hy;
|
|
594
|
+
const x0 = x - chx - shy, y0 = y + shx - chy; // (-hx,-hy)
|
|
595
|
+
const x1 = x + chx - shy, y1 = y - shx - chy; // ( hx,-hy)
|
|
596
|
+
const x2 = x - chx + shy, y2 = y + shx + chy; // (-hx, hy)
|
|
597
|
+
const x3 = x + chx + shy, y3 = y - shx + chy; // ( hx, hy)
|
|
598
|
+
|
|
599
|
+
// write tristrip with leading/trailing degenerate verts
|
|
600
|
+
let offset = glBatchCount * gl_INDICES_PER_POLY_VERTEX;
|
|
601
|
+
glPositionData[offset++] = x0; glPositionData[offset++] = y0; glColorData[offset++] = rgba;
|
|
602
|
+
glPositionData[offset++] = x0; glPositionData[offset++] = y0; glColorData[offset++] = rgba;
|
|
603
|
+
glPositionData[offset++] = x1; glPositionData[offset++] = y1; glColorData[offset++] = rgba;
|
|
604
|
+
glPositionData[offset++] = x2; glPositionData[offset++] = y2; glColorData[offset++] = rgba;
|
|
605
|
+
glPositionData[offset++] = x3; glPositionData[offset++] = y3; glColorData[offset++] = rgba;
|
|
606
|
+
glPositionData[offset++] = x3; glPositionData[offset++] = y3; glColorData[offset++] = rgba;
|
|
607
|
+
glBatchCount += vertCount;
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// instanced path: zero uvs and rgba so the texture contribution is killed,
|
|
612
|
+
// then carry the real color in the additive slot
|
|
613
|
+
if (glBatchCount >= gl_MAX_INSTANCES || glBatchAdditive !== glAdditive)
|
|
614
|
+
glFlush();
|
|
615
|
+
glSetInstancedMode();
|
|
616
|
+
|
|
617
|
+
let offset = glBatchCount++ * gl_INDICES_PER_INSTANCE;
|
|
618
|
+
glPositionData[offset++] = x;
|
|
619
|
+
glPositionData[offset++] = y;
|
|
620
|
+
glPositionData[offset++] = sizeX;
|
|
621
|
+
glPositionData[offset++] = sizeY;
|
|
622
|
+
glPositionData[offset++] = 0;
|
|
623
|
+
glPositionData[offset++] = 0;
|
|
624
|
+
glPositionData[offset++] = 0;
|
|
625
|
+
glPositionData[offset++] = 0;
|
|
626
|
+
glColorData[offset++] = 0;
|
|
627
|
+
glColorData[offset++] = rgba;
|
|
628
|
+
glPositionData[offset++] = angle;
|
|
629
|
+
}
|
|
630
|
+
|
|
569
631
|
/** Transform and add a polygon to the gl draw list
|
|
570
632
|
* @param {Array<Vector2>} points - Array of Vector2 points
|
|
571
633
|
* @param {number} rgba - Color of the polygon as a 32-bit integer
|