Javascript 矢量,以最大速度计算移动力

Javascript 矢量,以最大速度计算移动力,javascript,math,vector,game-physics,Javascript,Math,Vector,Game Physics,我正在制作一个小型的太空射击游戏。当涉及到空间物理学时,我曾在一道数学题上犯过错误 用文字描述如下: 有一个最大速度。 因此,如果你全速前进,你的飞船将在屏幕上一次又一次地移动,就像旧的小行星游戏一样。 如果然后释放火箭助推,你的飞船应该在屏幕上以这个速度继续移动 然后是我现在遇到的棘手问题 如果你将船旋转任意角度,并再次提供动力,那么船应该尝试向这个方向移动,并且在移动速度方面永远不要超过最大速度。所以我的问题是。有人对这个问题有好的想法吗?如果你知道要找什么,感觉就像以前做过一样。:) 我将

我正在制作一个小型的太空射击游戏。当涉及到空间物理学时,我曾在一道数学题上犯过错误

用文字描述如下: 有一个最大速度。 因此,如果你全速前进,你的飞船将在屏幕上一次又一次地移动,就像旧的小行星游戏一样。 如果然后释放火箭助推,你的飞船应该在屏幕上以这个速度继续移动

然后是我现在遇到的棘手问题

如果你将船旋转任意角度,并再次提供动力,那么船应该尝试向这个方向移动,并且在移动速度方面永远不要超过最大速度。所以我的问题是。有人对这个问题有好的想法吗?如果你知道要找什么,感觉就像以前做过一样。:)

我将添加这张小图来说明如何使用一些向量计算。

红环:最高速度

绿线:当前船舶方向

黑线:方向和船在x和y方向的移动速度

黑环:运动的起源

可以说明这一点,但很难找到一个好的数学解决方案。:)

编辑

这是我现在在每一帧中使用的代码。它使飞船移动,但不提供移动的力量。用户必须用火箭助推器作出反作用,使飞船停止或减速。这样,当你释放飞船的加速速度时,它就会停止

    //Calculates ship movement rules
var shipVelocityVec = GetVectorPosByAngle(shipMoveSpeed, shipRotationAngle);
var shipUnitVec =$V([Math.cos(shipRotationAngle),Math.sin(shipRotationAngle),0]);
var rawAccel = shipAccelSpeed / shipMass;
var scale = (shipUnitVec.dot(shipVelocityVec))/(shipTopSpeed * shipTopSpeed);
var v1 = shipUnitVec.subtract(shipVelocityVec.multiply(scale));
var finalAccelVec = v1.multiply(rawAccel);
console.log(finalAccelVec);

//move ship according to rules
var shipPosVector = $V([shipxPos, shipyPos, 0]);
var movementVector =  shipPosVector.add(finalAccelVec);
shipxPos = movementVector.elements[0];
shipyPos = movementVector.elements[1];
function CalcShipMovement() {
//Calculates ship movement rules
shipPosVector = $V([shipxPos, shipyPos, 0]);
var shipVelocityVec = GetVectorPosByAngle(shipAccelSpeed, shipRotationAngle);
var shipUnitVec = $V([Math.cos(shipRotationAngle), Math.sin(shipRotationAngle), 0]);

if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) > 0) {
    var nextMove = currentShipMoveVector.add(shipVelocityVec);
    var nextSpeed = Get2DVectorLength(nextMove);
    //check if topspeed of movement should be changed
    if(nextSpeed > shipTopSpeed) {
        var scale = nextSpeed / shipTopSpeed;
        currentShipMoveVector = DevideVector(nextSpeed, scale);
    } else {
        currentShipMoveVector = currentShipMoveVector.add(shipVelocityVec);
    }
}
if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) == 0) {
    currentShipMoveVector = currentShipMoveVector.add(shipVelocityVec);
}}
要提供加速速度,用户必须按住按钮。当用户松开按钮时,加速度被设置为零,并且必须再次增压以提供最大加速度油门


找到解决方案在这里发布了它是如何完成的。

您似乎混淆了一些事情-如果正确使用矢量,即使加速度处于不同角度,将速度限制为最大速度也没有问题

