碰撞后计算物体位置方向

时间:2014-03-20 22:08:00

标签: android game-engine surfaceview game-physics

我正在编写自己的游戏引擎(非常基础),我想了解物理在游戏开发中的运作方式,而不是使用已经构建的游戏引擎。我正在使用Java为Android设备编写代码(使用SurfaceView)。

问题是我不知道如何计算碰撞后我的物体的位置。我创建了自己的碰撞检测,它运行良好。

enter image description here

如您所见,红色矩形是我的球应该移动的区域。箭头显示了碰撞发生后球应该移动的位置。球有不同的位置,标有1 - 11(注意,渲染“世界”时你只看到一个球!)。

球实际上是矩形!但你看不到边缘。

我创建了自己的Game Object类,我保存有关对象位置,速度,原点等的数据:

public abstract class GameObject
{
    public Vector2 dimension;
    public Vector2 position;
    public Vector2 velocity;
    public Vector2 origin;

    public Rectangle rectangle;

    public GameObject(Resources resources)
    {
        this.dimension = new Vector2();
        this.position = new Vector2();
        this.velocity = new Vector2();
        this.origin = new Vector2();

        this.rectangle = new Rectangle();
    }

    public void update(float deltaTime)
    {
        position.x += velocity.x;
        position.y += velocity.y;

        rectangle.set(position.x, position.y, dimension.x, dimension.y);

        origin.x = position.x + dimension.x / 2;
        origin.y = position.y + dimension.y / 2;
    }
}

如果球与其中一个红色矩形边距碰撞,则调用此方法:

protected void onBallCollideWithLevelEdge(Ball ball)
{
   // Calculate next position:
   ??????????
}

我的球有速度和位置。我应该保存球的先前位置吗?

2 个答案:

答案 0 :(得分:0)

1)为什么你把球表示为矩形?圆圈更容易处理,特别是如果你想将碰撞延伸到球球。

2)如果您正在尝试制作物理引擎,则必须具有所有对象的坐标以及相应的一阶和二阶导数,即速度和加速度。此外,您需要每个物体的质量和一些其他参数,例如材料(用于摩擦)和弹性,但这在开始时不需要。

3)当发生与墙壁的碰撞时,你有当前的球位置和速度。根据这些数据,您必须计算法向力。法向力使得球不能穿过墙壁,所以我用这样的东西来计算它的大小:

Nx = DELTAx*k;
Ny = DELTAy*k;

其中k是一些弹性常数,你可以修剪,x是球在墙上穿透了多少的量度。请注意,这仅适用于“慢”对象。如果你处理子弹,你最好使用像射线或。的东西 另一种方法是计算碰撞时的动能并将其转换为弹性能量。一旦你有弹性能量,你就可以在垂直于墙壁的方向上释放它,将它转化为力。 一旦你获得了力量,它就会通过将其除以质量而变为加速度。

4)在每次模拟迭代中,您将速度添加到位置,加速到速度,记住将其乘以积分时间(dt)。这个时间可以任意设置,它是一个常数。如果你想要100Hz模拟,你可以将dt设置为10ms。您还必须重新计算加速度,即力的总和除以质量。

5)你注意到我从未谈过方向,因为如果你推理分解每个轴(x,y在2D引擎中)的坐标,你就不需要它。如果法向力是“正确”,如在您的示例中,Ny分量将设置为零,而Nx将转换为加速度并将改变水平速度。这也将改变球的方向。

这些只是建议,实际上你应该从研究运动学和后来的理性力学开始。

答案 1 :(得分:0)

我的功能看起来像这样:

位置calculateValidPosition(位置开始,位置结束)     位置middlePoint =(开始+结束)/ 2

if (middlePoint == start || middlePoint == end)
    return start 

if( isColliding(middlePont) )
    return calculateValidPosition(start, middlePoint)
else
    return calculate(middlePoint, end)

我刚刚制作了这段代码,因此会有很大的改进空间......首先不要让它递归。

当检测到碰撞时,将调用此函数,将参数作为参数传递给对象的最后一个有效位置,以及当前的无效位置。在每次迭代中,第一个参数始终有效(无碰撞),第二个参数无效(存在碰撞)。

但我认为这可以让您了解可能的解决方案,因此您可以根据自己的需要进行调整。