基于XNA图块的边界框碰撞 - 滑向墙壁

时间:2012-12-19 11:09:13

标签: xna 2d collision-detection bounding-box

我正在使用XNA制作一个简单的基于2d tile的RPG游戏。我已经制作了一个简单的瓷砖地图,其中包含每个瓷砖包含矩形的瓷砖对象列表。我对玩家的移动更新首先创建一个矩形,表示下一帧中的玩家。然后它运行一个foreach循环来检查tile列表中的每个tile是否与播放器矩形相交。如果是这样,它会将碰撞的布尔值设置为true,并且还会记住玩家将与之碰撞的图块。

如果玩家将发生碰撞,它会设置玩家位置,以便玩家触摸进入玩家的区块。我遇到的问题是,不可能在瓷砖墙上“滑动”。例如,如果我向下移动并同时向左移动,一旦我击中了一块牌,如果继续向左移动,则该牌手会被卡住。你有什么想法我怎么能改进方法所以无论我如何移动它都会正确行动?

public void MovementUpdate(KeyboardState ks, GameTime time, List<Tile> tlist)
    {
        Direction = Vector2.Zero;
        Rectangle nextPosRec;

        if (ks.IsKeyDown(Keys.Right)){
            Direction.X = MOVE_RIGHT;
        }

        if (ks.IsKeyDown(Keys.Down))
        {
            Direction.Y = MOVE_DOWN;
        }

        if (ks.IsKeyDown(Keys.Up))
        {
            Direction.Y = MOVE_UP;
        }

        if (ks.IsKeyDown(Keys.Left)){
            Direction.X = MOVE_LEFT;
        }

        Vector2 nextPos = Position ;
        nextPos += Direction * Speed * (float)time.ElapsedGameTime.TotalSeconds;
        nextPosRec = new Rectangle((int)nextPos.X, (int)nextPos.Y, 32, 32);

        bool colide = false;
        Tile ctile = new Tile(playerTexture, Position, 0);

        foreach (Tile t in tlist)
        {
            if (t.tileRectangle.Intersects(nextPosRec))
            {
                colide = true;
                ctile = t;
            }
        }

        if (colide == false)
        {
            Position = nextPos;
        }
        else
        {
            if (Position.Y < ctile.tileRectangle.Top - 32)
            {
                //COLLIDE TOP
                Position.Y = ctile.tileRectangle.Top - 32;
            }

            if(Position.Y > ctile.tileRectangle.Bottom)
            {
                //COLLIDE BOTTOM
                Position.Y = ctile.tileRectangle.Bottom;
            }

            if (Position.X < ctile.tileRectangle.Left - 32)
            {
                //COLLIDE LEFT
                Position.X = ctile.tileRectangle.Left - 32;
            }

            if (Position.X > ctile.tileRectangle.Right)
            {
                //COLLIDE RIGHT
                Position.X = ctile.tileRectangle.Right;
            }

        }

    }

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

您的碰撞逻辑存在一些缺陷:

  • 您忽略了多次碰撞,只处理了一次(与ctile碰撞)
  • 你的碰撞方向逻辑是不正确的,它检查是否有交叉点,但没有检查是否划过了哪些边框,这就是粘贴行为的来源

应该为每个相交的图块执行碰撞处理,而不仅仅是您现在正在进行的最后一个图块。在你的碰撞处理中,你可以将物体移回到它在x和y轴上碰撞的瓷砖的数量。

如果你真的使用了瓷砖地图(瓷砖网格),迭代所有瓷砖的效率非常低。您可以计算哪些图块与正在移动的对象相交。