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

时间:2015-03-05 15:21:41

标签: java math 2d game-physics trigonometry

我目前正在使用Java创建一个2D空间游戏,您可以在其中控制船只,空间。 游戏不使用任何外部库。

该船应该朝向光标移动。然而,当移动光标时,旧力量不会神奇地消失;随着时间的推移,船改变了方向,最终朝着理想的方向前进。

然而,我遇到了关于船舶运动的问题。 基本上,这个图像粗略地说明了我想要实现的目标:

enter image description here

该图像显示了在一场比赛中船舶应该如何移动。 进一步解释:

  • 船的最大速度由圆圈表示。

  • 目标角度是光标当前所在的位置。

  • 当前角度是船舶当前行驶的方向。

  • 当前角度应越来越接近目标角度,直到达到这两个角度相同的点。

  • 船舶应尽可能以最短的路线朝目标角度方向改变方向;它可以左右转动,而不仅仅是左转或右转。

现在我已经解释了我想要实现的目标,现在我将描述我到目前为止所取得的成就及其运作方式。

基本上,“船”是位于屏幕中央的图像。当你“移动”船只时,船就会停留;什么动作是游戏区的其余部分。

船舶相对于代表游戏区域的坐标系的当前“位置”是整数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));
 }

此代码成功地将船舶的最大速度设置为所需的值,但是,如果得到的“矢量”大于2,即速度为时,这不起作用(船舶航线不会改变)已达到它的最大值且targetAngle太靠近船舶当前行驶的角度(+ - Pi / 2)。

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

3 个答案:

答案 0 :(得分:1)

  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;
 }

希望这是你所需要的......虽然这是非常不现实的,但是宇宙飞船具有最大的速度,但是在可玩性方面......我也会这样做。

答案 1 :(得分:0)

如何规范船舶的速度,而不是让它实际超过你的速度限制(= 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 指令不均匀需要的。

答案 2 :(得分:0)

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

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
    }
}

当接近目标点时,它处理船舶减速。刚看它,它似乎没有正确处理加速度。