q5play 4.1.2 → 4.2.0
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/package.json +1 -1
- package/py.typed +0 -0
- package/q5play.d.ts +1369 -144
- package/q5play.js +466 -125
- package/q5play.pyi +5007 -0
package/q5play.js
CHANGED
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
* |__/ |__/ \______/
|
|
13
13
|
*
|
|
14
14
|
* @package q5play
|
|
15
|
-
* @version 4.
|
|
15
|
+
* @version 4.2
|
|
16
16
|
* @author quinton-ashley
|
|
17
17
|
* @website https://q5play.org
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
let q5play_version = '4.
|
|
20
|
+
let q5play_version = '4.2';
|
|
21
21
|
|
|
22
22
|
if (typeof globalThis.Q5 == 'undefined') {
|
|
23
23
|
console.error('q5play requires q5.js to be loaded first. Visit https://q5js.org to learn more.');
|
|
@@ -396,7 +396,9 @@ async function q5playPreSetup(q) {
|
|
|
396
396
|
const scaleFrom = (x, y) => ({ x: x * meterSize, y: y * meterSize });
|
|
397
397
|
|
|
398
398
|
const linearSlop = 0.005,
|
|
399
|
-
angularSlop = 0.
|
|
399
|
+
angularSlop = 0.0333;
|
|
400
|
+
|
|
401
|
+
let visualSlop = 0.5;
|
|
400
402
|
|
|
401
403
|
const isSlop = (val) => Math.abs(val) <= linearSlop;
|
|
402
404
|
const fixRound = (val) => {
|
|
@@ -1199,10 +1201,10 @@ async function q5playPreSetup(q) {
|
|
|
1199
1201
|
else this.addCollider(...args);
|
|
1200
1202
|
}
|
|
1201
1203
|
|
|
1202
|
-
this.
|
|
1204
|
+
this.prevX = x;
|
|
1205
|
+
this.prevY = y;
|
|
1203
1206
|
this.prevRotation = 0;
|
|
1204
|
-
|
|
1205
|
-
this._destIdx = 0;
|
|
1207
|
+
|
|
1206
1208
|
this._debug = false;
|
|
1207
1209
|
|
|
1208
1210
|
if (!group._isAllSpritesGroup) $.allSprites.push(this);
|
|
@@ -1891,7 +1893,7 @@ async function q5playPreSetup(q) {
|
|
|
1891
1893
|
}
|
|
1892
1894
|
const speed = this._vel.mag();
|
|
1893
1895
|
if (speed) {
|
|
1894
|
-
this.
|
|
1896
|
+
this.__setVel($.cos(val) * speed, $.sin(val) * speed);
|
|
1895
1897
|
this._vel._magCached = false;
|
|
1896
1898
|
}
|
|
1897
1899
|
this._vel._direction = val;
|
|
@@ -1999,19 +2001,17 @@ async function q5playPreSetup(q) {
|
|
|
1999
2001
|
this._opacity = val;
|
|
2000
2002
|
}
|
|
2001
2003
|
|
|
2002
|
-
get
|
|
2003
|
-
return this.
|
|
2004
|
+
get previousX() {
|
|
2005
|
+
return this.prevX;
|
|
2004
2006
|
}
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
+
|
|
2008
|
+
get previousY() {
|
|
2009
|
+
return this.prevY;
|
|
2007
2010
|
}
|
|
2008
2011
|
|
|
2009
2012
|
get previousRotation() {
|
|
2010
2013
|
return this.prevRotation;
|
|
2011
2014
|
}
|
|
2012
|
-
set previousRotation(val) {
|
|
2013
|
-
this.prevRotation = val;
|
|
2014
|
-
}
|
|
2015
2015
|
|
|
2016
2016
|
get pixelPerfect() {
|
|
2017
2017
|
return this._pixelPerfect;
|
|
@@ -2035,8 +2035,9 @@ async function q5playPreSetup(q) {
|
|
|
2035
2035
|
get rotation() {
|
|
2036
2036
|
if (!this._physicsEnabled || !usePhysics) return this._rotation || 0;
|
|
2037
2037
|
let val = b2Body_GetRotation(this.bdID).GetAngle();
|
|
2038
|
+
if ($._angleMode == DEGREES) val = $.degrees(val);
|
|
2038
2039
|
if (friendlyRounding) val = fixRoundAngular(val);
|
|
2039
|
-
return (this._rotation =
|
|
2040
|
+
return (this._rotation = val);
|
|
2040
2041
|
}
|
|
2041
2042
|
set rotation(val) {
|
|
2042
2043
|
this._rotation = val;
|
|
@@ -2153,14 +2154,14 @@ async function q5playPreSetup(q) {
|
|
|
2153
2154
|
return this._vel.mag();
|
|
2154
2155
|
}
|
|
2155
2156
|
set speed(val) {
|
|
2156
|
-
if (!val) this.
|
|
2157
|
+
if (!val) this.__setVel(0, 0);
|
|
2157
2158
|
else {
|
|
2158
2159
|
const mag = this._vel.mag();
|
|
2159
2160
|
if (mag > 0) {
|
|
2160
|
-
this.
|
|
2161
|
+
this.__setVel((this._vel.x / mag) * val, (this._vel.y / mag) * val);
|
|
2161
2162
|
} else {
|
|
2162
2163
|
const dir = this._vel.direction();
|
|
2163
|
-
this.
|
|
2164
|
+
this.__setVel($.cos(dir) * val, $.sin(dir) * val);
|
|
2164
2165
|
}
|
|
2165
2166
|
}
|
|
2166
2167
|
this._vel._mag = val;
|
|
@@ -2168,7 +2169,7 @@ async function q5playPreSetup(q) {
|
|
|
2168
2169
|
}
|
|
2169
2170
|
|
|
2170
2171
|
setSpeedAndDirection(speed, direction) {
|
|
2171
|
-
this.
|
|
2172
|
+
this.__setVel($.cos(direction) * speed, $.sin(direction) * speed);
|
|
2172
2173
|
this._vel._mag = speed;
|
|
2173
2174
|
this._vel._direction = direction;
|
|
2174
2175
|
this._vel._magCached = this._vel._directionCached = true;
|
|
@@ -2230,7 +2231,7 @@ async function q5playPreSetup(q) {
|
|
|
2230
2231
|
}
|
|
2231
2232
|
|
|
2232
2233
|
get pos() {
|
|
2233
|
-
return this.
|
|
2234
|
+
return { x: this._posX, y: this._posY };
|
|
2234
2235
|
}
|
|
2235
2236
|
set pos(val) {
|
|
2236
2237
|
if (val == $.mouse && !$.mouse.isActive) return;
|
|
@@ -2409,7 +2410,6 @@ async function q5playPreSetup(q) {
|
|
|
2409
2410
|
}
|
|
2410
2411
|
set vel(val) {
|
|
2411
2412
|
this._setVel(val[0] ?? val.x, val[1] ?? val.y);
|
|
2412
|
-
this._vel._magCached = this._vel._directionCached = false;
|
|
2413
2413
|
}
|
|
2414
2414
|
|
|
2415
2415
|
_setVel(x, y) {
|
|
@@ -2419,6 +2419,16 @@ async function q5playPreSetup(q) {
|
|
|
2419
2419
|
this._velX = x;
|
|
2420
2420
|
this._velY = y;
|
|
2421
2421
|
this._velSynced = true;
|
|
2422
|
+
this._vel._magCached = this._vel._directionCached = false;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
__setVel(x, y) {
|
|
2426
|
+
if (this._physicsEnabled) {
|
|
2427
|
+
b2Body_SetLinearVelocity(this.bdID, new b2Vec2(x, y));
|
|
2428
|
+
}
|
|
2429
|
+
this._velX = x;
|
|
2430
|
+
this._velY = y;
|
|
2431
|
+
this._velSynced = true;
|
|
2422
2432
|
}
|
|
2423
2433
|
|
|
2424
2434
|
get velocity() {
|
|
@@ -2447,6 +2457,9 @@ async function q5playPreSetup(q) {
|
|
|
2447
2457
|
|
|
2448
2458
|
_update() {
|
|
2449
2459
|
if (this._customUpdate) this._customUpdate();
|
|
2460
|
+
this.prevX = this._posX;
|
|
2461
|
+
this.prevY = this._posY;
|
|
2462
|
+
this.prevRotation = this.rotation;
|
|
2450
2463
|
if (this.autoUpdate) this.autoUpdate = null;
|
|
2451
2464
|
}
|
|
2452
2465
|
|
|
@@ -2468,6 +2481,70 @@ async function q5playPreSetup(q) {
|
|
|
2468
2481
|
}
|
|
2469
2482
|
}
|
|
2470
2483
|
|
|
2484
|
+
if (this._destArrivalTime !== undefined && $.world.physicsTime >= this._destArrivalTime) {
|
|
2485
|
+
const x = this._posX,
|
|
2486
|
+
y = this._posY,
|
|
2487
|
+
prevX = this.prevX,
|
|
2488
|
+
prevY = this.prevY,
|
|
2489
|
+
destX = this._destX,
|
|
2490
|
+
destY = this._destY;
|
|
2491
|
+
|
|
2492
|
+
const destReachedX =
|
|
2493
|
+
destX === undefined || (destX >= Math.min(prevX, x) - visualSlop && destX <= Math.max(prevX, x) + visualSlop);
|
|
2494
|
+
const destReachedY =
|
|
2495
|
+
destY === undefined || (destY >= Math.min(prevY, y) - visualSlop && destY <= Math.max(prevY, y) + visualSlop);
|
|
2496
|
+
const destReached = destReachedX && destReachedY;
|
|
2497
|
+
|
|
2498
|
+
if (destReached) {
|
|
2499
|
+
this._setVel(0, 0);
|
|
2500
|
+
this.rotationSpeed = 0;
|
|
2501
|
+
this.pos = [this._destX ?? this._posX, this._destY ?? this._posY];
|
|
2502
|
+
if (this._destRot !== undefined) {
|
|
2503
|
+
this.rotation = this._destRot;
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
if (this._destResolve) {
|
|
2508
|
+
this._destResolve(destReached);
|
|
2509
|
+
this._destResolve = undefined;
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
this._destX = this._destY = this._destRot = this._destArrivalTime = undefined;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
if (this._destRotArrivalTime !== undefined && $.world.physicsTime >= this._destRotArrivalTime) {
|
|
2516
|
+
const isDeg = $._angleMode == DEGREES,
|
|
2517
|
+
full = isDeg ? 360 : $.TWO_PI,
|
|
2518
|
+
half = isDeg ? 180 : Math.PI,
|
|
2519
|
+
prevRot = this.prevRotation,
|
|
2520
|
+
currRot = this.rotation,
|
|
2521
|
+
destRot = this._destRot;
|
|
2522
|
+
|
|
2523
|
+
// normalize destRot to [-half, half) to match this.rotation's range
|
|
2524
|
+
let nd = ((destRot % full) + full) % full;
|
|
2525
|
+
if (nd >= half) nd -= full;
|
|
2526
|
+
|
|
2527
|
+
// when the sprite crosses the ±half boundary, prevRot and currRot jump
|
|
2528
|
+
// by ~full°; invert the range check so nd is tested against the arc that
|
|
2529
|
+
// was actually traversed rather than the gap between them
|
|
2530
|
+
const crossed180 = Math.abs(prevRot - currRot) > half;
|
|
2531
|
+
const rotReached = crossed180
|
|
2532
|
+
? nd >= Math.max(prevRot, currRot) - visualSlop || nd <= Math.min(prevRot, currRot) + visualSlop
|
|
2533
|
+
: nd >= Math.min(prevRot, currRot) - visualSlop && nd <= Math.max(prevRot, currRot) + visualSlop;
|
|
2534
|
+
|
|
2535
|
+
if (rotReached) {
|
|
2536
|
+
this.rotationSpeed = 0;
|
|
2537
|
+
this.rotation = nd;
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
if (this._destRotationResolve) {
|
|
2541
|
+
this._destRotationResolve(rotReached);
|
|
2542
|
+
this._destRotationResolve = undefined;
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
this._destRot = this._destRotArrivalTime = undefined;
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2471
2548
|
if (!this._physicsEnabled && !this._deleted) return;
|
|
2472
2549
|
|
|
2473
2550
|
this.__step();
|
|
@@ -2776,32 +2853,6 @@ async function q5playPreSetup(q) {
|
|
|
2776
2853
|
wind.delete();
|
|
2777
2854
|
}
|
|
2778
2855
|
|
|
2779
|
-
angleTo(x, y) {
|
|
2780
|
-
if (typeof x == 'object') {
|
|
2781
|
-
y = x.y;
|
|
2782
|
-
x = x.x;
|
|
2783
|
-
}
|
|
2784
|
-
return $.atan2(y - this.y, x - this.x);
|
|
2785
|
-
}
|
|
2786
|
-
|
|
2787
|
-
rotationToFace(x, y, facing) {
|
|
2788
|
-
if (typeof x == 'object') {
|
|
2789
|
-
facing = y;
|
|
2790
|
-
y = x.y;
|
|
2791
|
-
x = x.x;
|
|
2792
|
-
}
|
|
2793
|
-
// if the sprite is too close to the position, don't rotate
|
|
2794
|
-
if (Math.abs(x - this.x) < 0.01 && Math.abs(y - this.y) < 0.01) {
|
|
2795
|
-
return 0;
|
|
2796
|
-
}
|
|
2797
|
-
return this.angleTo(x, y) + (facing || 0);
|
|
2798
|
-
}
|
|
2799
|
-
|
|
2800
|
-
angleToFace(x, y, facing) {
|
|
2801
|
-
let ang = this.rotationToFace(x, y, facing);
|
|
2802
|
-
return minAngleDist(ang, this.rotation);
|
|
2803
|
-
}
|
|
2804
|
-
|
|
2805
2856
|
moveTowards(x, y, tracking) {
|
|
2806
2857
|
if (x === undefined) return;
|
|
2807
2858
|
|
|
@@ -2816,13 +2867,13 @@ async function q5playPreSetup(q) {
|
|
|
2816
2867
|
|
|
2817
2868
|
let velX, velY;
|
|
2818
2869
|
|
|
2819
|
-
if (x !== null) {
|
|
2870
|
+
if (x !== null && x !== undefined) {
|
|
2820
2871
|
let diffX = x - this.x;
|
|
2821
2872
|
if (!isSlop(diffX)) {
|
|
2822
2873
|
velX = diffX * tracking;
|
|
2823
2874
|
} else velX = 0;
|
|
2824
2875
|
} else velX = this._velX;
|
|
2825
|
-
if (y !== null) {
|
|
2876
|
+
if (y !== null && y !== undefined) {
|
|
2826
2877
|
let diffY = y - this.y;
|
|
2827
2878
|
if (!isSlop(diffY)) {
|
|
2828
2879
|
velY = diffY * tracking;
|
|
@@ -2830,7 +2881,155 @@ async function q5playPreSetup(q) {
|
|
|
2830
2881
|
} else velY = this._velY;
|
|
2831
2882
|
|
|
2832
2883
|
this._setVel(velX, velY);
|
|
2833
|
-
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
moveTo(x, y, speed) {
|
|
2887
|
+
if (x === undefined && (y === undefined || y === null)) return;
|
|
2888
|
+
|
|
2889
|
+
if (x !== null && x !== undefined && typeof x != 'number') {
|
|
2890
|
+
let pos = x;
|
|
2891
|
+
if (pos == $.mouse && !$.mouse.isActive) return;
|
|
2892
|
+
speed = y;
|
|
2893
|
+
y = pos.y;
|
|
2894
|
+
x = pos.x;
|
|
2895
|
+
}
|
|
2896
|
+
|
|
2897
|
+
const moveX = x !== null && x !== undefined;
|
|
2898
|
+
const moveY = y !== null && y !== undefined;
|
|
2899
|
+
|
|
2900
|
+
speed ||= this.speed || 1;
|
|
2901
|
+
|
|
2902
|
+
const dist =
|
|
2903
|
+
moveX && moveY
|
|
2904
|
+
? Math.hypot(x - this._posX, y - this._posY)
|
|
2905
|
+
: moveX
|
|
2906
|
+
? Math.abs(x - this._posX)
|
|
2907
|
+
: Math.abs(y - this._posY);
|
|
2908
|
+
|
|
2909
|
+
if (this._destResolve) {
|
|
2910
|
+
this._destResolve(false);
|
|
2911
|
+
this._destResolve = undefined;
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2914
|
+
this._destX = moveX ? x : undefined;
|
|
2915
|
+
this._destY = moveY ? y : undefined;
|
|
2916
|
+
this._destArrivalTime = $.world.physicsTime + dist / (speed * $.world._updateRate);
|
|
2917
|
+
|
|
2918
|
+
if (dist > 0) {
|
|
2919
|
+
if (moveX && moveY) {
|
|
2920
|
+
this.setSpeedAndDirection(speed, $.atan2(y - this.y, x - this.x));
|
|
2921
|
+
} else if (moveX) {
|
|
2922
|
+
this._setVel(x > this._posX ? speed : -speed, this._velY);
|
|
2923
|
+
} else {
|
|
2924
|
+
this._setVel(this._velX, y > this._posY ? speed : -speed);
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
|
|
2928
|
+
return {
|
|
2929
|
+
then: (onFulfilled) => {
|
|
2930
|
+
this._destResolve = onFulfilled;
|
|
2931
|
+
}
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
angleTo(x, y, facing = 0) {
|
|
2936
|
+
if (typeof x == 'object') {
|
|
2937
|
+
facing = y || 0;
|
|
2938
|
+
y = x.y;
|
|
2939
|
+
x = x.x;
|
|
2940
|
+
}
|
|
2941
|
+
// if the sprite is too close to the position, don't rotate
|
|
2942
|
+
if (Math.abs(x - this.x) < 0.01 && Math.abs(y - this.y) < 0.01) {
|
|
2943
|
+
return this.rotation;
|
|
2944
|
+
}
|
|
2945
|
+
return $.atan2(y - this.y, x - this.x) + facing;
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
angleDistTo(x, y, facing = 0) {
|
|
2949
|
+
if (typeof x == 'object') {
|
|
2950
|
+
facing = y || 0;
|
|
2951
|
+
y = x.y;
|
|
2952
|
+
x = x.x;
|
|
2953
|
+
}
|
|
2954
|
+
// if the sprite is too close to the position, don't rotate
|
|
2955
|
+
if (Math.abs(x - this.x) < 0.01 && Math.abs(y - this.y) < 0.01) {
|
|
2956
|
+
return 0;
|
|
2957
|
+
}
|
|
2958
|
+
return minAngleDist($.atan2(y - this.y, x - this.x) + facing, this.rotation);
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2961
|
+
rotateTo(angle, speed) {
|
|
2962
|
+
let args = arguments;
|
|
2963
|
+
let x, y, facing;
|
|
2964
|
+
if (typeof args[0] != 'number') {
|
|
2965
|
+
x = args[0].x;
|
|
2966
|
+
y = args[0].y;
|
|
2967
|
+
speed = args[1];
|
|
2968
|
+
facing = args[2];
|
|
2969
|
+
} else if (arguments.length > 2) {
|
|
2970
|
+
x = args[0];
|
|
2971
|
+
y = args[1];
|
|
2972
|
+
speed = args[2];
|
|
2973
|
+
facing = args[3];
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
if (x !== undefined) angle = this.angleTo(x, y, facing);
|
|
2977
|
+
|
|
2978
|
+
const full = $._angleMode == DEGREES ? 360 : $.TWO_PI;
|
|
2979
|
+
let angleDist = (angle - this.rotation) % full;
|
|
2980
|
+
if (angleDist < 0 && speed > 0) angleDist += full;
|
|
2981
|
+
if (angleDist > 0 && speed < 0) angleDist -= full;
|
|
2982
|
+
|
|
2983
|
+
return this.rotate(angleDist, speed);
|
|
2984
|
+
}
|
|
2985
|
+
|
|
2986
|
+
rotateMinTo(angle, speed, facing) {
|
|
2987
|
+
let args = arguments;
|
|
2988
|
+
let x, y;
|
|
2989
|
+
if (typeof args[0] != 'number') {
|
|
2990
|
+
x = args[0].x;
|
|
2991
|
+
y = args[0].y;
|
|
2992
|
+
speed = args[1];
|
|
2993
|
+
facing = args[2];
|
|
2994
|
+
} else if (args.length > 2) {
|
|
2995
|
+
x = args[0];
|
|
2996
|
+
y = args[1];
|
|
2997
|
+
speed = args[2];
|
|
2998
|
+
facing = args[3];
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
if (x !== undefined) angle = this.angleTo(x, y, facing);
|
|
3002
|
+
|
|
3003
|
+
return this.rotate(minAngleDist(angle, this.rotation), speed);
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
rotate(angleDist, speed) {
|
|
3007
|
+
if (Math.abs(angleDist) <= angularSlop) return;
|
|
3008
|
+
|
|
3009
|
+
speed ||= this.rotationSpeed || 1;
|
|
3010
|
+
speed = Math.abs(speed) * Math.sign(angleDist);
|
|
3011
|
+
|
|
3012
|
+
// cap speed so the sprite doesn't overshoot the destination in one physics step
|
|
3013
|
+
if (Math.abs(speed) > Math.abs(angleDist)) speed = angleDist;
|
|
3014
|
+
|
|
3015
|
+
this._destRotArrivalTime = $.world.physicsTime + Math.abs(angleDist) / (Math.abs(speed) * $.world._updateRate);
|
|
3016
|
+
|
|
3017
|
+
this._destRot = this.rotation + angleDist;
|
|
3018
|
+
|
|
3019
|
+
if (this._destRotationResolve) {
|
|
3020
|
+
this._destRotationResolve(false);
|
|
3021
|
+
this._destRotationResolve = undefined;
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
this.rotationSpeed = speed;
|
|
3025
|
+
|
|
3026
|
+
log(this.rotation, this._destRot, angleDist, speed, this._destRotArrivalTime);
|
|
3027
|
+
|
|
3028
|
+
return {
|
|
3029
|
+
then: (onFulfilled) => {
|
|
3030
|
+
this._destRotationResolve = onFulfilled;
|
|
3031
|
+
}
|
|
3032
|
+
};
|
|
2834
3033
|
}
|
|
2835
3034
|
|
|
2836
3035
|
rotateTowards(angle, tracking) {
|
|
@@ -2848,18 +3047,31 @@ async function q5playPreSetup(q) {
|
|
|
2848
3047
|
facing = args[3];
|
|
2849
3048
|
}
|
|
2850
3049
|
|
|
2851
|
-
if (x !== undefined) angle = this.
|
|
3050
|
+
if (x !== undefined) angle = this.angleDistTo(x, y, facing);
|
|
2852
3051
|
else angle -= this.rotation;
|
|
2853
3052
|
|
|
2854
3053
|
tracking ??= 0.1;
|
|
2855
3054
|
this.rotationSpeed = angle * tracking;
|
|
2856
3055
|
}
|
|
2857
3056
|
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
3057
|
+
transformTowards(x, y, rotation, tracking = 0.1) {
|
|
3058
|
+
if (x === undefined) return;
|
|
3059
|
+
|
|
3060
|
+
if (typeof x != 'number') {
|
|
3061
|
+
let pos = x;
|
|
3062
|
+
if (pos == $.mouse && !$.mouse.isActive) return;
|
|
3063
|
+
tracking = rotation ?? tracking;
|
|
3064
|
+
rotation = y;
|
|
3065
|
+
y = pos.y;
|
|
3066
|
+
x = pos.x;
|
|
3067
|
+
}
|
|
3068
|
+
|
|
3069
|
+
const t = new b2Transform();
|
|
3070
|
+
t.p = scaleTo(x ?? this._posX, y ?? this._posY);
|
|
3071
|
+
rotation ??= this._rotation;
|
|
3072
|
+
if ($._angleMode == DEGREES) rotation = (rotation % 360) * DEGTORAD;
|
|
2861
3073
|
t.q = b2MakeRot(rotation);
|
|
2862
|
-
b2Body_SetTargetTransform(this.bdID, t, $.world._timeStep);
|
|
3074
|
+
b2Body_SetTargetTransform(this.bdID, t, $.world._timeStep / tracking);
|
|
2863
3075
|
}
|
|
2864
3076
|
|
|
2865
3077
|
delete() {
|
|
@@ -4532,6 +4744,134 @@ async function q5playPreSetup(q) {
|
|
|
4532
4744
|
}
|
|
4533
4745
|
}
|
|
4534
4746
|
|
|
4747
|
+
rotateTowards() {
|
|
4748
|
+
for (let s of this) {
|
|
4749
|
+
s.rotateTowards(...arguments);
|
|
4750
|
+
}
|
|
4751
|
+
}
|
|
4752
|
+
|
|
4753
|
+
rotateTo(angle, speed) {
|
|
4754
|
+
const thenables = [];
|
|
4755
|
+
for (let s of this) {
|
|
4756
|
+
thenables.push(s.rotateTo(...arguments));
|
|
4757
|
+
}
|
|
4758
|
+
return {
|
|
4759
|
+
then: (onFulfilled) => {
|
|
4760
|
+
let pending = thenables.length;
|
|
4761
|
+
if (!pending) return onFulfilled(true);
|
|
4762
|
+
let allReached = true;
|
|
4763
|
+
for (let t of thenables) {
|
|
4764
|
+
t.then((reached) => {
|
|
4765
|
+
if (!reached) allReached = false;
|
|
4766
|
+
if (--pending === 0) onFulfilled(allReached);
|
|
4767
|
+
});
|
|
4768
|
+
}
|
|
4769
|
+
}
|
|
4770
|
+
};
|
|
4771
|
+
}
|
|
4772
|
+
|
|
4773
|
+
rotate(angle, speed) {
|
|
4774
|
+
const thenables = [];
|
|
4775
|
+
for (let s of this) {
|
|
4776
|
+
thenables.push(s.rotate(...arguments));
|
|
4777
|
+
}
|
|
4778
|
+
return {
|
|
4779
|
+
then: (onFulfilled) => {
|
|
4780
|
+
let pending = thenables.length;
|
|
4781
|
+
if (!pending) return onFulfilled(true);
|
|
4782
|
+
let allReached = true;
|
|
4783
|
+
for (let t of thenables) {
|
|
4784
|
+
t.then((reached) => {
|
|
4785
|
+
if (!reached) allReached = false;
|
|
4786
|
+
if (--pending === 0) onFulfilled(allReached);
|
|
4787
|
+
});
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
};
|
|
4791
|
+
}
|
|
4792
|
+
|
|
4793
|
+
rotateMinTo(angle, speed) {
|
|
4794
|
+
const thenables = [];
|
|
4795
|
+
for (let s of this) {
|
|
4796
|
+
thenables.push(s.rotateMinTo(...arguments));
|
|
4797
|
+
}
|
|
4798
|
+
return {
|
|
4799
|
+
then: (onFulfilled) => {
|
|
4800
|
+
let pending = thenables.length;
|
|
4801
|
+
if (!pending) return onFulfilled(true);
|
|
4802
|
+
let allReached = true;
|
|
4803
|
+
for (let t of thenables) {
|
|
4804
|
+
t.then((reached) => {
|
|
4805
|
+
if (!reached) allReached = false;
|
|
4806
|
+
if (--pending === 0) onFulfilled(allReached);
|
|
4807
|
+
});
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
};
|
|
4811
|
+
}
|
|
4812
|
+
|
|
4813
|
+
transformTowards(x, y, rotation, tracking = 0.1) {
|
|
4814
|
+
if (x === undefined) return;
|
|
4815
|
+
|
|
4816
|
+
if (typeof x != 'number') {
|
|
4817
|
+
let pos = x;
|
|
4818
|
+
if (pos == $.mouse && !$.mouse.isActive) return;
|
|
4819
|
+
tracking = rotation ?? tracking;
|
|
4820
|
+
rotation = y;
|
|
4821
|
+
y = pos.y;
|
|
4822
|
+
x = pos.x;
|
|
4823
|
+
}
|
|
4824
|
+
|
|
4825
|
+
this._resetCentroid();
|
|
4826
|
+
|
|
4827
|
+
for (let s of this) {
|
|
4828
|
+
if (s.distCentroid === undefined) {
|
|
4829
|
+
this._resetDistancesFromCentroid();
|
|
4830
|
+
}
|
|
4831
|
+
s.transformTowards(s.distCentroid.x + x, s.distCentroid.y + y, rotation, tracking);
|
|
4832
|
+
}
|
|
4833
|
+
}
|
|
4834
|
+
|
|
4835
|
+
moveTo(x, y, speed) {
|
|
4836
|
+
if (x === undefined && (y === undefined || y === null)) return;
|
|
4837
|
+
|
|
4838
|
+
let nullX = x === null || x === undefined;
|
|
4839
|
+
let nullY = y === null || y === undefined;
|
|
4840
|
+
|
|
4841
|
+
if (!nullX && typeof x != 'number') {
|
|
4842
|
+
let pos = x;
|
|
4843
|
+
if (pos == $.mouse && !$.mouse.isActive) return;
|
|
4844
|
+
speed = y;
|
|
4845
|
+
y = pos.y;
|
|
4846
|
+
x = pos.x;
|
|
4847
|
+
nullX = nullY = false;
|
|
4848
|
+
}
|
|
4849
|
+
|
|
4850
|
+
this._resetCentroid();
|
|
4851
|
+
this._resetDistancesFromCentroid();
|
|
4852
|
+
|
|
4853
|
+
const thenables = [];
|
|
4854
|
+
for (let s of this) {
|
|
4855
|
+
const tx = nullX ? null : s.distCentroid.x + x;
|
|
4856
|
+
const ty = nullY ? null : s.distCentroid.y + y;
|
|
4857
|
+
thenables.push(s.moveTo(tx, ty, speed));
|
|
4858
|
+
}
|
|
4859
|
+
|
|
4860
|
+
return {
|
|
4861
|
+
then: (onFulfilled) => {
|
|
4862
|
+
let pending = thenables.length;
|
|
4863
|
+
if (!pending) return onFulfilled(true);
|
|
4864
|
+
let allReached = true;
|
|
4865
|
+
for (let t of thenables) {
|
|
4866
|
+
t.then((reached) => {
|
|
4867
|
+
if (!reached) allReached = false;
|
|
4868
|
+
if (--pending === 0) onFulfilled(allReached);
|
|
4869
|
+
});
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4872
|
+
};
|
|
4873
|
+
}
|
|
4874
|
+
|
|
4535
4875
|
toString() {
|
|
4536
4876
|
return 'g' + this.idNum;
|
|
4537
4877
|
}
|
|
@@ -5040,6 +5380,7 @@ async function q5playPreSetup(q) {
|
|
|
5040
5380
|
}
|
|
5041
5381
|
set meterSize(val) {
|
|
5042
5382
|
meterSize = val;
|
|
5383
|
+
visualSlop = meterSize / 120;
|
|
5043
5384
|
}
|
|
5044
5385
|
|
|
5045
5386
|
get profile() {
|
|
@@ -5155,6 +5496,8 @@ async function q5playPreSetup(q) {
|
|
|
5155
5496
|
|
|
5156
5497
|
this.physicsTime += timeStep;
|
|
5157
5498
|
|
|
5499
|
+
this._sync();
|
|
5500
|
+
|
|
5158
5501
|
let sprites = Object.values($.q5play.sprites);
|
|
5159
5502
|
let groups = Object.values($.q5play.groups);
|
|
5160
5503
|
|
|
@@ -5171,6 +5514,71 @@ async function q5playPreSetup(q) {
|
|
|
5171
5514
|
if (this.autoStep) this.autoStep = null;
|
|
5172
5515
|
}
|
|
5173
5516
|
|
|
5517
|
+
_sync() {
|
|
5518
|
+
jointStack = [];
|
|
5519
|
+
shapeStack = [];
|
|
5520
|
+
|
|
5521
|
+
b2World_Draw(wID, drawCmds.GetDebugDraw());
|
|
5522
|
+
|
|
5523
|
+
let cmdPtr = drawCmds.GetCommandsData(),
|
|
5524
|
+
cmdSize = drawCmds.GetCommandsSize(),
|
|
5525
|
+
cmdStride = drawCmds.GetCommandStride(),
|
|
5526
|
+
offset = cmdPtr,
|
|
5527
|
+
renderJointForces = $.q5play.renderJointForces,
|
|
5528
|
+
s;
|
|
5529
|
+
|
|
5530
|
+
for (let i = 0; i < cmdSize; i++, offset += cmdStride) {
|
|
5531
|
+
// workaround that unpacks data from
|
|
5532
|
+
// the shape material's customColor
|
|
5533
|
+
const customColor = Box2D.HEAPU32[(offset + 4) >> 2],
|
|
5534
|
+
uid = customColor & 0xffffff,
|
|
5535
|
+
isSensor = (customColor >>> 25) & 0x1,
|
|
5536
|
+
isFirstShape = (customColor >>> 26) & 0x1;
|
|
5537
|
+
|
|
5538
|
+
s = $.q5play.sprites[uid];
|
|
5539
|
+
|
|
5540
|
+
let type = Box2D.HEAPU8[offset];
|
|
5541
|
+
|
|
5542
|
+
if (type == 7) {
|
|
5543
|
+
continue;
|
|
5544
|
+
}
|
|
5545
|
+
|
|
5546
|
+
let vertexCount = Box2D.HEAPU16[(offset + 8) >> 1];
|
|
5547
|
+
|
|
5548
|
+
let dataLen = 4;
|
|
5549
|
+
if (type == 1) dataLen = 5 + vertexCount * 2;
|
|
5550
|
+
else if (type == 3 || type == 4) dataLen = 5;
|
|
5551
|
+
let data = new Float32Array(Box2D.HEAPU8.buffer, offset + 12, dataLen);
|
|
5552
|
+
|
|
5553
|
+
if (!s) {
|
|
5554
|
+
if (type == 0 && renderJointForces) jointStack.push(data);
|
|
5555
|
+
continue;
|
|
5556
|
+
}
|
|
5557
|
+
|
|
5558
|
+
// always keep position in sync since it has a low performance cost
|
|
5559
|
+
// unless the shape is a chain
|
|
5560
|
+
if (type < 4 || (type == 4 && !s._hasCapsuleChain)) {
|
|
5561
|
+
s._posX = data[0] * meterSize;
|
|
5562
|
+
s._posY = data[1] * meterSize;
|
|
5563
|
+
}
|
|
5564
|
+
|
|
5565
|
+
s._velSynced = false;
|
|
5566
|
+
s._vel._magCached = false;
|
|
5567
|
+
|
|
5568
|
+
if (!s.visible) {
|
|
5569
|
+
continue;
|
|
5570
|
+
}
|
|
5571
|
+
|
|
5572
|
+
if (s._hasImagery || s._userDefinedDraw) {
|
|
5573
|
+
s._rotation = Math.atan2(data[2], data[3]) * RADTODEG;
|
|
5574
|
+
}
|
|
5575
|
+
|
|
5576
|
+
if (s.debug || (!s._hasImagery && !s._userDefinedDraw)) {
|
|
5577
|
+
shapeStack.push({ type, sprite: s, isSensor, isFirstShape, data, vertexCount });
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
|
|
5174
5582
|
get realTime() {
|
|
5175
5583
|
return $.millis() / 1000;
|
|
5176
5584
|
}
|
|
@@ -5298,7 +5706,7 @@ async function q5playPreSetup(q) {
|
|
|
5298
5706
|
}
|
|
5299
5707
|
|
|
5300
5708
|
get pos() {
|
|
5301
|
-
return this._pos;
|
|
5709
|
+
return { x: this._pos.x, y: this._pos.y };
|
|
5302
5710
|
}
|
|
5303
5711
|
set pos(val) {
|
|
5304
5712
|
this.x = val[0] ?? val.x;
|
|
@@ -6966,7 +7374,7 @@ async function q5playPreSetup(q) {
|
|
|
6966
7374
|
}
|
|
6967
7375
|
|
|
6968
7376
|
get pos() {
|
|
6969
|
-
return this.
|
|
7377
|
+
return { x: this.x, y: this.y };
|
|
6970
7378
|
}
|
|
6971
7379
|
get position() {
|
|
6972
7380
|
return this._pos;
|
|
@@ -7879,71 +8287,6 @@ async function q5playPreSetup(q) {
|
|
|
7879
8287
|
jointStack = [],
|
|
7880
8288
|
shapeStack = [];
|
|
7881
8289
|
|
|
7882
|
-
$._syncWorld = () => {
|
|
7883
|
-
jointStack = [];
|
|
7884
|
-
shapeStack = [];
|
|
7885
|
-
|
|
7886
|
-
b2World_Draw(wID, drawCmds.GetDebugDraw());
|
|
7887
|
-
|
|
7888
|
-
let cmdPtr = drawCmds.GetCommandsData(),
|
|
7889
|
-
cmdSize = drawCmds.GetCommandsSize(),
|
|
7890
|
-
cmdStride = drawCmds.GetCommandStride(),
|
|
7891
|
-
offset = cmdPtr,
|
|
7892
|
-
renderJointForces = $.q5play.renderJointForces,
|
|
7893
|
-
s;
|
|
7894
|
-
|
|
7895
|
-
for (let i = 0; i < cmdSize; i++, offset += cmdStride) {
|
|
7896
|
-
// workaround that unpacks data from
|
|
7897
|
-
// the shape material's customColor
|
|
7898
|
-
const customColor = Box2D.HEAPU32[(offset + 4) >> 2],
|
|
7899
|
-
uid = customColor & 0xffffff,
|
|
7900
|
-
isSensor = (customColor >>> 25) & 0x1,
|
|
7901
|
-
isFirstShape = (customColor >>> 26) & 0x1;
|
|
7902
|
-
|
|
7903
|
-
s = $.q5play.sprites[uid];
|
|
7904
|
-
|
|
7905
|
-
let type = Box2D.HEAPU8[offset];
|
|
7906
|
-
|
|
7907
|
-
if (type == 7) {
|
|
7908
|
-
continue;
|
|
7909
|
-
}
|
|
7910
|
-
|
|
7911
|
-
let vertexCount = Box2D.HEAPU16[(offset + 8) >> 1];
|
|
7912
|
-
|
|
7913
|
-
let dataLen = 4;
|
|
7914
|
-
if (type == 1) dataLen = 5 + vertexCount * 2;
|
|
7915
|
-
else if (type == 3 || type == 4) dataLen = 5;
|
|
7916
|
-
let data = new Float32Array(Box2D.HEAPU8.buffer, offset + 12, dataLen);
|
|
7917
|
-
|
|
7918
|
-
if (!s) {
|
|
7919
|
-
if (type == 0 && renderJointForces) jointStack.push(data);
|
|
7920
|
-
continue;
|
|
7921
|
-
}
|
|
7922
|
-
|
|
7923
|
-
// always keep position in sync since it has a low performance cost
|
|
7924
|
-
// unless the shape is a chain
|
|
7925
|
-
if (type < 4 || (type == 4 && !s._hasCapsuleChain)) {
|
|
7926
|
-
s._posX = data[0] * meterSize;
|
|
7927
|
-
s._posY = data[1] * meterSize;
|
|
7928
|
-
}
|
|
7929
|
-
|
|
7930
|
-
s._velSynced = false;
|
|
7931
|
-
s._vel._magCached = false;
|
|
7932
|
-
|
|
7933
|
-
if (!s.visible) {
|
|
7934
|
-
continue;
|
|
7935
|
-
}
|
|
7936
|
-
|
|
7937
|
-
if (s._hasImagery || s._userDefinedDraw) {
|
|
7938
|
-
s._rotation = Math.atan2(data[2], data[3]) * RADTODEG;
|
|
7939
|
-
}
|
|
7940
|
-
|
|
7941
|
-
if (s.debug || (!s._hasImagery && !s._userDefinedDraw)) {
|
|
7942
|
-
shapeStack.push({ type, sprite: s, isSensor, isFirstShape, data, vertexCount });
|
|
7943
|
-
}
|
|
7944
|
-
}
|
|
7945
|
-
};
|
|
7946
|
-
|
|
7947
8290
|
const colorMax = $._colorFormat,
|
|
7948
8291
|
debugGreen = $.color(0, colorMax, 0, colorMax * 0.9),
|
|
7949
8292
|
debugGreenFill = $.color(0, colorMax, 0, colorMax * 0.1),
|
|
@@ -8242,7 +8585,6 @@ function q5playUpdate() {
|
|
|
8242
8585
|
|
|
8243
8586
|
if ($.world.autoStep && $.world.timeScale > 0) {
|
|
8244
8587
|
$.world.physicsUpdate();
|
|
8245
|
-
$._syncWorld();
|
|
8246
8588
|
}
|
|
8247
8589
|
$.world.autoStep ??= true;
|
|
8248
8590
|
|
|
@@ -8413,8 +8755,7 @@ attractTo -> es:atraerA
|
|
|
8413
8755
|
repelFrom -> es:repelerDe
|
|
8414
8756
|
applyTorque -> es:aplicarTorque
|
|
8415
8757
|
angleTo -> es:ánguloHacia
|
|
8416
|
-
|
|
8417
|
-
angleToFace -> es:ánguloParaMirar
|
|
8758
|
+
angleDistTo -> es:distÁnguloHacia
|
|
8418
8759
|
setSpeedAndDirection -> es:establecerVelocidadYDirección
|
|
8419
8760
|
scaleBy -> es:escalarPor
|
|
8420
8761
|
resetMass -> es:reiniciarMasa
|