我必须使用Windows Forms进行学校游戏.我的游戏包括一个必须通过迷宫的用户.我试图阻止我的用户使用碰撞检测直接穿过墙壁,但由于用于表示墙壁的矩形的不同形状而被卡住了. Here’s an image of the game.这个问题可能类似于this one,但是我的运动我认为它完全不同,因为我没有布置网格系统或图形地图.
如你所见,墙壁相当厚.每个墙由C#矩形表示,我的播放器图像(小黄鬼)也是如此.我知道如何使用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)){block?中的所有代码?
解决方法:
在移动中,保存当前位置,执行移动,检查碰撞,如果为真,则恢复旧位置.
为此,HandleCollision将返回一个布尔值,对于每个成功的测试都是true(成功=检测到碰撞),如果没有满足条件则返回false.该方法根本不会修改任何x或y值.要反映其新功能,应将此方法重命名为CheckCollision.
从你的另一篇文章中的gif来看,你的比赛场地似乎被划分为正方形,而墙壁和精灵则由多个正方形组成?然后,您的移动应以一平方的增量进行,直到达到预期的增量.对于每个方格,必须检查碰撞.
对于更高级的方法,每次移动只需要一次检查,您需要一些线性数学.碰撞检查将需要当前点P和移动的增量d.你需要检查P和P之间的墙是否交叉.这通常由线性条件下的符号变化表示.对于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作为新位置的最小值.