我现在已经在自上而下的汽车游戏中工作了很长一段时间,似乎它总能回归到能够正确地完成一件事情。在我的实例中,它正确地完成了我的汽车物理。
我遇到的问题是我的当前轮换没有得到妥善处理。我知道问题在于我的幅度为0,同时乘以Math.cos / sin方向,但我根本不知道如何解决它。
这是当前的基础代码。
private void move(int deltaTime) {
double secondsElapsed = (deltaTime / 1000.0);// seconds since last update
double speed = velocity.magnitude();
double magnitude = 0;
if (up)
magnitude = 100.0;
if (down)
magnitude = -100.0;
if (right)
direction += rotationSpeed * (speed/topspeed);// * secondsElapsed;
if (left)
direction -= rotationSpeed * (speed/topspeed);// * secondsElapsed;
double dir = Math.toRadians(direction - 90);
acceleration = new Vector2D(magnitude * Math.cos(dir), magnitude * Math.sin(dir));
Vector2D deltaA = acceleration.scale(secondsElapsed);
velocity = velocity.add(deltaA);
if (speed < 1.5 && speed != 0)
velocity.setLength(0);
Vector2D deltaP = velocity.scale(secondsElapsed);
position = position.add(deltaP);
...
}
我的矢量类模拟矢量基础知识 - 包括加法减法,乘以标量......等等。
重新迭代潜在问题 - 当幅度为0时,幅度* Math.cos(dir)= 0,因此当玩家只按右箭头键或左箭头键时没有“加速”方向不会改变。
如果有人需要更多信息,您可以在
找到它答案 0 :(得分:6)
是的,那些物理计算都混淆了。根本问题在于,正如您所知,将加速度乘以方向是错误的。这是因为你的“方向”不仅仅是汽车加速的方向;这是汽车行驶的方向。
最简单的解决方法是首先分别考虑加速度和转向。首先,加速:为此,你只有一个速度,你有“向上”和“向下”键。为此,代码看起来像这样(包括将接近零速度降低到零的阈值代码):
if (up)
acceleration = 100.0;
if (down)
acceleration = -100.0;
speed += acceleration * secondsElapsed;
if (abs(speed) < 1.5) speed = 0;
另外,你有转向,它会改变汽车运动的方向 - 也就是说,它会改变你乘以速度的单位矢量来获得速度。我也冒昧地修改你的变量名称,看起来更像代码的加速部分,并澄清它们的含义。
if (right)
rotationRate = maxRotationSpeed * (speed/topspeed);
if (left)
rotationRate = maxRotationSpeed * (speed/topspeed);
direction += rotationRate * secondsElapsed;
double dir = Math.toRadians(direction - 90);
velocity = new Vector2D(speed * Math.cos(dir), speed * Math.sin(dir));
您可以使用第二部分速度计算中第一部分的速度简单地组合这两个部分,以获得完整的简单加速和转向模拟。
答案 1 :(得分:1)
由于你问加速度是一个向量,这里有一个替代解决方案可以用这种方式计算。
首先,给定速度(Vector2D
值),假设您可以从中计算方向。我不知道你的语法,所以这里有一个概述:
double forwardDirection = Math.toDegrees(velocity.direction()) + 90;
这是汽车指向的方向。 (汽车总是指向它们的速度方向。)
然后,我们得到加速的组件。首先,加速的前后部分非常简单:
double forwardAcceleration = 0;
if (up)
forwardAcceleration = 100;
if (down)
forwardAcceleration = -100;
由于转向引起的加速度稍微复杂一些。如果你在一个圆圈中走动,朝向该圆心的加速度的大小等于速度平方除以圆的半径。并且,如果你向左转,加速度在左边;如果你正确驾驶,它就在右边。所以:
double speed = velocity.magnitude();
double leftAcceleration = 0;
if (right)
leftAcceleration = ((speed * speed) / turningRadius);
if (left)
leftAcceleration = -((speed * speed) / turningRadius);
现在,您有一个forwardAcceleration
值,其中包含正向加速度(向后为负)和leftAcceleration
值,其中包含向左方向的加速度(向右为负)。让我们将其转换为加速度向量。
首先,我们使用一些额外的方向变量来制作单位向量(主要是为了使代码易于解释):
double leftDirection = forwardDirection + 90;
double fDir = Math.toRadians(forwardDirection - 90);
double ldir = Math.toRadians(leftDirection - 90);
Vector2D forwardUnitVector = new Vector2D(Math.cos(fDir), Math.sin(fDir));
Vector2D leftUnitVector = new Vector2D(Math.cos(lDir), Math.sin(lDir));
然后,您可以通过组合前向和左向片段来创建加速度矢量,如下所示:
Vector2D acceleration = forwardUnitVector.scale(forwardAcceleration);
acceleration = acceleration.add(leftUnitVector.scale(leftAcceleration));
好的,这就是你的加速度。您可以将其转换为速度变化(请注意,正确的术语是deltaV
,而不是deltaA
):
Vector2D deltaV = acceleration.scale(secondsElapsed);
velocity = velocity.add(deltaV).
最后,您可能想知道汽车的方向(为了在屏幕上绘制它),所以您可以从新的速度计算:
double forwardDirection = Math.toDegrees(velocity.direction()) + 90;
你有它 - 用加速度作为矢量进行物理计算,而不是使用与汽车一起旋转的一维速度。
(这个版本更接近你最初想要做的事情,所以让我分析一下你出错的地方。来自上/下的加速部分始终是指向方向的方向汽车是指向的;在汽车转弯之前它不会随着转向而转动。同时,转向产生的部分加速度总是纯粹向左或向右,其大小与前/后加速度无关 - 特别是,即使前/后加速度为零,其幅度也可能非零。要获得总加速度矢量,需要分别计算这两个部分并将它们作为矢量相加。)
这些计算都不完全准确。在这一个中,您计算了汽车开始的“前进”和“左”方向,但汽车正在旋转,因此这些方向在时间步长上发生变化。因此,deltaV = acceleration * time
方程只是一个估计值,会产生一个稍微错误的答案。另一个解决方案有类似的不准确性 - 但另一个解决方案更好的原因之一是,在这一个中,小错误意味着如果你左右转向汽车速度会增加,即使你没有触摸“向上”键 - 而在另一个中,这种交叉错误不会发生,因为我们将速度和转向分开。