在小行星类型游戏中正确运动

目前我有一些小行星游戏,可以在这里看到:

但是当用户在船仍然移动时按下W时,它将采取船舶移动的速度而不管其旋转并加到它上,导致船出现不稳定且不协调(很难解释,观看该video)。

这是我正在使用的代码:

public void update(int delta) throws SlickException { float hip = speed * delta; float rotation = image.getRotation(); for (Bullet b : bulletList) { b.update(delta); } Input input = gc.getInput(); if (input.isKeyDown(Input.KEY_A)) { image.rotate(rotateLeftSpeed * delta); if (rotateLeftSpeed > (ROTATE_LIMIT * -1)) { rotateLeftSpeed -= rotateSpeed; } } else { if (rotateLeftSpeed < 0) { image.rotate(rotateLeftSpeed * delta); rotateLeftSpeed += rotateSpeed; } } if (input.isKeyDown(Input.KEY_D)) { image.rotate(rotateRightSpeed * delta); if (rotateRightSpeed  0) { image.rotate(rotateRightSpeed * delta); rotateRightSpeed -= rotateSpeed; } } if (input.isKeyDown(Input.KEY_W)) { hip = speed * delta; protation = image.getRotation(); rotation = image.getRotation(); x += hip * Math.sin(Math.toRadians(rotation)); y -= hip * Math.cos(Math.toRadians(rotation)); if (speed  0) { System.out.println(offSpeed); srotation = image.getRotation(); hip = speed * delta; x += hip * Math.sin(Math.toRadians(protation)); y -= hip * Math.cos(Math.toRadians(protation)); speed -= 0.003f; } } 

无论如何我可以在不引入dx和dy值的情况下完成此操作吗? 尽可能减少修改?

问题很明显,即使你面向一个方向,但这并不意味着当你打开推进器时你会那个方向移动

你需要第二个内部方向向量,当你的推进器开启时,它会更新,很可能是通过简单的向量加法和随后的标准化。 然后您可以使用方向计算将力施加到船上的方向。

最后,我使用了这个:

 if (input.isKeyDown(Input.KEY_W)) { dx += Math.sin(Math.toRadians(image.getRotation())) * delta * 0.01; dy += -Math.cos(Math.toRadians(image.getRotation())) * delta * 0.01; } x += dx; y += dy; dx *= 0.98; dy *= 0.98; 

根据dxdy (而不是速度和角度)跟踪玩家的动作,并在按下W时添加到这些值。

我认为问题是你正在加入从W直接按X,Y坐标的冲动。 你需要做的是有一个带X,Y坐标的速度矢量,并在用户推力时加上它。

在每个时间步上,您将x速度和y速度分量添加到X,Y坐标。

基础物理学是你有位置(x,y),速度(dx / dt,dy / dt)和加速度(dx ^ 2 / dt,dy ^ 2 / dt)。 推力提供加速度,您必须随着时间的推移积分以提供速度,然后随着时间的推移积分以提供位置。

物理学中有两个“概念”需要实现:速度和摩擦力。

这是2D中的一个简单示例。 您还可以使用包装类将x / y变量组合到单个对象中,并提供方便的方法来更改其内容。

每个对象都需要有一个位置和一个速度变量。 我们还需要摩擦力,这是每种材料的常数(因为您的物体可能总是以相同的材料行进,我们只是模拟摩擦力是恒定的)。 在这个简单的模拟中,当摩擦力达到1时,摩擦力变弱。这意味着在摩擦力= 1时你没有摩擦力,在摩擦力为0时你的物体会立即停止:

 public class PhysicsObject{ public static final double FRICTION = 0.99; private double posX; private double posY; private double speedX = 0; private double speedY = 0; public PhysicsObject(double posX, double posY){ this.posX = posX; this.posY = posY; } public void accelerate(double accelerationX, double accelerationY){ speedX += accelerationX; speedY += accelerationY; } public void update(){ posX += speedX; posY += speedY; speedX *= FRICTION; speedY *= FRICTION; } public double getPosX(){ return posX; } public double getPosY(){ return posY; } } 

请注意,您的对象具有更新方法。 需要定期在场景中的所有对象上调用此方法,以应用移动。 在这种方法中你也可以处理碰撞检测,敌人可以做他们的AI逻辑。