基于物理的 2D 运动:随时间改变物体的方向

Physics based 2D movement: Changing direction of an object over time

我目前正在 Java 中创建一个 2D space 游戏,你可以在 space 中控制一艘船。 游戏不使用任何外部库。

飞船应该向光标移动。但是,当移动光标时,旧势力并没有神奇地消失;随着时间的推移,这艘船改变了它的航向,最终朝着期望的方向移动。

但是,我 运行 遇到了关于船舶移动的问题。 基本上,我想要实现的是这张图片粗略地说明:

图像显示了在一个游戏刻度内飞船应该如何移动。 进一步解释:

现在我已经解释了我想要实现的目标,现在我将描述我到目前为止已经实现的目标以及它是如何工作的。

基本上,"ship" 是一个位于屏幕中央的图像。当你 "move" 船时,船留在原地;移动的是游戏区的其余部分。

飞船当前"position"相对于代表游玩区域的坐标系为整数xPos和yPos

现在看一些示例代码,说明系统如何工作:

 int xPos;
 int yPos;

 public void updateMovement() {
     xPos += xSpeed;
     yPos += ySpeed; 
 }

 public void moveForward() {
     double yTempSpeed = ySpeed;
     double xTempSpeed = xSpeed;
     yTempSpeed += 0.01 * Math.sin(Math.toRadians(targetAngle));
     xTempSpeed += 0.01 * Math.cos(Math.toRadians(targetAngle));
     double resultVector = Math.sqrt(xTempSpeed * xTempSpeed + yTempSpeed * yTempSpeed);
     if (resultVector < 2) {
         ySpeed += 0.01 * Math.sin(Math.toRadians(targetAngle));
         xSpeed += 0.01 * Math.cos(Math.toRadians(targetAngle));
 }

此代码成功将船舶的最大速度设置为所需值,但是,如果结果 "vector" 大于 2,即,这不起作用(船舶的航向不会改变),即当速度已经达到最大值并且 targetAngle 太接近船只当前行驶的角度时 (+- Pi / 2)。

我将如何根据此实现更改当前角度?

  public void moveForward() {
     ySpeed += 0.01 * Math.sin(Math.toRadians(targetAngle));
     xSpeed += 0.01 * Math.cos(Math.toRadians(targetAngle));
     double currentSpeed = Math.sqrt(xTempSpeed * xTempSpeed + yTempSpeed * yTempSpeed);
     if (currentSpeed > maxSpeed) {
         //the resulting speed is allways <= maxspeed (normed to that)
         ySpeed *= maxSpeed/currentSpeed;
         xSpeed *= maxSpeed/currentSpeed;
 }

希望这就是您所需要的...虽然这很不现实,但航天器具有最大速度,但就 "playability" 而言,我也会这样做。

如何使船速正常化,而不是让它实际超过您的速度限制 (=2):

//it's good to put all constants out of a function in one place
//to make it easier if you ever wanted to change it
private final int MAX_SPEED = 2;
private final double ACCEL_FACTOR = 0.01;

public void moveForward() {
 ySpeed += ACCEL_FACTOR * Math.sin(Math.toRadians(targetAngle));
 xSpeed += ACCEL_FACTOR * Math.cos(Math.toRadians(targetAngle));

 //normalize ship speed, i.e. preserve ratio of xSpeed/ySpeed
 //but make sure that xSpeed^2 + ySpeed^2 <= MAX_SPEED^2

 //your code goes here
 //...

}

阅读有关向量归一化的内容。这样,船速的变化将正常应用(此时速度可以>=MAX_SPEED),但在归一化后它永远不会大于MAX_SPEED,所以你的 if 甚至不需要指令。

您可能会发现以下 (Swift) 代码很有用,尽管您需要自己处理飞船线性速度和 angular 速度的每帧积分:

func moveShipTowards(location: CGPoint) {
    if let ship = shipNode? {

        let distanceVector = CGVector(origin: ship.position, point: location)
        let targetAngle = distanceVector.angle
        let shipAngle = ship.zRotation
        var dø = targetAngle - shipAngle

        // convert to shortest arc
        if dø > π {
            dø -= 2.0 * π
        } else if dø < -π {
            dø += 2.0 * π
        }

        // resulting angular velocity
        ship.physicsBody.angularVelocity = 12 * dø.clampedTo(π)

        var velocityUnitVector = CGVector(cosf(ship.zRotation), sinf(ship.zRotation))
        var magnitude = distanceVector.length.clampedTo(400)

        ship.physicsBody.velocity = velocityUnitVector * magnitude
    }
}

它处理让飞船在接近目标点时减速。刚才看了一下,不过似乎没有正确处理加速。