您的设置应如下所示:

  • 你的船应该有位置,速度和加速度。其中每一个都可以表示为二维向量(具有单独的
    x
    y
    分量)
  • 每帧,将速度添加到位置,将加速度添加到速度
  • 在每一帧中,检查图像是否不超过某个最大值。如果是,则用速度矢量限制速度,并将其乘以最大速度

  • 就这样!没有特殊的情况要考虑——这就是向量代数的魔力! 你可以使用一些实际的物理原理,施加一个阻力,而不仅仅是施加一个特别的最大速度。这将是作用在宇宙飞船上的一个额外的力,方向与速度矢量相反。对于阻力的大小,最简单的方法是将其与速度矢量成比例

    总体效果是,随着宇宙飞船移动速度的加快,阻力增大,当飞船移动速度加快时,在运动方向上加速变得更加困难。当加速度与运动方向相反时,它也会使加速度变得更容易


    这与你的描述有一点不同,那就是宇宙飞船不会永远以最大速度飞行,它会减速。然而,它不会停止,因为阻力随着船的减速而下降。这和我对小行星的记忆比那艘永远以恒定速度航行的飞船更吻合,但我已经玩了很久了

    @BlueRaja的解决方案应该是可行的,尽管当你达到最高速度时,你的行为会突然改变

    如果你想要一个没有“接缝”的解决方案,我相信你可以通过对加速度进行适当的调整来实现你想要的,如下所示:

    ship_unit_vec = [cos(ship_angle), sin(ship_angle)]
    raw_accel = (engine_thrust / ship_mass)
    
    scale = dot_product(ship_unit_vec, ship_velocity_vec) / max_speed^2
    
    final_accel_vec = raw_accel * (ship_unit_vec - scale * ship_velocity_vec)
    
    注:


    • 如果
      | ship|u velocity|vec |我做到了!谢谢您的帮助。

      终于找到了解决办法。问题是,我试图在速度方面修改船舶的当前运动,然后计算“阻力”,当用户尝试转向另一个方向时,该阻力将是该运动的产物。这个解决方案就像提到的@BlueRaja和@Comingstorm一样。当涉及到运动时,所有的力都应该加在一起。这应该是改变船舶位置的原因。不应添加到船舶当前移动中。你可能会影响当前的运动,但你必须以不同的方式来做。所以我想我可以分享我的解决方案

      每次用户加速船舶时,都会运行此功能

          //Calculates ship movement rules
      var shipVelocityVec = GetVectorPosByAngle(shipMoveSpeed, shipRotationAngle);
      var shipUnitVec =$V([Math.cos(shipRotationAngle),Math.sin(shipRotationAngle),0]);
      var rawAccel = shipAccelSpeed / shipMass;
      var scale = (shipUnitVec.dot(shipVelocityVec))/(shipTopSpeed * shipTopSpeed);
      var v1 = shipUnitVec.subtract(shipVelocityVec.multiply(scale));
      var finalAccelVec = v1.multiply(rawAccel);
      console.log(finalAccelVec);
      
      //move ship according to rules
      var shipPosVector = $V([shipxPos, shipyPos, 0]);
      var movementVector =  shipPosVector.add(finalAccelVec);
      shipxPos = movementVector.elements[0];
      shipyPos = movementVector.elements[1];
      
      function CalcShipMovement() {
      //Calculates ship movement rules
      shipPosVector = $V([shipxPos, shipyPos, 0]);
      var shipVelocityVec = GetVectorPosByAngle(shipAccelSpeed, shipRotationAngle);
      var shipUnitVec = $V([Math.cos(shipRotationAngle), Math.sin(shipRotationAngle), 0]);
      
      if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) > 0) {
          var nextMove = currentShipMoveVector.add(shipVelocityVec);
          var nextSpeed = Get2DVectorLength(nextMove);
          //check if topspeed of movement should be changed
          if(nextSpeed > shipTopSpeed) {
              var scale = nextSpeed / shipTopSpeed;
              currentShipMoveVector = DevideVector(nextSpeed, scale);
          } else {
              currentShipMoveVector = currentShipMoveVector.add(shipVelocityVec);
          }
      }
      if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) == 0) {
          currentShipMoveVector = currentShipMoveVector.add(shipVelocityVec);
      }}
      
      该代码在每一帧中运行,生成船舶的图形以改变其位置

      function SetShipMovement() {
      if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) > 0) {
          shipMoveSpeed = Get2DVectorLength(currentShipMoveVector);
          shipPosVector = shipPosVector.add(currentShipMoveVector);
          shipxPos = shipPosVector.elements[0];
          shipyPos = shipPosVector.elements[1];
          //Makes the ship slow down if no acceleration is done for the ship
          if(shipAccelSpeed == 0) {
              currentShipMoveVector = currentShipMoveVector.subtract(DevideVector(currentShipMoveVector, 50));
          }
      } else {
          currentShipMoveVector = $V([0, 0, 0]);
      }}
      

      我想这是2d的东西吧?保持单独的x和y速度指示器。如果你以某个角度推进,将该角度的推力分解为x和y分量,允许你分别调整飞船的x/y速度分量。在每次速度调整时,检查船的速度,如果达到最大值,停止调整。请纠正我的误解,但在图#3中,速度的组合向量不是大于红环允许的吗?不是,因为x和y加在一起等于圆圈的最大运动。绿线可能更长。在#3中,绿线应该是圆直径的全长。分离X和Y运动不是一个坏主意+1在用你的问题绘制图表时,添加一个与位置的速度成比例的量,与速度的加速度成比例。@Michael:这取决于单位(像素/秒vs.像素/帧)。:)不是真的。除非你的帧在时间上都是均匀分布的,否则你无法将常数吸收到单位中。这是一个微积分问题,是关于积分的问题,不是加法的问题。我想我实际上必须使用Michaels的概念,因为这里应该有一个力,来自于前面的动作,它必须被处理,以得到trav的最终方向