littlejsengine 1.17.10 → 1.17.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/littlejs.d.ts +29 -9
- package/dist/littlejs.esm.js +63 -63
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +62 -63
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +61 -62
- package/examples/electron/index.html +2 -2
- package/examples/games.jpg +0 -0
- package/examples/screenshot.jpg +0 -0
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/fontImage.js +1 -1
- package/examples/starter/index.html +2 -2
- package/package.json +1 -1
- package/plugins/pluginExport.js +1 -0
- package/plugins/uiSystem.js +4 -5
- package/src/engine.js +9 -31
- package/src/engineAudio.js +5 -5
- package/src/engineDebug.js +1 -1
- package/src/engineDraw.js +34 -12
- package/src/engineMath.js +6 -4
- package/src/engineTileLayer.js +2 -2
package/dist/littlejs.release.js
CHANGED
|
@@ -33,7 +33,7 @@ const engineName = 'LittleJS';
|
|
|
33
33
|
* @type {string}
|
|
34
34
|
* @default
|
|
35
35
|
* @memberof Engine */
|
|
36
|
-
const engineVersion = '1.17.
|
|
36
|
+
const engineVersion = '1.17.11';
|
|
37
37
|
|
|
38
38
|
/** Frames per second to update
|
|
39
39
|
* @type {number}
|
|
@@ -396,33 +396,11 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
396
396
|
workReadContext = workReadCanvas.getContext('2d', { willReadFrequently: true });
|
|
397
397
|
|
|
398
398
|
// create promises for loading images
|
|
399
|
-
const promises = imageSources.map((src,
|
|
400
|
-
new Promise(resolve =>
|
|
401
|
-
{
|
|
402
|
-
ASSERT(isString(src), 'imageSources must be an array of strings');
|
|
403
|
-
|
|
404
|
-
const image = new Image;
|
|
405
|
-
image.onerror = image.onload = ()=>
|
|
406
|
-
{
|
|
407
|
-
const textureInfo = new TextureInfo(image);
|
|
408
|
-
textureInfos[textureIndex] = textureInfo;
|
|
409
|
-
resolve();
|
|
410
|
-
}
|
|
411
|
-
image.crossOrigin = 'anonymous';
|
|
412
|
-
image.src = src;
|
|
413
|
-
})
|
|
414
|
-
);
|
|
399
|
+
const promises = imageSources.map((src, i)=> loadTexture(i, src));
|
|
415
400
|
|
|
401
|
+
// no images to load
|
|
416
402
|
if (!imageSources.length)
|
|
417
|
-
|
|
418
|
-
// no images to load
|
|
419
|
-
promises.push(new Promise(resolve =>
|
|
420
|
-
{
|
|
421
|
-
const textureInfo = new TextureInfo(new Image);
|
|
422
|
-
textureInfos[0] = textureInfo;
|
|
423
|
-
resolve();
|
|
424
|
-
}));
|
|
425
|
-
}
|
|
403
|
+
promises.push(loadTexture(0));
|
|
426
404
|
|
|
427
405
|
// load engine font image
|
|
428
406
|
promises.push(fontImageInit());
|
|
@@ -649,7 +627,7 @@ function drawEngineLogo(t)
|
|
|
649
627
|
x.lineWidth = .1+p*3.9;
|
|
650
628
|
x.textAlign = 'center';
|
|
651
629
|
x.textBaseline = 'top';
|
|
652
|
-
rect(11,Y+
|
|
630
|
+
rect(11,Y+1,59,8*p,-1);
|
|
653
631
|
x.beginPath();
|
|
654
632
|
|
|
655
633
|
let w2 = 0;
|
|
@@ -672,8 +650,8 @@ function drawEngineLogo(t)
|
|
|
672
650
|
rect(25,15,8,25,-1); // cab front
|
|
673
651
|
rect(10,40,15,-25,1); // cab back
|
|
674
652
|
rect(14,21,7,9,2); // cab window
|
|
675
|
-
rect(38,
|
|
676
|
-
|
|
653
|
+
rect(38,20,6,-6,2); // little stack
|
|
654
|
+
|
|
677
655
|
// big stack
|
|
678
656
|
rect(49,20,10,-6,0);
|
|
679
657
|
const stackPoints = [vec2(44,8),vec2(64,8),vec2(59,8+6*p),vec2(49,8+6*p)];
|
|
@@ -681,8 +659,8 @@ function drawEngineLogo(t)
|
|
|
681
659
|
rect(44,8,20,-7,0);
|
|
682
660
|
|
|
683
661
|
// engine
|
|
684
|
-
for (let i=5;i--;) circle(59-i*6,30,10,0,
|
|
685
|
-
circle(59,30,4,0,
|
|
662
|
+
for (let i=5;i--;) circle(59-i*6*p,30,10,0,2*PI,1,0);
|
|
663
|
+
circle(59,30,4,0,7,2); // light
|
|
686
664
|
|
|
687
665
|
// engine outline
|
|
688
666
|
rect(35,20,24,0); // top
|
|
@@ -693,9 +671,7 @@ function drawEngineLogo(t)
|
|
|
693
671
|
rect(17,40,43,14,-1); // bottom center
|
|
694
672
|
|
|
695
673
|
// wheels
|
|
696
|
-
for (let i=3;i--;)
|
|
697
|
-
for (let j=2;j--;)
|
|
698
|
-
circle(15*i+17,47,j?7:1,PI,3*PI,2);
|
|
674
|
+
for (let i=3;i--;) for (let j=2;j--;) circle(17+15*i,47,j?7:1,0,2*PI,2);
|
|
699
675
|
|
|
700
676
|
// cowcatcher
|
|
701
677
|
for (let i=2;i--;)
|
|
@@ -1012,7 +988,9 @@ function wave(frequency=1, amplitude=1, t=time, offset=0)
|
|
|
1012
988
|
function isNumber(n) { return typeof n === 'number' && !isNaN(n); }
|
|
1013
989
|
|
|
1014
990
|
/**
|
|
1015
|
-
* Check if object
|
|
991
|
+
* Check if object can be converted to a string (has a toString method)
|
|
992
|
+
* - Returns true for strings, numbers, and most objects
|
|
993
|
+
* - Returns false for null and undefined
|
|
1016
994
|
* @param {any} s
|
|
1017
995
|
* @return {boolean}
|
|
1018
996
|
* @memberof Math */
|
|
@@ -1089,7 +1067,7 @@ function lineTest(posStart, posEnd, testFunction, normal)
|
|
|
1089
1067
|
if (stepX < 0)
|
|
1090
1068
|
hitPos.x -= e;
|
|
1091
1069
|
}
|
|
1092
|
-
if (stepY < 0)
|
|
1070
|
+
else if (stepY < 0)
|
|
1093
1071
|
hitPos.y -= e;
|
|
1094
1072
|
|
|
1095
1073
|
// set normal
|
|
@@ -1796,7 +1774,7 @@ class Color
|
|
|
1796
1774
|
* @memberof Math */
|
|
1797
1775
|
const WHITE = debugProtectConstant(rgb());
|
|
1798
1776
|
|
|
1799
|
-
/** Color - Clear White #
|
|
1777
|
+
/** Color - Clear White #ffffff00 with 0 alpha
|
|
1800
1778
|
* @type {Color}
|
|
1801
1779
|
* @memberof Math */
|
|
1802
1780
|
const CLEAR_WHITE = debugProtectConstant(rgb(1,1,1,0));
|
|
@@ -1806,7 +1784,7 @@ const CLEAR_WHITE = debugProtectConstant(rgb(1,1,1,0));
|
|
|
1806
1784
|
* @memberof Math */
|
|
1807
1785
|
const BLACK = debugProtectConstant(rgb(0,0,0));
|
|
1808
1786
|
|
|
1809
|
-
/** Color - Clear Black #
|
|
1787
|
+
/** Color - Clear Black #00000000 with 0 alpha
|
|
1810
1788
|
* @type {Color}
|
|
1811
1789
|
* @memberof Math */
|
|
1812
1790
|
const CLEAR_BLACK = debugProtectConstant(rgb(0,0,0,0));
|
|
@@ -3901,6 +3879,31 @@ function drawTextScreen(text, pos, size, color=WHITE, lineWidth=0, lineColor=BLA
|
|
|
3901
3879
|
///////////////////////////////////////////////////////////////////////////////
|
|
3902
3880
|
// Drawing utilities
|
|
3903
3881
|
|
|
3882
|
+
/** Load a texture at a specific index
|
|
3883
|
+
* @param {number} textureIndex - Index to store the texture at
|
|
3884
|
+
* @param {string} [src] - Image source path
|
|
3885
|
+
* @return {Promise} Promise that resolves when texture is loaded
|
|
3886
|
+
* @memberof Draw */
|
|
3887
|
+
async function loadTexture(textureIndex, src)
|
|
3888
|
+
{
|
|
3889
|
+
ASSERT(isNumber(textureIndex), 'textureIndex must be a number');
|
|
3890
|
+
ASSERT(!textureInfos[textureIndex], 'textureIndex is already loaded!');
|
|
3891
|
+
ASSERT(!src || isString(src), 'image src must be a string');
|
|
3892
|
+
|
|
3893
|
+
const image = new Image;
|
|
3894
|
+
if (src)
|
|
3895
|
+
{
|
|
3896
|
+
await new Promise(resolve =>
|
|
3897
|
+
{
|
|
3898
|
+
image.onerror = image.onload = resolve;
|
|
3899
|
+
image.crossOrigin = 'anonymous';
|
|
3900
|
+
image.src = src;
|
|
3901
|
+
});
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3904
|
+
textureInfos[textureIndex] = new TextureInfo(image);
|
|
3905
|
+
}
|
|
3906
|
+
|
|
3904
3907
|
/** Convert from screen to world space coordinates
|
|
3905
3908
|
* @param {Vector2} screenPos
|
|
3906
3909
|
* @return {Vector2}
|
|
@@ -4281,23 +4284,20 @@ class FontImage
|
|
|
4281
4284
|
}
|
|
4282
4285
|
|
|
4283
4286
|
// load engine font, called automatically on startup
|
|
4284
|
-
function fontImageInit()
|
|
4287
|
+
async function fontImageInit()
|
|
4285
4288
|
{
|
|
4286
|
-
|
|
4289
|
+
const image = new Image;
|
|
4290
|
+
await new Promise(resolve =>
|
|
4287
4291
|
{
|
|
4288
|
-
|
|
4289
|
-
const image = new Image;
|
|
4290
|
-
image.onerror = image.onload = ()=>
|
|
4291
|
-
{
|
|
4292
|
-
const tilePos=vec2(), tileSize=vec2(8), padding=1, bleed=0;
|
|
4293
|
-
const textureInfo = new TextureInfo(image);
|
|
4294
|
-
const tileInfo = new TileInfo(tilePos, tileSize, textureInfo, padding, bleed);
|
|
4295
|
-
engineFontImage = new FontImage(tileInfo);
|
|
4296
|
-
resolve();
|
|
4297
|
-
}
|
|
4292
|
+
image.onerror = image.onload = resolve;
|
|
4298
4293
|
image.crossOrigin = 'anonymous';
|
|
4299
4294
|
image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg==';
|
|
4300
4295
|
});
|
|
4296
|
+
|
|
4297
|
+
const tilePos=vec2(), tileSize=vec2(8), padding=1, bleed=0;
|
|
4298
|
+
const textureInfo = new TextureInfo(image);
|
|
4299
|
+
const tileInfo = new TileInfo(tilePos, tileSize, textureInfo, padding, bleed);
|
|
4300
|
+
engineFontImage = new FontImage(tileInfo);
|
|
4301
4301
|
}
|
|
4302
4302
|
/**
|
|
4303
4303
|
* LittleJS Input System
|
|
@@ -5280,7 +5280,7 @@ class Sound
|
|
|
5280
5280
|
|
|
5281
5281
|
/** Loads a sound from a URL and decodes it into sample data.
|
|
5282
5282
|
* @param {string} filename
|
|
5283
|
-
* @return {Promise
|
|
5283
|
+
* @return {Promise} */
|
|
5284
5284
|
async loadSound(filename)
|
|
5285
5285
|
{
|
|
5286
5286
|
const response = await fetch(filename);
|
|
@@ -5338,7 +5338,7 @@ class Sound
|
|
|
5338
5338
|
* // Control the individual instance
|
|
5339
5339
|
* instance.setVolume(.5);
|
|
5340
5340
|
* instance.pause();
|
|
5341
|
-
* instance.
|
|
5341
|
+
* instance.resume();
|
|
5342
5342
|
* instance.stop();
|
|
5343
5343
|
*/
|
|
5344
5344
|
class SoundInstance
|
|
@@ -5452,7 +5452,7 @@ class SoundInstance
|
|
|
5452
5452
|
this.startTime = undefined;
|
|
5453
5453
|
}
|
|
5454
5454
|
|
|
5455
|
-
/**
|
|
5455
|
+
/** Resume this sound instance */
|
|
5456
5456
|
resume()
|
|
5457
5457
|
{
|
|
5458
5458
|
if (!this.isPaused()) return;
|
|
@@ -5466,8 +5466,8 @@ class SoundInstance
|
|
|
5466
5466
|
*/
|
|
5467
5467
|
isPlaying() { return !!this.source; }
|
|
5468
5468
|
|
|
5469
|
-
/** Check if this instance is paused
|
|
5470
|
-
* @return {boolean} - True if
|
|
5469
|
+
/** Check if this instance is paused or stopped (not currently playing)
|
|
5470
|
+
* @return {boolean} - True if not playing
|
|
5471
5471
|
*/
|
|
5472
5472
|
isPaused() { return !this.isPlaying(); }
|
|
5473
5473
|
|
|
@@ -6393,7 +6393,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
6393
6393
|
collisionTest(pos, size=new Vector2, callbackObject)
|
|
6394
6394
|
{
|
|
6395
6395
|
ASSERT(isVector2(pos) && isVector2(size), 'pos and size must be Vector2s');
|
|
6396
|
-
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a
|
|
6396
|
+
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a function or EngineObject');
|
|
6397
6397
|
|
|
6398
6398
|
// make function to check for collision
|
|
6399
6399
|
const collisionTest = callbackObject ? typeof callbackObject === 'function' ?
|
|
@@ -6430,7 +6430,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
6430
6430
|
collisionRaycast(posStart, posEnd, callbackObject, normal)
|
|
6431
6431
|
{
|
|
6432
6432
|
ASSERT(isVector2(posStart) && isVector2(posEnd), 'positions must be Vector2s');
|
|
6433
|
-
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a
|
|
6433
|
+
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a function or EngineObject');
|
|
6434
6434
|
|
|
6435
6435
|
// make function to check for collision
|
|
6436
6436
|
const collisionTest = callbackObject ? typeof callbackObject === 'function' ?
|
|
@@ -9761,7 +9761,7 @@ class UIScrollbar extends UIObject
|
|
|
9761
9761
|
else
|
|
9762
9762
|
{
|
|
9763
9763
|
// draw the scrollbar handle
|
|
9764
|
-
const value = isHorizontal ? this.value : 1 - this.value;
|
|
9764
|
+
const value = clamp(isHorizontal ? this.value : 1 - this.value);
|
|
9765
9765
|
const p = (barWidth - handleWidth) * (value - .5);
|
|
9766
9766
|
const pos = this.pos.add(isHorizontal ? vec2(p, 0) : vec2(0, p));
|
|
9767
9767
|
const color = this.disabled ? this.disabledColor : this.handleColor;
|
|
@@ -9830,12 +9830,11 @@ class UIVideo extends UIObject
|
|
|
9830
9830
|
|
|
9831
9831
|
/** Play or resume the video
|
|
9832
9832
|
* @return {Promise} Promise that resolves when playback starts */
|
|
9833
|
-
play()
|
|
9833
|
+
async play()
|
|
9834
9834
|
{
|
|
9835
9835
|
// try to play the video, catch any errors (autoplay may be blocked)
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
return promise;
|
|
9836
|
+
try { await this.video.play(); }
|
|
9837
|
+
catch(e) {}
|
|
9839
9838
|
}
|
|
9840
9839
|
|
|
9841
9840
|
/** Pause the video */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</head><body>
|
|
8
8
|
|
|
9
9
|
<!-- LittleJS Engine -->
|
|
10
|
-
<script src=../../dist/littlejs.js?1.17.
|
|
10
|
+
<script src=../../dist/littlejs.js?1.17.11></script>
|
|
11
11
|
|
|
12
12
|
<!-- Add your game scripts here -->
|
|
13
|
-
<script src=game.js?1.17.
|
|
13
|
+
<script src=game.js?1.17.11></script>
|
|
Binary file
|
package/examples/screenshot.jpg
CHANGED
|
Binary file
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</head><body>
|
|
8
8
|
|
|
9
9
|
<!-- LittleJS Engine -->
|
|
10
|
-
<script src=../../dist/littlejs.js?1.17.
|
|
10
|
+
<script src=../../dist/littlejs.js?1.17.11></script>
|
|
11
11
|
|
|
12
12
|
<!-- LittleJS Engine Source
|
|
13
13
|
<script src=../../src/engine.js></script>
|
|
@@ -32,4 +32,4 @@
|
|
|
32
32
|
-->
|
|
33
33
|
|
|
34
34
|
<!-- Add your game scripts here -->
|
|
35
|
-
<script src=game.js?1.17.
|
|
35
|
+
<script src=game.js?1.17.11></script>
|
package/package.json
CHANGED
package/plugins/pluginExport.js
CHANGED
package/plugins/uiSystem.js
CHANGED
|
@@ -1209,7 +1209,7 @@ class UIScrollbar extends UIObject
|
|
|
1209
1209
|
else
|
|
1210
1210
|
{
|
|
1211
1211
|
// draw the scrollbar handle
|
|
1212
|
-
const value = isHorizontal ? this.value : 1 - this.value;
|
|
1212
|
+
const value = clamp(isHorizontal ? this.value : 1 - this.value);
|
|
1213
1213
|
const p = (barWidth - handleWidth) * (value - .5);
|
|
1214
1214
|
const pos = this.pos.add(isHorizontal ? vec2(p, 0) : vec2(0, p));
|
|
1215
1215
|
const color = this.disabled ? this.disabledColor : this.handleColor;
|
|
@@ -1278,12 +1278,11 @@ class UIVideo extends UIObject
|
|
|
1278
1278
|
|
|
1279
1279
|
/** Play or resume the video
|
|
1280
1280
|
* @return {Promise} Promise that resolves when playback starts */
|
|
1281
|
-
play()
|
|
1281
|
+
async play()
|
|
1282
1282
|
{
|
|
1283
1283
|
// try to play the video, catch any errors (autoplay may be blocked)
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
return promise;
|
|
1284
|
+
try { await this.video.play(); }
|
|
1285
|
+
catch(e) {}
|
|
1287
1286
|
}
|
|
1288
1287
|
|
|
1289
1288
|
/** Pause the video */
|
package/src/engine.js
CHANGED
|
@@ -30,7 +30,7 @@ const engineName = 'LittleJS';
|
|
|
30
30
|
* @type {string}
|
|
31
31
|
* @default
|
|
32
32
|
* @memberof Engine */
|
|
33
|
-
const engineVersion = '1.17.
|
|
33
|
+
const engineVersion = '1.17.11';
|
|
34
34
|
|
|
35
35
|
/** Frames per second to update
|
|
36
36
|
* @type {number}
|
|
@@ -393,33 +393,11 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
393
393
|
workReadContext = workReadCanvas.getContext('2d', { willReadFrequently: true });
|
|
394
394
|
|
|
395
395
|
// create promises for loading images
|
|
396
|
-
const promises = imageSources.map((src,
|
|
397
|
-
new Promise(resolve =>
|
|
398
|
-
{
|
|
399
|
-
ASSERT(isString(src), 'imageSources must be an array of strings');
|
|
400
|
-
|
|
401
|
-
const image = new Image;
|
|
402
|
-
image.onerror = image.onload = ()=>
|
|
403
|
-
{
|
|
404
|
-
const textureInfo = new TextureInfo(image);
|
|
405
|
-
textureInfos[textureIndex] = textureInfo;
|
|
406
|
-
resolve();
|
|
407
|
-
}
|
|
408
|
-
image.crossOrigin = 'anonymous';
|
|
409
|
-
image.src = src;
|
|
410
|
-
})
|
|
411
|
-
);
|
|
396
|
+
const promises = imageSources.map((src, i)=> loadTexture(i, src));
|
|
412
397
|
|
|
398
|
+
// no images to load
|
|
413
399
|
if (!imageSources.length)
|
|
414
|
-
|
|
415
|
-
// no images to load
|
|
416
|
-
promises.push(new Promise(resolve =>
|
|
417
|
-
{
|
|
418
|
-
const textureInfo = new TextureInfo(new Image);
|
|
419
|
-
textureInfos[0] = textureInfo;
|
|
420
|
-
resolve();
|
|
421
|
-
}));
|
|
422
|
-
}
|
|
400
|
+
promises.push(loadTexture(0));
|
|
423
401
|
|
|
424
402
|
// load engine font image
|
|
425
403
|
promises.push(fontImageInit());
|
|
@@ -646,7 +624,7 @@ function drawEngineLogo(t)
|
|
|
646
624
|
x.lineWidth = .1+p*3.9;
|
|
647
625
|
x.textAlign = 'center';
|
|
648
626
|
x.textBaseline = 'top';
|
|
649
|
-
rect(11,Y+
|
|
627
|
+
rect(11,Y+1,59,8*p,-1);
|
|
650
628
|
x.beginPath();
|
|
651
629
|
|
|
652
630
|
let w2 = 0;
|
|
@@ -669,8 +647,8 @@ function drawEngineLogo(t)
|
|
|
669
647
|
rect(25,15,8,25,-1); // cab front
|
|
670
648
|
rect(10,40,15,-25,1); // cab back
|
|
671
649
|
rect(14,21,7,9,2); // cab window
|
|
672
|
-
rect(38,
|
|
673
|
-
|
|
650
|
+
rect(38,20,6,-6,2); // little stack
|
|
651
|
+
|
|
674
652
|
// big stack
|
|
675
653
|
rect(49,20,10,-6,0);
|
|
676
654
|
const stackPoints = [vec2(44,8),vec2(64,8),vec2(59,8+6*p),vec2(49,8+6*p)];
|
|
@@ -678,7 +656,7 @@ function drawEngineLogo(t)
|
|
|
678
656
|
rect(44,8,20,-7,0);
|
|
679
657
|
|
|
680
658
|
// engine
|
|
681
|
-
for (let i=5;i--;) circle(59-i*6,30,10,0,
|
|
659
|
+
for (let i=5;i--;) circle(59-i*6*p,30,10,0,2*PI,1,0);
|
|
682
660
|
circle(59,30,4,0,7,2); // light
|
|
683
661
|
|
|
684
662
|
// engine outline
|
|
@@ -690,7 +668,7 @@ function drawEngineLogo(t)
|
|
|
690
668
|
rect(17,40,43,14,-1); // bottom center
|
|
691
669
|
|
|
692
670
|
// wheels
|
|
693
|
-
for (let i=3;i--;) for (let j=2;j--;) circle(15*i
|
|
671
|
+
for (let i=3;i--;) for (let j=2;j--;) circle(17+15*i,47,j?7:1,0,2*PI,2);
|
|
694
672
|
|
|
695
673
|
// cowcatcher
|
|
696
674
|
for (let i=2;i--;)
|
package/src/engineAudio.js
CHANGED
|
@@ -204,7 +204,7 @@ class Sound
|
|
|
204
204
|
|
|
205
205
|
/** Loads a sound from a URL and decodes it into sample data.
|
|
206
206
|
* @param {string} filename
|
|
207
|
-
* @return {Promise
|
|
207
|
+
* @return {Promise} */
|
|
208
208
|
async loadSound(filename)
|
|
209
209
|
{
|
|
210
210
|
const response = await fetch(filename);
|
|
@@ -262,7 +262,7 @@ class Sound
|
|
|
262
262
|
* // Control the individual instance
|
|
263
263
|
* instance.setVolume(.5);
|
|
264
264
|
* instance.pause();
|
|
265
|
-
* instance.
|
|
265
|
+
* instance.resume();
|
|
266
266
|
* instance.stop();
|
|
267
267
|
*/
|
|
268
268
|
class SoundInstance
|
|
@@ -376,7 +376,7 @@ class SoundInstance
|
|
|
376
376
|
this.startTime = undefined;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
/**
|
|
379
|
+
/** Resume this sound instance */
|
|
380
380
|
resume()
|
|
381
381
|
{
|
|
382
382
|
if (!this.isPaused()) return;
|
|
@@ -390,8 +390,8 @@ class SoundInstance
|
|
|
390
390
|
*/
|
|
391
391
|
isPlaying() { return !!this.source; }
|
|
392
392
|
|
|
393
|
-
/** Check if this instance is paused
|
|
394
|
-
* @return {boolean} - True if
|
|
393
|
+
/** Check if this instance is paused or stopped (not currently playing)
|
|
394
|
+
* @return {boolean} - True if not playing
|
|
395
395
|
*/
|
|
396
396
|
isPaused() { return !this.isPlaying(); }
|
|
397
397
|
|
package/src/engineDebug.js
CHANGED
|
@@ -158,7 +158,7 @@ function debugPoint(pos, color, time, angle, screenSpace=false)
|
|
|
158
158
|
function debugLine(posA, posB, color, width=.1, time, screenSpace=false)
|
|
159
159
|
{
|
|
160
160
|
ASSERT(isVector2(posA), 'posA must be a vec2');
|
|
161
|
-
ASSERT(isVector2(posB), 'posB must be
|
|
161
|
+
ASSERT(isVector2(posB), 'posB must be a vec2');
|
|
162
162
|
ASSERT(isNumber(width), 'width must be a number');
|
|
163
163
|
|
|
164
164
|
const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
|
package/src/engineDraw.js
CHANGED
|
@@ -729,6 +729,31 @@ function drawTextScreen(text, pos, size, color=WHITE, lineWidth=0, lineColor=BLA
|
|
|
729
729
|
///////////////////////////////////////////////////////////////////////////////
|
|
730
730
|
// Drawing utilities
|
|
731
731
|
|
|
732
|
+
/** Load a texture at a specific index
|
|
733
|
+
* @param {number} textureIndex - Index to store the texture at
|
|
734
|
+
* @param {string} [src] - Image source path
|
|
735
|
+
* @return {Promise} Promise that resolves when texture is loaded
|
|
736
|
+
* @memberof Draw */
|
|
737
|
+
async function loadTexture(textureIndex, src)
|
|
738
|
+
{
|
|
739
|
+
ASSERT(isNumber(textureIndex), 'textureIndex must be a number');
|
|
740
|
+
ASSERT(!textureInfos[textureIndex], 'textureIndex is already loaded!');
|
|
741
|
+
ASSERT(!src || isString(src), 'image src must be a string');
|
|
742
|
+
|
|
743
|
+
const image = new Image;
|
|
744
|
+
if (src)
|
|
745
|
+
{
|
|
746
|
+
await new Promise(resolve =>
|
|
747
|
+
{
|
|
748
|
+
image.onerror = image.onload = resolve;
|
|
749
|
+
image.crossOrigin = 'anonymous';
|
|
750
|
+
image.src = src;
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
textureInfos[textureIndex] = new TextureInfo(image);
|
|
755
|
+
}
|
|
756
|
+
|
|
732
757
|
/** Convert from screen to world space coordinates
|
|
733
758
|
* @param {Vector2} screenPos
|
|
734
759
|
* @return {Vector2}
|
|
@@ -1109,21 +1134,18 @@ class FontImage
|
|
|
1109
1134
|
}
|
|
1110
1135
|
|
|
1111
1136
|
// load engine font, called automatically on startup
|
|
1112
|
-
function fontImageInit()
|
|
1137
|
+
async function fontImageInit()
|
|
1113
1138
|
{
|
|
1114
|
-
|
|
1139
|
+
const image = new Image;
|
|
1140
|
+
await new Promise(resolve =>
|
|
1115
1141
|
{
|
|
1116
|
-
|
|
1117
|
-
const image = new Image;
|
|
1118
|
-
image.onerror = image.onload = ()=>
|
|
1119
|
-
{
|
|
1120
|
-
const tilePos=vec2(), tileSize=vec2(8), padding=1, bleed=0;
|
|
1121
|
-
const textureInfo = new TextureInfo(image);
|
|
1122
|
-
const tileInfo = new TileInfo(tilePos, tileSize, textureInfo, padding, bleed);
|
|
1123
|
-
engineFontImage = new FontImage(tileInfo);
|
|
1124
|
-
resolve();
|
|
1125
|
-
}
|
|
1142
|
+
image.onerror = image.onload = resolve;
|
|
1126
1143
|
image.crossOrigin = 'anonymous';
|
|
1127
1144
|
image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAAeAQMAAABnrVXaAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAAjpJREFUOMu9kzFu2zAUhn+CAROgqrk+B2l0BWYxMjlXeYaAtFtbdA1sGgHqRQfI0CNkSG5AwYB0BQ8d5Bsomwah6CPVeGg6tEPzAxLwyI+P78cP4u9lNO9OoMKnLMOobG5020/yaj/MrRcCGh1gBbyiLTPJEYaIiom5KM9Jq7KgynMGtb6L4GL4MF2H4LQKCXTvDVw2I4MsgZT7QLExdiutH+D08VOP3INXRrWX1/mmpbkNgAPYRVANb4xpcegYvhiNbIXauQICEjBuYLfMakaakWQeXxiZ0VDtuJCKs3ztMV59QtsHJNcRxDzfdL21ty3PrfIcXTN+E+GFAv6T5nbT9jd50/WFxb5ksdAv49qS6ouymG66ji08UMT6moykYLAo+V0j23GN4m829ZySAD5K7QsBfQTvOG8eE+gTeGYRAmnNAubN3hf5Zv9tJWDHp/VTuaSm7SN4fyINQqaNO3RMVxvpSPXnOChnRNvFcGY0gnwiPswYwTKVPE0zVtX3mTEIOoFzaqLrGuJaV+Uqumb71fVk/VoOH3cdLNQP/FHi8hV0CQNoqBZsUPlLPMsdCJro9QAaQQ0woDy9BJm0eTxCFnO9srcYlhNVlfR2EyTrph1uUtbUtAJifwRgrKuYdXVHeb0YI3QpawohQHkloI3J5FuVwI5ORxC9k2Tuz9Ir1IjgeIPGMHYkAZe2RuYkmWFmt3gGbTPOmBUWVTmRmHtGrfpzG/yuQNOKa6gBB/WA9khitPgl6/GP+gl2Af6tCbvaygAAAABJRU5ErkJggg==';
|
|
1128
1145
|
});
|
|
1146
|
+
|
|
1147
|
+
const tilePos=vec2(), tileSize=vec2(8), padding=1, bleed=0;
|
|
1148
|
+
const textureInfo = new TextureInfo(image);
|
|
1149
|
+
const tileInfo = new TileInfo(tilePos, tileSize, textureInfo, padding, bleed);
|
|
1150
|
+
engineFontImage = new FontImage(tileInfo);
|
|
1129
1151
|
}
|
package/src/engineMath.js
CHANGED
|
@@ -267,7 +267,9 @@ function wave(frequency=1, amplitude=1, t=time, offset=0)
|
|
|
267
267
|
function isNumber(n) { return typeof n === 'number' && !isNaN(n); }
|
|
268
268
|
|
|
269
269
|
/**
|
|
270
|
-
* Check if object
|
|
270
|
+
* Check if object can be converted to a string (has a toString method)
|
|
271
|
+
* - Returns true for strings, numbers, and most objects
|
|
272
|
+
* - Returns false for null and undefined
|
|
271
273
|
* @param {any} s
|
|
272
274
|
* @return {boolean}
|
|
273
275
|
* @memberof Math */
|
|
@@ -344,7 +346,7 @@ function lineTest(posStart, posEnd, testFunction, normal)
|
|
|
344
346
|
if (stepX < 0)
|
|
345
347
|
hitPos.x -= e;
|
|
346
348
|
}
|
|
347
|
-
if (stepY < 0)
|
|
349
|
+
else if (stepY < 0)
|
|
348
350
|
hitPos.y -= e;
|
|
349
351
|
|
|
350
352
|
// set normal
|
|
@@ -1051,7 +1053,7 @@ class Color
|
|
|
1051
1053
|
* @memberof Math */
|
|
1052
1054
|
const WHITE = debugProtectConstant(rgb());
|
|
1053
1055
|
|
|
1054
|
-
/** Color - Clear White #
|
|
1056
|
+
/** Color - Clear White #ffffff00 with 0 alpha
|
|
1055
1057
|
* @type {Color}
|
|
1056
1058
|
* @memberof Math */
|
|
1057
1059
|
const CLEAR_WHITE = debugProtectConstant(rgb(1,1,1,0));
|
|
@@ -1061,7 +1063,7 @@ const CLEAR_WHITE = debugProtectConstant(rgb(1,1,1,0));
|
|
|
1061
1063
|
* @memberof Math */
|
|
1062
1064
|
const BLACK = debugProtectConstant(rgb(0,0,0));
|
|
1063
1065
|
|
|
1064
|
-
/** Color - Clear Black #
|
|
1066
|
+
/** Color - Clear Black #00000000 with 0 alpha
|
|
1065
1067
|
* @type {Color}
|
|
1066
1068
|
* @memberof Math */
|
|
1067
1069
|
const CLEAR_BLACK = debugProtectConstant(rgb(0,0,0,0));
|
package/src/engineTileLayer.js
CHANGED
|
@@ -643,7 +643,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
643
643
|
collisionTest(pos, size=new Vector2, callbackObject)
|
|
644
644
|
{
|
|
645
645
|
ASSERT(isVector2(pos) && isVector2(size), 'pos and size must be Vector2s');
|
|
646
|
-
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a
|
|
646
|
+
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a function or EngineObject');
|
|
647
647
|
|
|
648
648
|
// make function to check for collision
|
|
649
649
|
const collisionTest = callbackObject ? typeof callbackObject === 'function' ?
|
|
@@ -680,7 +680,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
680
680
|
collisionRaycast(posStart, posEnd, callbackObject, normal)
|
|
681
681
|
{
|
|
682
682
|
ASSERT(isVector2(posStart) && isVector2(posEnd), 'positions must be Vector2s');
|
|
683
|
-
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a
|
|
683
|
+
ASSERT(!callbackObject || typeof callbackObject === 'function' || callbackObject instanceof EngineObject, 'callbackObject must be a function or EngineObject');
|
|
684
684
|
|
|
685
685
|
// make function to check for collision
|
|
686
686
|
const collisionTest = callbackObject ? typeof callbackObject === 'function' ?
|