【发布时间】:2012-09-10 17:07:35
【问题描述】:
我有一个简单的 BreakOut 游戏(垂直,沿底部划桨)启动并运行,但碰撞检测有点偏离。 我使用 Rectangle.Intersect 来初步检查球是否完全与给定的砖相交,然后如果它确实还有 4 个 Intersect 调用来检查球是垂直碰撞(砖的一侧,左+右)还是水平(砖的顶部+底部)。 在某些情况下,当球在 2 个水平相邻的砖块的交叉点附近以锐角与砖块相撞时,它会将它们都移除并继续向上。我认为这是双重碰撞。我已经强行退出了 foreach 循环,它在找到矩形相交的那一刻检查矩形相交,但这还没有解决问题。
这是在游戏类的主Update()函数中:
foreach (Brick brick in bricks)
{
if (brick.CheckCollision(ball))
{
break;
}
}
这是 Brick.CheckCollision() 函数:
public bool CheckCollision(Ball ball)
{
if (alive && ball.Bounds.Intersects(location))
{
alive=false;
ball.Deflection(this);
return true;
}
return false;
}
这就是 Ball.Deflection() 函数。在此,我使用没有宽度/高度的矩形来标记砖的侧面。不确定这是否是正确的方法:
public void Deflection(Brick brick)
{
//For vertical collision (top or bottom of brick) invert Y motion
if (this.Bounds.Intersects(new Rectangle(brick.Location.Left, brick.Location.Top, brick.Location.Right - brick.Location.Left, 0)) ||
this.Bounds.Intersects(new Rectangle(brick.Location.Left, brick.Location.Bottom, brick.Location.Right - brick.Location.Left, 0)))
{
motion.Y *= -1;
return;
}
//For horizontal collision (left or right side of brick) invert X motion
if (this.Bounds.Intersects(new Rectangle(brick.Location.Left, brick.Location.Top, 0, brick.Location.Bottom - brick.Location.Top)) ||
this.Bounds.Intersects(new Rectangle(brick.Location.Right, brick.Location.Top, 0, brick.Location.Bottom - brick.Location.Top)))
{
motion.X *= -1;
return;
}
}
我认为我犯了一个明显的逻辑错误,但如果可以改进一般方法,我会全力以赴!
【问题讨论】:
-
我刚刚经历了一个可能的 eureka/duh 时刻。如果球的位置在一帧中足够远地进入brick1,并且在反转方向并在另一帧上移动之后,它是否仍然在brick2内?这将解释双重负运动变化。我要以整个错误的方式进行检测吗?我计划做一些非常基本的事情(以防它不是我的第一场比赛)所以我不想太深入到数学方面。
-
这很有可能。如果在砖块之后更新球,它会改变行为吗?希望这能让球有足够的时间离开另一个砖块的边界框。
-
这将是一种方法。也许在更新之前捕获球的位置。如果发生碰撞,那么除了改变球的速度之外,您还可以将球的位置设置为之前的位置。
-
它不应该造成口吃效果。它可能会使球看起来像是早一到两个像素地从砖块上反弹(取决于速度),但我不认为它会很明显。请记住当前位置的捕获、更新/碰撞检查以及当前位置的可能重置(使用碰撞检查中修改的速度)都将在单个更新周期内发生。两者之间不应有任何绘图。
-
您可能会发现添加一些将信息写入屏幕调试部分的日志记录代码很有帮助。
标签: c# xna collision-detection