我正在编写自己的游戏引擎(非常基础),我想了解物理在游戏开发中的运作方式,而不是使用已经构建的游戏引擎。我正在使用Java为Android设备编写代码(使用SurfaceView)。
问题是我不知道如何计算碰撞后我的物体的位置。我创建了自己的碰撞检测,它运行良好。
如您所见,红色矩形是我的球应该移动的区域。箭头显示了碰撞发生后球应该移动的位置。球有不同的位置,标有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:
??????????
}
我的球有速度和位置。我应该保存球的先前位置吗?
答案 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)
我刚刚制作了这段代码,因此会有很大的改进空间......首先不要让它递归。
当检测到碰撞时,将调用此函数,将参数作为参数传递给对象的最后一个有效位置,以及当前的无效位置。在每次迭代中,第一个参数始终有效(无碰撞),第二个参数无效(存在碰撞)。
但我认为这可以让您了解可能的解决方案,因此您可以根据自己的需要进行调整。