我正在实现一个简单的基于瓦片的游戏,它包含了基于时间的移动。
我负责移动和碰撞检测的代码是
private function onEnterFrame(event:Event):void
{
if (waiting && game.movingBreakers <= 0)
endLevel();
var interval:int = getTimer() - oldTime;
oldTime += interval;
var totalBreakers:uint = breakers.length;
if (totalBreakers)
{
for each (var breaker:Breaker in breakers)
{
if (!breaker.moving)
continue;
switch (breaker.direction)
{
case TOP:
breaker.y -= SPEED * interval;
break;
case BOTTOM:
breaker.y += SPEED * interval;
break;
case LEFT:
breaker.x -= SPEED * interval;
break;
case RIGHT:
breaker.x += SPEED * interval;
break;
}
checkCollisions(breaker);
}
}
}
我最近遇到的问题是,由于一些与游戏无关的原因,我的电脑上的cpu负载很重。因此,游戏的帧在稍后的时间更新,但精灵(断路器)处于正确的位置,因为它们的移动是基于时间的。然而,由于最后两帧之间的时间差较大,精灵移动到了更远的位置,因此一些碰撞失败。因此,我的问题是,在基于时间的运动中,如何解决碰撞检测问题?
在增量时间进行移动时,有几种很好的方法可以解决这种情况。
1)最常见的方法之一是执行"固定时间步长"。这本质上是一个实现,它强制受影响对象上的update()
(在本例中为movement()
)仅在"时间步长"结束后运行。假设FIXED_STEP:int = 10
有一个可变常数,这个值10表示10ms。如果您的增量时间(interval
)已过去10ms或更长时间,则无论您的(经过时间/FIXED_STEP
)是多少倍,都会发出update()
,并且任何剩余时间都会添加到下一个经过时间值中。
一个例子是说你的delta时间是45ms,所以你会运行update()
4次,并在下一个delta时间上加5。
这将允许您的碰撞仍然被检测到。这里有一个C#解释,我认为它也解释得很好:固定时间步骤C#XNA
2)另一种方法是计算在帧之间移动对象的距离,然后细分距离以创建移动步骤。即-你在a点的对象(一个40x40的矩形)将移动到B点,X轴上的距离为200px,你将对象移动200/object.width(即40)=5,所以你将调用movement()
5次,并移动40px的对象宽度。这将覆盖移动区域,您的碰撞可以在任何一次移动更新中检测到。
还有其他方法可以做到这一点,但由于性能原因可能没有那么好。光线投射和在物体的给定路径上找到交点非常准确,但性能非常高,需要一些挖掘才能学习和实现。
我还读到一些人创建了一个从update()
之前的原点到之后的位置的新对象,并用它来进行检测。即-点(0,0)处的对象A在下一帧后移动到(200,0),则创建一个从(0,O)到(200+object.width,0+object.height)的区域,并对该对象运行碰撞测试。
不管怎样,我希望这能有所帮助,祝你好运!
您应该为AS3使用CollisionTestKit库。