确定我的对象在 2D 平面上朝向哪个方向
本文关键字:方向 平面 我的 对象 2D | 更新日期: 2023-09-27 17:56:32
我和我的朋友在XNA 4.0中胡闹,制作2D赛车游戏。有点像这个:伊万"钢铁侠"斯图尔特的超级越野。我们遇到的问题是知道汽车朝哪个方向适当地移动它。我们可以通过枚举值北、南、东、西来跟踪方向,但由于多种原因,我们不想这样做。
我们想知道是否有办法通过数学来实现这一点。也许通过在汽车引擎盖上指定一个锚点,让汽车始终向该位置移动,然后移动该锚点。我们不确定。或者也许有一种方法可以使用 2D 矢量。
我想既然我们遇到了困难,我们应该向编码社区寻求帮助!
只是为了清楚。我不是在找代码;我只想讨论一些 2D 在所有方向上移动的概念,而不必跟踪方向枚举。我知道这不可能是唯一的方法。
汽车物理学实际上是一门非常困难的学科。我祝你一切顺利,但你正在开始一个艰难的追求。
至于答案:您可以将方向角存储在弧度中,并使用 atan2 函数获取角度之间的关系。
或者你可以使用Vector2D并使用矢量数学来确定角度,atan2也将是你的朋友。
我关于这个问题的代码片段:
public class RotatingImage implements RotatingImageVO {
protected double x, y; // center position
protected double facingx, facingy;
protected double angle;
protected void calculateAngle() {
angle = Math.atan2(x-facingx, facingy-y);
}
}
请记住,计算 atan2 是昂贵的。当我为每个对象的每次绘制迭代执行此操作时(塔防,塔在旋转;它占用了我~30%的计算能力。仅当您检测到明显的角度变化时才执行此操作。喜欢这个:
public void setFacingPoint(double facingx, double facingy) {
if (Math.abs((facingx-this.facingx)/(facingx+this.facingx)) > 0.002
|| Math.abs((facingy-this.facingy)/(facingy+this.facingy)) > 0.002) {
this.facingx = facingx;
this.facingy = facingy;
calculateAngle();
}
}
您可以使用规范化向量来表示方向。这只是一个硬编码示例,但您可以轻松使用游戏手柄操纵杆的输入。
Vector2 north = new Vector2(0, -1);
稍后在你的代码中像这样移动你的精灵(假设有一个位置向量)。
float speed = 100; // 100 pixels per second.
Vector2 direction = north;
position += direction * ((float)gameTime.ElapsedGameTime.TotalSeconds * speed);
使用单位向量描述方向,使用点描述位置是有意义的。然后当汽车向前移动时,你这样做
currentPosition = currentPosition + distance * directionvector;
//(伪代码)
更改方向时,最好使用矩阵来(旋转)变换方向矢量。
(我不熟悉XNA)
编写了一些虚拟代码来说明:
[Test]
public void MoveForwardTest()
{
var position = new Point(0, 0);
var direction = new Vector(1, 0);
double distance = 5;
//Update position moving forward distance along direction
position = position + distance * direction;
Assert.AreEqual(5.0, position.X, 1e-3);
Assert.AreEqual(0, position.Y, 1e-3);
}
[Test]
public void RotateThenMoveTest()
{
var position = new Point(0, 0);
var direction = new Vector(1, 0);
double distance = 5;
//Create the rotation matrix
var rotateTransform = new RotateTransform(90);
//Apply the rotation to the direction
direction = Vector.Multiply(direction, rotateTransform.Value);
//Update position moving forward distance along direction
position = position + distance * direction;
Assert.AreEqual(0, position.X, 1e-3);
Assert.AreEqual(5.0, position.Y, 1e-3);
}
[Test]
public void CheckIfOtherCarIsInfrontTest()
{
var position = new Point(0, 0);
var direction = new Vector(1, 0);
var otherCarPosition = new Point(1, 0);
//Create a vector from current car to other car
Vector vectorTo = Point.Subtract(otherCarPosition, position);
//If the dotproduct is > 0 the other car is in front
Assert.IsTrue(Vector.Multiply(direction, vectorTo) > 0);
}
[Test]
public void AngleToNortTest()
{
var direction = new Vector(1, 0);
var northDirection = new Vector(0, 1);
Assert.AreEqual(90, Vector.AngleBetween(direction, northDirection), 1e-3);
}