q5play 4.0.7 → 4.0.8

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/q5play.js +88 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q5play",
3
- "version": "4.0.7",
3
+ "version": "4.0.8",
4
4
  "author": "quinton-ashley",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "description": "A web-based game engine that uses q5.js WebGPU for graphics and Box2D v3 WASM for physics.",
package/q5play.js CHANGED
@@ -334,7 +334,8 @@ async function q5playPreSetup(q) {
334
334
 
335
335
  // in q5play the default angle mode is degrees
336
336
  const DEGREES = $.DEGREES,
337
- DEGTORAD = Math.PI / 180;
337
+ DEGTORAD = Math.PI / 180,
338
+ RADTODEG = 180 / Math.PI;
338
339
  $.angleMode(DEGREES);
339
340
 
340
341
  // in q5play the default color mode is float RGB
@@ -1004,6 +1005,7 @@ async function q5playPreSetup(q) {
1004
1005
  if (!group.visualOnly) {
1005
1006
  const def = new b2DefaultBodyDef();
1006
1007
  def.type = bodyTypes[this._phys];
1008
+ def.allowFastRotation = true;
1007
1009
  this.bdID = b2CreateBody(wID, def);
1008
1010
  this._physicsEnabled = true;
1009
1011
 
@@ -5348,6 +5350,7 @@ async function q5playPreSetup(q) {
5348
5350
  this.type = type ??= 'glue';
5349
5351
  this.visible = true;
5350
5352
  this.deleted = false;
5353
+ this._springiness = 0;
5351
5354
 
5352
5355
  if (!a._shapes.length) a.addDefaultSensors();
5353
5356
  if (!b._shapes.length) b.addDefaultSensors();
@@ -5536,6 +5539,7 @@ async function q5playPreSetup(q) {
5536
5539
 
5537
5540
  _springMap(val) {
5538
5541
  if (val > 0) {
5542
+ this._springiness = val;
5539
5543
  if (val < 0.1) {
5540
5544
  val = $.map(val, 0, 0.1, 30, 4);
5541
5545
  } else if (val < 0.5) {
@@ -5572,7 +5576,7 @@ async function q5playPreSetup(q) {
5572
5576
  }
5573
5577
 
5574
5578
  get springiness() {
5575
- return Box2D.b2WeldJoint_GetLinearHertz(this.jID);
5579
+ return this._springiness;
5576
5580
  }
5577
5581
  set springiness(val) {
5578
5582
  val = this._springMap(val);
@@ -5648,7 +5652,7 @@ async function q5playPreSetup(q) {
5648
5652
  }
5649
5653
 
5650
5654
  get springiness() {
5651
- return Box2D.b2DistanceJoint_GetSpringHertz(this.jID);
5655
+ return this._springiness;
5652
5656
  }
5653
5657
  set springiness(val) {
5654
5658
  val = this._springMap(val);
@@ -5692,15 +5696,20 @@ async function q5playPreSetup(q) {
5692
5696
  constructor(spriteA, spriteB) {
5693
5697
  super(spriteA, spriteB, 'wheel');
5694
5698
 
5699
+ this._angle = $._angleMode == DEGREES ? 90 : Math.PI / 2;
5700
+ this._motorEnabled = false;
5701
+
5695
5702
  let j = this._init(b2DefaultWheelJointDef(wID));
5696
5703
  j.enableSpring = true;
5697
5704
  j.hertz = 4;
5698
5705
  j.dampingRatio = 0.7;
5699
- j.enableMotor = true;
5706
+ j.enableMotor = false; // neutral by default
5700
5707
  j.maxMotorTorque = 1000;
5701
5708
 
5702
5709
  this.jID = b2CreateWheelJoint(wID, j);
5703
5710
  jointDict[this.jID.index1] = this;
5711
+
5712
+ this._springiness = 0.1;
5704
5713
  }
5705
5714
 
5706
5715
  _init(j) {
@@ -5710,11 +5719,12 @@ async function q5playPreSetup(q) {
5710
5719
  j.base.bodyIdA = a.bdID;
5711
5720
  j.base.bodyIdB = b.bdID;
5712
5721
 
5713
- j.base.localFrameB.p = b2Body_GetLocalPoint(b.bdID, scaleTo(a.x, a.y));
5722
+ let rad = this._angle;
5723
+ if ($._angleMode == DEGREES) rad *= DEGTORAD;
5724
+ j.base.localFrameA.q.SetAngle(rad);
5714
5725
 
5715
- // let qA = b2Body_GetRotation(a.bdID);
5716
- // let qB = b2Body_GetRotation(b.bdID);
5717
- // j.base.localFrameA.q = b2InvMulRot(qA, qB);
5726
+ let pivot = scaleTo(b.x, b.y);
5727
+ j.base.localFrameA.p = b2Body_GetLocalPoint(a.bdID, pivot);
5718
5728
 
5719
5729
  return j;
5720
5730
  }
@@ -5727,9 +5737,12 @@ async function q5playPreSetup(q) {
5727
5737
  set angle(val) {
5728
5738
  if (val == this._angle) return;
5729
5739
  this._angle = val;
5730
- this._j.m_localXAxisA = new b2Vec2($.cos(val), $.sin(val));
5731
- this._j.m_localXAxisA.normalize();
5732
- this._j.m_localYAxisA = b2Vec2.crossNumVec2(1.0, this._j.m_localXAxisA);
5740
+ let rad = $._angleMode == DEGREES ? val * DEGTORAD : val;
5741
+
5742
+ let t = b2Joint_GetLocalFrameA(this.jID);
5743
+ t.q.SetAngle(rad);
5744
+ b2Joint_SetLocalFrameA(this.jID, t);
5745
+ b2Joint_WakeBodies(this.jID);
5733
5746
  }
5734
5747
 
5735
5748
  get springEnabled() {
@@ -5740,7 +5753,7 @@ async function q5playPreSetup(q) {
5740
5753
  }
5741
5754
 
5742
5755
  get springiness() {
5743
- return Box2D.b2WheelJoint_GetSpringHertz(this.jID);
5756
+ return this._springiness;
5744
5757
  }
5745
5758
  set springiness(val) {
5746
5759
  val = this._springMap(val);
@@ -5778,13 +5791,16 @@ async function q5playPreSetup(q) {
5778
5791
  }
5779
5792
  set motorEnabled(val) {
5780
5793
  Box2D.b2WheelJoint_EnableMotor(this.jID, val);
5794
+ this._motorEnabled = val;
5781
5795
  }
5782
5796
 
5783
5797
  get maxPower() {
5784
5798
  return Box2D.b2WheelJoint_GetMaxMotorTorque(this.jID);
5785
5799
  }
5786
5800
  set maxPower(val) {
5801
+ if (val > 0 && !this._motorEnabled) this.motorEnabled = true;
5787
5802
  Box2D.b2WheelJoint_SetMaxMotorTorque(this.jID, val);
5803
+ b2Joint_WakeBodies(this.jID);
5788
5804
  }
5789
5805
 
5790
5806
  get power() {
@@ -5792,10 +5808,14 @@ async function q5playPreSetup(q) {
5792
5808
  }
5793
5809
 
5794
5810
  get speed() {
5811
+ // if in neutral, return the wheel's angular velocity
5812
+ if (!this._motorEnabled) return this.spriteB.rotationSpeed;
5795
5813
  return Box2D.b2WheelJoint_GetMotorSpeed(this.jID);
5796
5814
  }
5797
5815
  set speed(val) {
5816
+ if (!this._motorEnabled) this.motorEnabled = true;
5798
5817
  Box2D.b2WheelJoint_SetMotorSpeed(this.jID, val);
5818
+ b2Joint_WakeBodies(this.jID);
5799
5819
  }
5800
5820
  };
5801
5821
 
@@ -5823,7 +5843,7 @@ async function q5playPreSetup(q) {
5823
5843
  }
5824
5844
 
5825
5845
  get springiness() {
5826
- return Box2D.b2RevoluteJoint_GetSpringHertz(this.jID);
5846
+ return this._springiness;
5827
5847
  }
5828
5848
  set springiness(val) {
5829
5849
  val = this._springMap(val);
@@ -5863,8 +5883,8 @@ async function q5playPreSetup(q) {
5863
5883
  max = val[1];
5864
5884
  }
5865
5885
  if ($._angleMode == DEGREES) {
5866
- min *= $._RADTODEG;
5867
- max *= $._RADTODEG;
5886
+ min *= DEGTORAD;
5887
+ max *= DEGTORAD;
5868
5888
  }
5869
5889
  Box2D.b2RevoluteJoint_SetLimits(this.jID, min, max);
5870
5890
  }
@@ -5893,8 +5913,6 @@ async function q5playPreSetup(q) {
5893
5913
  set maxPower(val) {
5894
5914
  Box2D.b2RevoluteJoint_SetMaxMotorTorque(this.jID, val);
5895
5915
  }
5896
-
5897
- _display() {}
5898
5916
  };
5899
5917
 
5900
5918
  $.SliderJoint = class extends $.Joint {
@@ -5902,17 +5920,39 @@ async function q5playPreSetup(q) {
5902
5920
  super(spriteA, spriteB, 'slider');
5903
5921
 
5904
5922
  let j = this._init(b2DefaultPrismaticJointDef());
5905
- j.enableLimit = true;
5906
- j.lowerTranslation = -1;
5907
- j.upperTranslation = 1;
5923
+ j.enableLimit = false;
5908
5924
  j.enableMotor = true;
5909
- j.maxMotorForce = 50;
5925
+ j.maxMotorForce = 10;
5910
5926
  j.motorSpeed = 0;
5911
5927
 
5912
5928
  this.jID = b2CreatePrismaticJoint(wID, j);
5913
5929
  jointDict[this.jID.index1] = this;
5914
5930
  }
5915
5931
 
5932
+ _init(j) {
5933
+ let a = this.spriteA,
5934
+ b = this.spriteB;
5935
+
5936
+ j.base.bodyIdA = a.bdID;
5937
+ j.base.bodyIdB = b.bdID;
5938
+
5939
+ // set the anchor at sprite A's position in B's local frame
5940
+ j.base.localFrameB.p = b2Body_GetLocalPoint(b.bdID, scaleTo(a.x, a.y));
5941
+
5942
+ // align the slide axis with the vector from A to B
5943
+ let dx = b.x - a.x;
5944
+ let dy = b.y - a.y;
5945
+ let len = Math.sqrt(dx * dx + dy * dy);
5946
+ let angle = len > 0 ? Math.atan2(dy, dx) : 0;
5947
+
5948
+ let qA = b2Body_GetRotation(a.bdID);
5949
+ let qB = b2Body_GetRotation(b.bdID);
5950
+ j.base.localFrameA.q.SetAngle(angle - qA.GetAngle());
5951
+ j.base.localFrameB.q.SetAngle(angle - qB.GetAngle());
5952
+
5953
+ return j;
5954
+ }
5955
+
5916
5956
  get translation() {
5917
5957
  return Box2D.b2PrismaticJoint_GetTranslation(this.jID) * meterSize;
5918
5958
  }
@@ -5943,6 +5983,21 @@ async function q5playPreSetup(q) {
5943
5983
  max = val[1];
5944
5984
  }
5945
5985
  Box2D.b2PrismaticJoint_SetLimits(this.jID, min / meterSize, max / meterSize);
5986
+ Box2D.b2PrismaticJoint_EnableLimit(this.jID, true);
5987
+ }
5988
+
5989
+ set limits(val) {
5990
+ let min, max;
5991
+ if (typeof val == 'number') {
5992
+ val /= 2;
5993
+ min = -val;
5994
+ max = val;
5995
+ } else {
5996
+ min = val[0];
5997
+ max = val[1];
5998
+ }
5999
+ Box2D.b2PrismaticJoint_SetLimits(this.jID, min / meterSize, max / meterSize);
6000
+ Box2D.b2PrismaticJoint_EnableLimit(this.jID, true);
5946
6001
  }
5947
6002
 
5948
6003
  get springEnabled() {
@@ -5953,10 +6008,10 @@ async function q5playPreSetup(q) {
5953
6008
  }
5954
6009
 
5955
6010
  get springiness() {
5956
- return Box2D.b2PrismaticJoint_GetSpringHertz(this.jID);
6011
+ return this._springiness;
5957
6012
  }
5958
6013
  set springiness(val) {
5959
- val = this._springMap ? this._springMap(val) : val;
6014
+ val = this._springMap(val);
5960
6015
  Box2D.b2PrismaticJoint_SetSpringHertz(this.jID, val);
5961
6016
  }
5962
6017
 
@@ -5979,6 +6034,7 @@ async function q5playPreSetup(q) {
5979
6034
  }
5980
6035
  set speed(val) {
5981
6036
  Box2D.b2PrismaticJoint_SetMotorSpeed(this.jID, val);
6037
+ b2Joint_WakeBodies(this.jID);
5982
6038
  }
5983
6039
 
5984
6040
  get maxPower() {
@@ -5992,14 +6048,14 @@ async function q5playPreSetup(q) {
5992
6048
  return Box2D.b2PrismaticJoint_GetMotorForce(this.jID);
5993
6049
  }
5994
6050
 
5995
- // get energy() {
5996
- // return Box2D.b2PrismaticJoint_GetSpeed(this.jID);
5997
- // }
6051
+ get energy() {
6052
+ return Box2D.b2PrismaticJoint_GetSpeed(this.jID);
6053
+ }
5998
6054
  };
5999
6055
 
6000
6056
  $.GrabberJoint = class extends $.Joint {
6001
- constructor(pointer, sprite) {
6002
- sprite ??= pointer;
6057
+ constructor(grabPoint, sprite) {
6058
+ sprite ??= grabPoint;
6003
6059
  super(sprite, sprite, 'grabber');
6004
6060
 
6005
6061
  let bd = b2DefaultBodyDef();
@@ -6025,11 +6081,11 @@ async function q5playPreSetup(q) {
6025
6081
 
6026
6082
  this.jID = b2CreateMotorJoint(wID, j);
6027
6083
 
6028
- let offX = sprite.x - (pointer[0] || pointer.x),
6029
- offY = sprite.y - (pointer[1] || pointer.y);
6084
+ let offX = sprite.x - (grabPoint[0] || grabPoint.x),
6085
+ offY = sprite.y - (grabPoint[1] || grabPoint.y);
6030
6086
  if (!isSlop(offX) || !isSlop(offY)) {
6031
6087
  this._setOffsetB(-offX, -offY);
6032
- this.target = pointer;
6088
+ this.target = grabPoint;
6033
6089
  }
6034
6090
 
6035
6091
  this.sprite = sprite;
@@ -7800,7 +7856,7 @@ async function q5playPreSetup(q) {
7800
7856
  s._vel._magCached = false;
7801
7857
 
7802
7858
  if (s._hasImagery || s._userDefinedDraw) {
7803
- s._rotation = Math.atan2(data[2], data[3]) * $._RADTODEG;
7859
+ s._rotation = Math.atan2(data[2], data[3]) * RADTODEG;
7804
7860
  }
7805
7861
 
7806
7862
  if (s.debug || (!s._hasImagery && !s._userDefinedDraw)) {