碰撞检测在二维迷宫厚厚的墙壁迷宫、墙壁

2023-09-07 14:21:12 作者:と 与生俱来的低调

我必须做出一个游戏的Windows窗体学校。我的游戏由具有打通迷宫的用户。我试图prevent我的用户通过使用碰撞检测的墙壁直行,但我被卡住,因为长方形的不同形状被用来重新present墙壁。 下面是游戏的图像。的这个问题可能是类似于this 之一,但与我的运动我认为,这是完全不同的,因为我没有一个网格系统或图形的地图布局。

I have to make a game with Windows Forms for school. My game consists of a user having to get through a maze. I'm trying to prevent my user from going straight through the walls using collision detection, but am getting stuck because of the varying shape of the rectangles being used to represent walls. Here's an image of the game. This question may be similar to this one, however with my movement I believe that it is quite different, as I don't have a grid system or graphical map laid out.

正如你所看到的,墙壁是相当厚。每个墙重新用C#长方形,的是我的球员形象(小黄鬼)psented $ P $。我知道如何确定,如果播放器通过这些墙壁使用C#的 IntersectsWith(矩形R)方法路口,但我不完全知道如何使用这些信息,以处理冲突和穿墙移动在所有停止播放器。

As you can see, the walls are fairly thick. Each wall is represented by a C# Rectangle, as is my Player image (the little yellow ghost). I know how to determine if the player is crossing through these walls using C#'s IntersectsWith(Rectangle r) method, but I'm not exactly sure how to use this information in order to handle the collision and STOP the player from moving through the walls at all.

下面是我已经试过:

这是我的实际行动code。因为游戏是建立在winform,该运动是由键盘事件,如 OnKey pressed 的onkeyup 触发

This is my actual movement code. Because the game is built in WinForm, the movement is triggered by keyboard events such as OnKeyPressed and 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; }                    
            }
        }
    }

现在这个code以上的样的的工作。然而,由于玩家的坐标具有壁的宽度/高度添加到它,这使得横跨其中玩家结束弹跳周围的地图一些奇怪碰撞隐形传输。那么,什么将是去有关实现碰撞检测系统,最有效的方式,也可以在替换所有code中的如果(playerRectangle.IntersectsWith(墙)){阻止?

Now this code above kind of works. However, because the player's coordinates are having the wall's width/height added to it, this makes some weird collision teleportation across the map where the player ends up bouncing around. So what would be the most efficient way of going about implementing a collision detection system which can replace all the code within the if (playerRectangle.IntersectsWith(wall)) { block?

推荐答案

在移动,保存当前的位置,执行移动,检查碰撞,如果属实,恢复旧的位置。

In the move, save the current position, perform the move, check for collision, and if true, restore the old position.

对于这项工作,HandleCollision会返回一个布尔值,适用于每一个成功的试验(检测成功=碰撞),假的,如果是没有遇到结束条件。该方法不会修改任何x或y价值可言。为了体现其新的功能,这种方法应该被重命名为CheckCollision。

For this to work, HandleCollision would return a Boolean value, true for each successful test (successful=collision detected), false at the end if no condition was met. The method would not modify any x or y value at all. To reflect its new function, this method should be renamed to CheckCollision.

从您的其他职位的GIF看来你比赛场地分为广场,城墙和精灵是由多个平方?然后,你的举动应该按一平方递增,直到预期的增量满足。为每平方碰撞必须检查

From the gif in your other post it seems that your playing field is divided into squares, and walls and sprite are composed of multiple squares? Then your move should proceed in increments of one square until the intended increment is met. For each square the collision has to be checked.

有关更高级的方法,每次只移动一个检查,你需要一些线性数学。碰撞检查将需要在当前点P和移动的D递增。你需要检查+ D的墙穿过P和P之间。这通常是通过以线性状态的符号改变指示。对于一个垂直的墙壁W到P的左边,当d点的墙上, P.x + DX-(W.x + W.width)将是负面的。确定s的 W.x + W.width&LT; = P.x + S * DX 。对于水平的墙壁,你必须做相同的检查,在y坐标。以最小的结束了所有的物体击中, P + S * D 作为新的位置。

For a more advanced method with only one check per move you need some linear mathematics. The collision check will need the current point P and the increment d of the move. You need to check if between P and P+d the wall is crossed. This is usually indicated by a sign change in a linear condition. For a vertical wall W to the left of P, if d points to the wall, P.x+d.x-(W.x+W.width) will be negative. Determine s with W.x+W.width<=P.x+s*d.x. For horizontal walls, you have to do the same check in the y-coordinate. Take the minimal s over all objects hit and P+s*d as the new position.