Javascript 矢量,以最大速度计算移动力
我正在制作一个小型的太空射击游戏。当涉及到空间物理学时,我曾在一道数学题上犯过错误 用文字描述如下: 有一个最大速度。 因此,如果你全速前进,你的飞船将在屏幕上一次又一次地移动,就像旧的小行星游戏一样。 如果然后释放火箭助推,你的飞船应该在屏幕上以这个速度继续移动 然后是我现在遇到的棘手问题 如果你将船旋转任意角度,并再次提供动力,那么船应该尝试向这个方向移动,并且在移动速度方面永远不要超过最大速度。所以我的问题是。有人对这个问题有好的想法吗?如果你知道要找什么,感觉就像以前做过一样。:) 我将添加这张小图来说明如何使用一些向量计算。 红环:最高速度 绿线:当前船舶方向 黑线:方向和船在x和y方向的移动速度 黑环:运动的起源 可以说明这一点,但很难找到一个好的数学解决方案。:) 编辑 这是我现在在每一帧中使用的代码。它使飞船移动,但不提供移动的力量。用户必须用火箭助推器作出反作用,使飞船停止或减速。这样,当你释放飞船的加速速度时,它就会停止Javascript 矢量,以最大速度计算移动力,javascript,math,vector,game-physics,Javascript,Math,Vector,Game Physics,我正在制作一个小型的太空射击游戏。当涉及到空间物理学时,我曾在一道数学题上犯过错误 用文字描述如下: 有一个最大速度。 因此,如果你全速前进,你的飞船将在屏幕上一次又一次地移动,就像旧的小行星游戏一样。 如果然后释放火箭助推,你的飞船应该在屏幕上以这个速度继续移动 然后是我现在遇到的棘手问题 如果你将船旋转任意角度,并再次提供动力,那么船应该尝试向这个方向移动,并且在移动速度方面永远不要超过最大速度。所以我的问题是。有人对这个问题有好的想法吗?如果你知道要找什么,感觉就像以前做过一样。:) 我将
//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的最终方向