从 A 减速到 B 减速(数学)XNA
Moving from A to B deceleration (Maths) XNA
在到达最终目的地之前以任何给定值(例如 accelerationDropOff = 1.5f)的速度减速的最佳方法是什么?
public bool MoveFromCurrentToPosition(float x, float y, float velocity, float acceleration, float deltaTime)
{
float startX = positionX, startY = positionY;
float endX = x, endY = y;
float deltaX = endX - startX;
float deltaY = endY - startY;
float speed = velocity;
float elapsed = 0.01f;
// On starting movement
float distance = (float)Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2));
float directionX = deltaX / distance;
float directionY = deltaY / distance;
isMoving = true;
// On update
if (isMoving == true)
{
positionX += directionX * speed * elapsed;
positionY += directionY * speed * elapsed;
if (currentAcceleration == 0)
{
currentAcceleration = acceleration;
}
else if (currentAcceleration >= maxAcceleration) // <- Don't accelerate anymore
{
speed *= currentAcceleration;
positionX += (directionX * speed) * deltaTime; positionY += (directionY * speed) * deltaTime;
bounds.X = (int)positionX; bounds.Y = (int)positionY;
}
else
{
currentAcceleration += acceleration;
speed *= currentAcceleration;
positionX += (directionX * speed) * deltaTime; positionY += (directionY * speed) * deltaTime;
bounds.X = (int)positionX; bounds.Y = (int)positionY;
}
float a = x, o = y;
double angle = Math.Atan2(o, a);
angle = angle * 180 / Math.PI;
movementDirection = (float)(180 - angle);
// Decelerate before reaching the end point
if (Math.Sqrt(Math.Pow(positionX - startX, 2) + Math.Pow(positionY - startY, 2)) >= distance)
{
positionX = endX;
positionY = endY;
isMoving = false;
return true;
}
}
return false;
}
我已经在这个问题上停留了一两个小时,Math.exe 没有响应。谁能给我指出正确的方向?
您似乎混淆了速度(速度)和加速度。速度是相对于给定时间范围的位置变化。加速度是相对于给定时间范围的速度变化。对于恒定加速度,位置和速度变化如下:
v1 = v0 + a * t
x1 = x0 + v0 * t + 1/2 * a * t^2
v0
、v1
和x0
、x1
分别是时间帧开始和结束的速度和位置,a
是加速度,t
是时间帧长度。如果您假设在时间范围内持续加速,这就是精确的公式。通常,您会发现类似下面的近似值,它们会引入一些积分错误:
v1 = v0 + a * t
x1 = x0 + v1 * t
我建议使用准确的公式。
据我了解你的问题,你想要找到一个加速度,使得以初始速度 v0
移动的物体在行进 d
个长度单位后停止。
这为您提供了以下等式:
0 = v0 + a * t //target velocity of 0
d = 0 + v0 * t + 1/2 * a * t^2 //travel distance of d
解决方法是:
a = -1/2 * v0^2 / d
此动作所需时间为:
t = 2 * d / v0
所以在减速运动开始时计算一次加速度,然后用上面的公式更新当前位置和速度。
对您的代码的一些额外提示:
如果要对变量 x
求平方,请使用 x * x
而不是 Math.pow(x, 2)
。它更易于阅读并且具有更好的性能。
如果您已经在使用 XNA,请使用它的 Vector2
结构。这使很多事情变得容易得多。您可以只添加两个向量,而不需要分别关心每个组件。有获取向量长度的方法,等等。
在到达最终目的地之前以任何给定值(例如 accelerationDropOff = 1.5f)的速度减速的最佳方法是什么?
public bool MoveFromCurrentToPosition(float x, float y, float velocity, float acceleration, float deltaTime)
{
float startX = positionX, startY = positionY;
float endX = x, endY = y;
float deltaX = endX - startX;
float deltaY = endY - startY;
float speed = velocity;
float elapsed = 0.01f;
// On starting movement
float distance = (float)Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2));
float directionX = deltaX / distance;
float directionY = deltaY / distance;
isMoving = true;
// On update
if (isMoving == true)
{
positionX += directionX * speed * elapsed;
positionY += directionY * speed * elapsed;
if (currentAcceleration == 0)
{
currentAcceleration = acceleration;
}
else if (currentAcceleration >= maxAcceleration) // <- Don't accelerate anymore
{
speed *= currentAcceleration;
positionX += (directionX * speed) * deltaTime; positionY += (directionY * speed) * deltaTime;
bounds.X = (int)positionX; bounds.Y = (int)positionY;
}
else
{
currentAcceleration += acceleration;
speed *= currentAcceleration;
positionX += (directionX * speed) * deltaTime; positionY += (directionY * speed) * deltaTime;
bounds.X = (int)positionX; bounds.Y = (int)positionY;
}
float a = x, o = y;
double angle = Math.Atan2(o, a);
angle = angle * 180 / Math.PI;
movementDirection = (float)(180 - angle);
// Decelerate before reaching the end point
if (Math.Sqrt(Math.Pow(positionX - startX, 2) + Math.Pow(positionY - startY, 2)) >= distance)
{
positionX = endX;
positionY = endY;
isMoving = false;
return true;
}
}
return false;
}
我已经在这个问题上停留了一两个小时,Math.exe 没有响应。谁能给我指出正确的方向?
您似乎混淆了速度(速度)和加速度。速度是相对于给定时间范围的位置变化。加速度是相对于给定时间范围的速度变化。对于恒定加速度,位置和速度变化如下:
v1 = v0 + a * t
x1 = x0 + v0 * t + 1/2 * a * t^2
v0
、v1
和x0
、x1
分别是时间帧开始和结束的速度和位置,a
是加速度,t
是时间帧长度。如果您假设在时间范围内持续加速,这就是精确的公式。通常,您会发现类似下面的近似值,它们会引入一些积分错误:
v1 = v0 + a * t
x1 = x0 + v1 * t
我建议使用准确的公式。
据我了解你的问题,你想要找到一个加速度,使得以初始速度 v0
移动的物体在行进 d
个长度单位后停止。
这为您提供了以下等式:
0 = v0 + a * t //target velocity of 0
d = 0 + v0 * t + 1/2 * a * t^2 //travel distance of d
解决方法是:
a = -1/2 * v0^2 / d
此动作所需时间为:
t = 2 * d / v0
所以在减速运动开始时计算一次加速度,然后用上面的公式更新当前位置和速度。
对您的代码的一些额外提示:
如果要对变量 x
求平方,请使用 x * x
而不是 Math.pow(x, 2)
。它更易于阅读并且具有更好的性能。
如果您已经在使用 XNA,请使用它的 Vector2
结构。这使很多事情变得容易得多。您可以只添加两个向量,而不需要分别关心每个组件。有获取向量长度的方法,等等。