littlejsengine 1.9.3 → 1.9.5
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/LittleJS.zip +0 -0
- package/dist/littlejs.d.ts +24 -21
- package/dist/littlejs.esm.js +179 -91
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +179 -91
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +174 -90
- package/examples/module/game.js +1 -1
- package/examples/platformer/gameCharacter.js +1 -2
- package/examples/platformer/gameEffects.js +2 -3
- package/examples/platformer/gameLevel.js +0 -1
- package/examples/typescript/game.js +1 -1
- package/examples/typescript/game.ts +1 -1
- package/package.json +1 -1
- package/reference.md +11 -11
- package/src/engine.js +67 -34
- package/src/engineAudio.js +1 -1
- package/src/engineBuild.js +4 -4
- package/src/engineDebug.js +5 -1
- package/src/engineDraw.js +11 -16
- package/src/engineInput.js +30 -16
- package/src/engineObject.js +9 -11
- package/src/engineTileLayer.js +6 -3
- package/src/engineUtilities.js +50 -9
package/dist/littlejs.js
CHANGED
|
@@ -264,6 +264,10 @@ function debugRender()
|
|
|
264
264
|
{
|
|
265
265
|
const saveContext = mainContext;
|
|
266
266
|
mainContext = overlayContext;
|
|
267
|
+
|
|
268
|
+
// draw red rectangle around screen
|
|
269
|
+
const cameraSize = getCameraSize();
|
|
270
|
+
debugRect(cameraPos, cameraSize.subtract(vec2(.1)), '#f008');
|
|
267
271
|
|
|
268
272
|
// mouse pick
|
|
269
273
|
let bestDistance = Infinity, bestObject;
|
|
@@ -353,7 +357,7 @@ function debugRender()
|
|
|
353
357
|
overlayContext.restore();
|
|
354
358
|
});
|
|
355
359
|
|
|
356
|
-
// remove expired
|
|
360
|
+
// remove expired primitives
|
|
357
361
|
debugPrimitives = debugPrimitives.filter(r=>r.time<0);
|
|
358
362
|
}
|
|
359
363
|
|
|
@@ -538,16 +542,57 @@ function smoothStep(percent) { return percent * percent * (3 - 2 * percent); }
|
|
|
538
542
|
function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
|
|
539
543
|
|
|
540
544
|
/** Returns true if two axis aligned bounding boxes are overlapping
|
|
541
|
-
* @param {Vector2}
|
|
542
|
-
* @param {Vector2} sizeA
|
|
543
|
-
* @param {Vector2}
|
|
544
|
-
* @param {Vector2} [sizeB=(0,0)]
|
|
545
|
-
* @return {Boolean}
|
|
545
|
+
* @param {Vector2} posA - Center of box A
|
|
546
|
+
* @param {Vector2} sizeA - Size of box A
|
|
547
|
+
* @param {Vector2} posB - Center of box B
|
|
548
|
+
* @param {Vector2} [sizeB=(0,0)] - Size of box B, a point if undefined
|
|
549
|
+
* @return {Boolean} - True if overlapping
|
|
546
550
|
* @memberof Utilities */
|
|
547
|
-
function isOverlapping(
|
|
551
|
+
function isOverlapping(posA, sizeA, posB, sizeB=vec2())
|
|
548
552
|
{
|
|
549
|
-
return abs(
|
|
550
|
-
&& abs(
|
|
553
|
+
return abs(posA.x - posB.x)*2 < sizeA.x + sizeB.x
|
|
554
|
+
&& abs(posA.y - posB.y)*2 < sizeA.y + sizeB.y;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** Returns true if a line segment is intersecting an axis aligned box
|
|
558
|
+
* @param {Vector2} start - Start of raycast
|
|
559
|
+
* @param {Vector2} end - End of raycast
|
|
560
|
+
* @param {Vector2} pos - Center of box
|
|
561
|
+
* @param {Vector2} size - Size of box
|
|
562
|
+
* @return {Boolean} - True if intersecting
|
|
563
|
+
* @memberof Utilities */
|
|
564
|
+
function isIntersecting(start, end, pos, size)
|
|
565
|
+
{
|
|
566
|
+
// Liang-Barsky algorithm
|
|
567
|
+
const boxMin = pos.subtract(size.scale(.5));
|
|
568
|
+
const boxMax = boxMin.add(size);
|
|
569
|
+
const delta = end.subtract(start);
|
|
570
|
+
const a = start.subtract(boxMin);
|
|
571
|
+
const b = start.subtract(boxMax);
|
|
572
|
+
const p = [-delta.x, delta.x, -delta.y, delta.y];
|
|
573
|
+
const q = [a.x, -b.x, a.y, -b.y];
|
|
574
|
+
let tMin = 0, tMax = 1;
|
|
575
|
+
for (let i = 4; i--;)
|
|
576
|
+
{
|
|
577
|
+
if (p[i])
|
|
578
|
+
{
|
|
579
|
+
const t = q[i] / p[i];
|
|
580
|
+
if (p[i] < 0)
|
|
581
|
+
{
|
|
582
|
+
if (t > tMax) return false;
|
|
583
|
+
tMin = max(t, tMin);
|
|
584
|
+
}
|
|
585
|
+
else
|
|
586
|
+
{
|
|
587
|
+
if (t < tMin) return false;
|
|
588
|
+
tMax = min(t, tMax);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
else if (q[i] < 0)
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return true;
|
|
551
596
|
}
|
|
552
597
|
|
|
553
598
|
/** Returns an oscillating wave between 0 and amplitude with frequency of 1 Hz by default
|
|
@@ -1047,7 +1092,7 @@ class Color
|
|
|
1047
1092
|
|
|
1048
1093
|
/** Returns this color expressed in hsla format
|
|
1049
1094
|
* @return {Array} */
|
|
1050
|
-
|
|
1095
|
+
HSLA()
|
|
1051
1096
|
{
|
|
1052
1097
|
const r = clamp(this.r);
|
|
1053
1098
|
const g = clamp(this.g);
|
|
@@ -1731,6 +1776,8 @@ class EngineObject
|
|
|
1731
1776
|
this.collideSolidObjects = false;
|
|
1732
1777
|
/** @property {Boolean} - Object collides with and blocks other objects */
|
|
1733
1778
|
this.isSolid = false;
|
|
1779
|
+
/** @property {Boolean} - Object collides with raycasts */
|
|
1780
|
+
this.collideRaycast = false;
|
|
1734
1781
|
|
|
1735
1782
|
// add to list of objects
|
|
1736
1783
|
engineObjects.push(this);
|
|
@@ -1935,13 +1982,7 @@ class EngineObject
|
|
|
1935
1982
|
* @param {Number} tileData - the value of the tile at the position
|
|
1936
1983
|
* @param {Vector2} pos - tile where the collision occured
|
|
1937
1984
|
* @return {Boolean} - true if the collision should be resolved */
|
|
1938
|
-
collideWithTile(tileData, pos)
|
|
1939
|
-
|
|
1940
|
-
/** Called to check if a tile raycast hit
|
|
1941
|
-
* @param {Number} tileData - the value of the tile at the position
|
|
1942
|
-
* @param {Vector2} pos - tile where the raycast is
|
|
1943
|
-
* @return {Boolean} - true if the raycast should hit */
|
|
1944
|
-
collideWithTileRaycast(tileData, pos) { return tileData > 0; }
|
|
1985
|
+
collideWithTile(tileData, pos) { return tileData > 0; }
|
|
1945
1986
|
|
|
1946
1987
|
/** Called to check if a object collision should be resolved
|
|
1947
1988
|
* @param {EngineObject} object - the object to test against
|
|
@@ -1988,16 +2029,18 @@ class EngineObject
|
|
|
1988
2029
|
}
|
|
1989
2030
|
|
|
1990
2031
|
/** Set how this object collides
|
|
1991
|
-
* @param {Boolean} [collideSolidObjects] - Does it collide with solid objects
|
|
1992
|
-
* @param {Boolean} [isSolid] - Does it collide with and block other objects (expensive in large numbers)
|
|
1993
|
-
* @param {Boolean} [collideTiles] - Does it collide with the tile collision
|
|
1994
|
-
|
|
2032
|
+
* @param {Boolean} [collideSolidObjects] - Does it collide with solid objects?
|
|
2033
|
+
* @param {Boolean} [isSolid] - Does it collide with and block other objects? (expensive in large numbers)
|
|
2034
|
+
* @param {Boolean} [collideTiles] - Does it collide with the tile collision?
|
|
2035
|
+
* @param {Boolean} [collideRaycast] - Does it collide with raycasts? */
|
|
2036
|
+
setCollision(collideSolidObjects=true, isSolid=true, collideTiles=true, collideRaycast=true)
|
|
1995
2037
|
{
|
|
1996
2038
|
ASSERT(collideSolidObjects || !isSolid, 'solid objects must be set to collide');
|
|
1997
2039
|
|
|
1998
2040
|
this.collideSolidObjects = collideSolidObjects;
|
|
1999
2041
|
this.isSolid = isSolid;
|
|
2000
2042
|
this.collideTiles = collideTiles;
|
|
2043
|
+
this.collideRaycast = collideRaycast;
|
|
2001
2044
|
}
|
|
2002
2045
|
|
|
2003
2046
|
/** Returns string containg info about this object for debugging
|
|
@@ -2137,13 +2180,23 @@ class TileInfo
|
|
|
2137
2180
|
this.textureIndex = textureIndex;
|
|
2138
2181
|
}
|
|
2139
2182
|
|
|
2140
|
-
/** Returns
|
|
2183
|
+
/** Returns a copy of this tile offset by a vector
|
|
2141
2184
|
* @param {Vector2} offset - Offset to apply in pixels
|
|
2142
2185
|
* @return {TileInfo}
|
|
2143
2186
|
*/
|
|
2144
2187
|
offset(offset)
|
|
2145
2188
|
{ return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
|
|
2146
2189
|
|
|
2190
|
+
/** Returns a copy of this tile offset by a number of animation frames
|
|
2191
|
+
* @param {Number} frame - Offset to apply in animation frames
|
|
2192
|
+
* @return {TileInfo}
|
|
2193
|
+
*/
|
|
2194
|
+
frame(frame)
|
|
2195
|
+
{
|
|
2196
|
+
ASSERT(typeof frame == 'number');
|
|
2197
|
+
return this.offset(vec2(frame*this.size.x, 0));
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2147
2200
|
/** Returns the texture info for this tile
|
|
2148
2201
|
* @return {TextureInfo}
|
|
2149
2202
|
*/
|
|
@@ -2294,21 +2347,6 @@ function drawRect(pos, size, color, angle, useWebGL, screenSpace, context)
|
|
|
2294
2347
|
drawTile(pos, size, undefined, color, angle, false, undefined, useWebGL, screenSpace, context);
|
|
2295
2348
|
}
|
|
2296
2349
|
|
|
2297
|
-
/** Draw colored polygon using passed in points
|
|
2298
|
-
* @param {Array} points - Array of Vector2 points
|
|
2299
|
-
* @param {Color} [color=(1,1,1,1)]
|
|
2300
|
-
* @param {Boolean} [screenSpace=false]
|
|
2301
|
-
* @param {CanvasRenderingContext2D} [context=mainContext]
|
|
2302
|
-
* @memberof Draw */
|
|
2303
|
-
function drawPoly(points, color=new Color, screenSpace, context=mainContext)
|
|
2304
|
-
{
|
|
2305
|
-
context.fillStyle = color.toString();
|
|
2306
|
-
context.beginPath();
|
|
2307
|
-
for (const point of screenSpace ? points : points.map(worldToScreen))
|
|
2308
|
-
context.lineTo(point.x, point.y);
|
|
2309
|
-
context.fill();
|
|
2310
|
-
}
|
|
2311
|
-
|
|
2312
2350
|
/** Draw colored line between two points
|
|
2313
2351
|
* @param {Vector2} posA
|
|
2314
2352
|
* @param {Vector2} posB
|
|
@@ -2735,9 +2773,21 @@ function mouseToScreen(mousePos)
|
|
|
2735
2773
|
///////////////////////////////////////////////////////////////////////////////
|
|
2736
2774
|
// Gamepad input
|
|
2737
2775
|
|
|
2776
|
+
// gamepad internal variables
|
|
2738
2777
|
const stickData = [];
|
|
2778
|
+
|
|
2779
|
+
// gamepads are updated by engine every frame automatically
|
|
2739
2780
|
function gamepadsUpdate()
|
|
2740
2781
|
{
|
|
2782
|
+
const applyDeadZones = (v)=>
|
|
2783
|
+
{
|
|
2784
|
+
const min=.3, max=.8;
|
|
2785
|
+
const deadZone = (v)=>
|
|
2786
|
+
v > min ? percent( v, min, max) :
|
|
2787
|
+
v < -min ? -percent(-v, min, max) : 0;
|
|
2788
|
+
return vec2(deadZone(v.x), deadZone(-v.y)).clampLength();
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2741
2791
|
// update touch gamepad if enabled
|
|
2742
2792
|
if (touchGamepadEnable && isTouchDevice)
|
|
2743
2793
|
{
|
|
@@ -2749,7 +2799,16 @@ function gamepadsUpdate()
|
|
|
2749
2799
|
{
|
|
2750
2800
|
// read virtual analog stick
|
|
2751
2801
|
const sticks = stickData[0] || (stickData[0] = []);
|
|
2752
|
-
sticks[0] = vec2(
|
|
2802
|
+
sticks[0] = vec2();
|
|
2803
|
+
if (touchGamepadAnalog)
|
|
2804
|
+
sticks[0] = applyDeadZones(touchGamepadStick);
|
|
2805
|
+
else if (touchGamepadStick.lengthSquared() > .3)
|
|
2806
|
+
{
|
|
2807
|
+
// convert to 8 way dpad
|
|
2808
|
+
sticks[0].x = Math.round(touchGamepadStick.x);
|
|
2809
|
+
sticks[0].y = -Math.round(touchGamepadStick.y);
|
|
2810
|
+
sticks[0] = sticks[0].clampLength();
|
|
2811
|
+
}
|
|
2753
2812
|
|
|
2754
2813
|
// read virtual gamepad buttons
|
|
2755
2814
|
const data = inputData[1] || (inputData[1] = []);
|
|
@@ -2761,7 +2820,12 @@ function gamepadsUpdate()
|
|
|
2761
2820
|
}
|
|
2762
2821
|
}
|
|
2763
2822
|
|
|
2764
|
-
|
|
2823
|
+
// return if gamepads are disabled or not supported
|
|
2824
|
+
if (!gamepadsEnable || !navigator || !navigator.getGamepads)
|
|
2825
|
+
return;
|
|
2826
|
+
|
|
2827
|
+
// only poll gamepads when focused or in debug mode
|
|
2828
|
+
if (!debug && !document.hasFocus())
|
|
2765
2829
|
return;
|
|
2766
2830
|
|
|
2767
2831
|
// poll gamepads
|
|
@@ -2775,14 +2839,9 @@ function gamepadsUpdate()
|
|
|
2775
2839
|
|
|
2776
2840
|
if (gamepad)
|
|
2777
2841
|
{
|
|
2778
|
-
// read clamp dead zone of analog sticks
|
|
2779
|
-
const deadZone = .3, deadZoneMax = .8, applyDeadZone = (v)=>
|
|
2780
|
-
v > deadZone ? percent( v, deadZone, deadZoneMax) :
|
|
2781
|
-
v < -deadZone ? -percent(-v, deadZone, deadZoneMax) : 0;
|
|
2782
|
-
|
|
2783
2842
|
// read analog sticks
|
|
2784
2843
|
for (let j = 0; j < gamepad.axes.length-1; j+=2)
|
|
2785
|
-
sticks[j>>1] = vec2(
|
|
2844
|
+
sticks[j>>1] = applyDeadZones(vec2(gamepad.axes[j],gamepad.axes[j+1]));
|
|
2786
2845
|
|
|
2787
2846
|
// read buttons
|
|
2788
2847
|
for (let j = gamepad.buttons.length; j--;)
|
|
@@ -2911,14 +2970,7 @@ function createTouchGamepad()
|
|
|
2911
2970
|
if (touchPos.distance(stickCenter) < touchGamepadSize)
|
|
2912
2971
|
{
|
|
2913
2972
|
// virtual analog stick
|
|
2914
|
-
|
|
2915
|
-
touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
|
|
2916
|
-
else
|
|
2917
|
-
{
|
|
2918
|
-
// 8 way dpad
|
|
2919
|
-
const angle = touchPos.subtract(stickCenter).angle();
|
|
2920
|
-
touchGamepadStick.setAngle((angle * 4 / PI + 8.5 | 0) * PI / 4);
|
|
2921
|
-
}
|
|
2973
|
+
touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
|
|
2922
2974
|
}
|
|
2923
2975
|
else if (touchPos.distance(buttonCenter) < touchGamepadSize)
|
|
2924
2976
|
{
|
|
@@ -3177,7 +3229,7 @@ class SoundWave extends Sound
|
|
|
3177
3229
|
* 1, 0, 9, 1 // channel notes
|
|
3178
3230
|
* ],
|
|
3179
3231
|
* [ // channel 1
|
|
3180
|
-
* 0, 1, // instrument
|
|
3232
|
+
* 0, 1, // instrument 0, right speaker
|
|
3181
3233
|
* 0, 12, 17, -1 // channel notes
|
|
3182
3234
|
* ]
|
|
3183
3235
|
* ],
|
|
@@ -3641,7 +3693,7 @@ function tileCollisionTest(pos, size=vec2(), object)
|
|
|
3641
3693
|
}
|
|
3642
3694
|
}
|
|
3643
3695
|
|
|
3644
|
-
/** Return the center of tile
|
|
3696
|
+
/** Return the center of first tile hit (does not return the exact intersection)
|
|
3645
3697
|
* @param {Vector2} posStart
|
|
3646
3698
|
* @param {Vector2} posEnd
|
|
3647
3699
|
* @param {EngineObject} [object]
|
|
@@ -3837,8 +3889,11 @@ class TileLayer extends EngineObject
|
|
|
3837
3889
|
mainCanvas.height = mainCanvasSize.y;
|
|
3838
3890
|
}
|
|
3839
3891
|
|
|
3840
|
-
//
|
|
3841
|
-
|
|
3892
|
+
// disable smoothing for pixel art
|
|
3893
|
+
this.context.imageSmoothingEnabled = !canvasPixelated;
|
|
3894
|
+
|
|
3895
|
+
// setup gl rendering if enabled
|
|
3896
|
+
glEnable && glPreRender();
|
|
3842
3897
|
}
|
|
3843
3898
|
|
|
3844
3899
|
/** Call to end the redraw process */
|
|
@@ -4987,7 +5042,7 @@ const engineName = 'LittleJS';
|
|
|
4987
5042
|
* @type {String}
|
|
4988
5043
|
* @default
|
|
4989
5044
|
* @memberof Engine */
|
|
4990
|
-
const engineVersion = '1.9.
|
|
5045
|
+
const engineVersion = '1.9.5';
|
|
4991
5046
|
|
|
4992
5047
|
/** Frames per second to update
|
|
4993
5048
|
* @type {Number}
|
|
@@ -5054,6 +5109,19 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5054
5109
|
{
|
|
5055
5110
|
ASSERT(Array.isArray(imageSources), 'pass in images as array');
|
|
5056
5111
|
|
|
5112
|
+
// Called automatically by engine to setup render system
|
|
5113
|
+
function enginePreRender()
|
|
5114
|
+
{
|
|
5115
|
+
// save canvas size
|
|
5116
|
+
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
5117
|
+
|
|
5118
|
+
// disable smoothing for pixel art
|
|
5119
|
+
mainContext.imageSmoothingEnabled = !canvasPixelated;
|
|
5120
|
+
|
|
5121
|
+
// setup gl rendering if enabled
|
|
5122
|
+
glEnable && glPreRender();
|
|
5123
|
+
}
|
|
5124
|
+
|
|
5057
5125
|
// internal update loop for engine
|
|
5058
5126
|
function engineUpdate(frameTimeMS=0)
|
|
5059
5127
|
{
|
|
@@ -5069,7 +5137,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5069
5137
|
timeReal += frameTimeDeltaMS / 1e3;
|
|
5070
5138
|
frameTimeBufferMS += paused ? 0 : frameTimeDeltaMS;
|
|
5071
5139
|
if (!debugSpeedUp)
|
|
5072
|
-
frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp
|
|
5140
|
+
frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp in case of slow framerate
|
|
5073
5141
|
updateCanvas();
|
|
5074
5142
|
|
|
5075
5143
|
if (paused)
|
|
@@ -5211,7 +5279,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5211
5279
|
}
|
|
5212
5280
|
image.src = src;
|
|
5213
5281
|
})
|
|
5214
|
-
)
|
|
5282
|
+
);
|
|
5215
5283
|
|
|
5216
5284
|
// draw splash screen
|
|
5217
5285
|
showSplashScreen && promises.push(new Promise(resolve =>
|
|
@@ -5236,19 +5304,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
|
|
|
5236
5304
|
});
|
|
5237
5305
|
}
|
|
5238
5306
|
|
|
5239
|
-
// Called automatically by engine to setup render system
|
|
5240
|
-
function enginePreRender()
|
|
5241
|
-
{
|
|
5242
|
-
// save canvas size
|
|
5243
|
-
mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
|
|
5244
|
-
|
|
5245
|
-
// disable smoothing for pixel art
|
|
5246
|
-
mainContext.imageSmoothingEnabled = !canvasPixelated;
|
|
5247
|
-
|
|
5248
|
-
// setup gl rendering if enabled
|
|
5249
|
-
glEnable && glPreRender();
|
|
5250
|
-
}
|
|
5251
|
-
|
|
5252
5307
|
/** Update each engine object, remove destroyed objects, and update time
|
|
5253
5308
|
* @memberof Engine */
|
|
5254
5309
|
function engineObjectsUpdate()
|
|
@@ -5282,30 +5337,63 @@ function engineObjectsDestroy()
|
|
|
5282
5337
|
engineObjects = engineObjects.filter(o=>!o.destroyed);
|
|
5283
5338
|
}
|
|
5284
5339
|
|
|
5285
|
-
/**
|
|
5286
|
-
* @param {Vector2} [pos] - Center of test area
|
|
5340
|
+
/** Collects all object within a given area
|
|
5341
|
+
* @param {Vector2} [pos] - Center of test area, or undefined for all objects
|
|
5287
5342
|
* @param {Number|Vector2} [size] - Radius of circle if float, rectangle size if Vector2
|
|
5288
|
-
* @param {Function} [callbackFunction] - Calls this function on every object that passes the test
|
|
5289
5343
|
* @param {Array} [objects=engineObjects] - List of objects to check
|
|
5344
|
+
* @return {Array} - List of collected objects
|
|
5290
5345
|
* @memberof Engine */
|
|
5291
|
-
function
|
|
5346
|
+
function engineObjectsCollect(pos, size, objects=engineObjects)
|
|
5292
5347
|
{
|
|
5348
|
+
const collectedObjects = [];
|
|
5293
5349
|
if (!pos) // all objects
|
|
5294
5350
|
{
|
|
5295
5351
|
for (const o of objects)
|
|
5296
|
-
|
|
5352
|
+
collectedObjects.push(o);
|
|
5297
5353
|
}
|
|
5298
|
-
else if (
|
|
5354
|
+
else if (size instanceof Vector2) // bounding box test
|
|
5299
5355
|
{
|
|
5300
5356
|
for (const o of objects)
|
|
5301
|
-
isOverlapping(pos, size, o.pos, o.size) &&
|
|
5357
|
+
isOverlapping(pos, size, o.pos, o.size) && collectedObjects.push(o);
|
|
5302
5358
|
}
|
|
5303
5359
|
else // circle test
|
|
5304
5360
|
{
|
|
5305
5361
|
const sizeSquared = size*size;
|
|
5306
5362
|
for (const o of objects)
|
|
5307
|
-
pos.distanceSquared(o.pos) < sizeSquared &&
|
|
5363
|
+
pos.distanceSquared(o.pos) < sizeSquared && collectedObjects.push(o);
|
|
5308
5364
|
}
|
|
5365
|
+
return collectedObjects;
|
|
5366
|
+
}
|
|
5367
|
+
|
|
5368
|
+
/** Triggers a callback for each object within a given area
|
|
5369
|
+
* @param {Vector2} [pos] - Center of test area, or undefined for all objects
|
|
5370
|
+
* @param {Number|Vector2} [size] - Radius of circle if float, rectangle size if Vector2
|
|
5371
|
+
* @param {Function} [callbackFunction] - Calls this function on every object that passes the test
|
|
5372
|
+
* @param {Array} [objects=engineObjects] - List of objects to check
|
|
5373
|
+
* @memberof Engine */
|
|
5374
|
+
function engineObjectsCallback(pos, size, callbackFunction, objects=engineObjects)
|
|
5375
|
+
{ engineObjectsCollect(pos, size, objects).forEach(o => callbackFunction(o)); }
|
|
5376
|
+
|
|
5377
|
+
/** Return a list of objects intersecting a ray
|
|
5378
|
+
* @param {Vector2} start
|
|
5379
|
+
* @param {Vector2} end
|
|
5380
|
+
* @param {Array} [objects=engineObjects] - List of objects to check
|
|
5381
|
+
* @return {Array} - List of objects hit
|
|
5382
|
+
* @memberof Engine */
|
|
5383
|
+
function engineObjectsRaycast(start, end, objects=engineObjects)
|
|
5384
|
+
{
|
|
5385
|
+
const hitObjects = [];
|
|
5386
|
+
for (const o of objects)
|
|
5387
|
+
{
|
|
5388
|
+
if (o.collideRaycast && isIntersecting(start, end, o.pos, o.size))
|
|
5389
|
+
{
|
|
5390
|
+
debugRaycast && debugRect(o.pos, o.size, '#f00');
|
|
5391
|
+
hitObjects.push(o);
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
|
|
5395
|
+
debugRaycast && debugLine(start, end, hitObjects.length ? '#f00' : '#00f', .02);
|
|
5396
|
+
return hitObjects;
|
|
5309
5397
|
}
|
|
5310
5398
|
|
|
5311
5399
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -5393,16 +5481,16 @@ function drawEngineSplashScreen(t)
|
|
|
5393
5481
|
rect(37,14,9,6);
|
|
5394
5482
|
|
|
5395
5483
|
// big stack
|
|
5396
|
-
rect(50,20,10,-
|
|
5397
|
-
rect(50,20,6.5,-
|
|
5398
|
-
rect(50,20,3.5,-
|
|
5399
|
-
rect(50,20,10,-
|
|
5400
|
-
circle(55,2,11.4,.5,PI-.5,color(3,3))
|
|
5401
|
-
circle(55,2,11.4,.5,PI/2,color(3,2),1)
|
|
5402
|
-
circle(55,2,11.4,.5,PI-.5)
|
|
5403
|
-
rect(45,7,20,-7,color(0,2))
|
|
5404
|
-
rect(45,
|
|
5405
|
-
rect(45,
|
|
5484
|
+
rect(50,20,10,-8,color(0,1))
|
|
5485
|
+
rect(50,20,6.5,-8,color(0,2))
|
|
5486
|
+
rect(50,20,3.5,-8,color(0,3))
|
|
5487
|
+
rect(50,20,10,-8)
|
|
5488
|
+
circle(55,2,11.4,.5,PI-.5,color(3,3))
|
|
5489
|
+
circle(55,2,11.4,.5,PI/2,color(3,2),1)
|
|
5490
|
+
circle(55,2,11.4,.5,PI-.5)
|
|
5491
|
+
rect(45,7,20,-7,color(0,2))
|
|
5492
|
+
rect(45,-1,20,4,color(0,3))
|
|
5493
|
+
rect(45,-1,20,8)
|
|
5406
5494
|
|
|
5407
5495
|
// engine
|
|
5408
5496
|
for (let i=5; i--;)
|