我必须使用Windows Forms进行学校游戏。我的游戏包括一个必须通过迷宫的用户。我试图阻止我的用户使用碰撞检测直接穿过墙壁,但由于用于表示墙壁的矩形的不同形状而被卡住了。 Here's an image of the game.这个问题可能与this one类似,但是我的动作相信它完全不同,因为我没有网格系统或图形地图。
如你所见,墙壁很厚。每个墙都由C#Rectangle,
表示,我的播放器图像(小黄鬼)也是如此。我知道如何使用C#的IntersectsWith(Rectangle r)
方法确定玩家是否穿过这些墙壁,但我不确定如何使用这些信息来处理碰撞并阻止玩家穿过墙壁移动所有
这是我尝试过的:
这是我的实际动作代码。由于游戏是在WinForm中构建的,因此移动是由键盘事件触发的,例如OnKeyPressed
和OnKeyUp
public void Move(Direction dir)
{
HandleCollision(); // Handle collision while player is trying to move.
if (dir == Direction.NORTH)
{
this.y -= moveSpeed;
}
if (dir == Direction.SOUTH)
{
this.y += moveSpeed;
}
if (dir == Direction.EAST)
{
this.x += moveSpeed;
}
if (dir == Direction.WEST)
{
this.x -= moveSpeed;
}
}
这是我的碰撞方法,HandleCollision()
:
private void HandleCollision()
{
// First, check to see if the player is hitting any of the boundaries of the game.
if (this.x <= 0)
{
this.x = 0;
}
if (this.x >= 748)
{
this.x = 748;
}
if (this.y <= 0)
{
this.y = 0;
}
if (this.y >= 405)
{
this.y = 405;
}
// Second, check for wall collision.
foreach (Rectangle wall in mazeWalls)
{
if (playerRectangle.IntersectsWith(wall))
{
if (player.X > wall.X) { player.X += wall.Width; }
else if (player.X < wall.X) { player.X -= wall.Width; }
else if (player.Y > wall.Y) { player.Y += wall.Height; }
else if (player.Y < wall.Y) { player.Y -= wall.Height; }
}
}
}
现在种上面的代码有效。但是,因为玩家的坐标正在增加墙的宽度/高度,所以这会在地图上进行一些奇怪的碰撞传送,玩家最终会在其周围弹跳。那么,实现可以替换if (playerRectangle.IntersectsWith(wall)) {
块中所有代码的碰撞检测系统的最有效方法是什么?
答案 0 :(得分:3)
在移动中,保存当前位置,执行移动,检查碰撞,如果为真,则恢复旧位置。
为此,HandleCollision将返回一个布尔值,对于每个成功的测试都是true(成功=检测到碰撞),如果没有满足条件则返回false。该方法根本不会修改任何x或y值。要反映其新功能,应将此方法重命名为CheckCollision。
从你的另一篇文章中的gif来看,你的比赛场地似乎被划分为正方形,而墙壁和精灵则由多个正方形组成?然后,您的移动应以一平方的增量进行,直到达到预期的增量。对于每个方格,必须检查碰撞。
对于更高级的方法,每次移动只需要一次检查,您需要一些线性数学。碰撞检查将需要当前点P和移动的增量d。您需要检查P和P + d之间是否穿过墙。这通常由线性条件下的符号变化表示。对于P左侧的垂直墙W,如果d指向墙,P.x+d.x-(W.x+W.width)
将为负。使用W.x+W.width<=P.x+s*d.x
确定s。对于水平墙,您必须在y坐标中进行相同的检查。将所有击中的对象和P+s*d
作为新位置的最小值。