基于XNA平铺的边界框碰撞-靠墙滑动

基于XNA平铺的边界框碰撞-靠墙滑动,xna,2d,collision-detection,bounding-box,Xna,2d,Collision Detection,Bounding Box,我正在使用XNA制作一个简单的基于2d瓷砖的RPG游戏。我制作了一个简单的平铺贴图,其中有一个平铺对象列表,每个平铺对象包含一个矩形。玩家的“我的移动更新”首先创建一个矩形,表示下一帧中的玩家。然后它运行一个foreach循环来检查tile列表中的每个tile是否与播放器矩形相交。如果是,它会将“碰撞布尔”设置为true,并记住玩家将与之碰撞的平铺 如果玩家将发生碰撞,它会设置玩家的位置,以便玩家在进入时触摸瓷砖。我的问题是不可能靠着瓷砖墙“滑动”。例如,如果我同时向下和向左移动,只要我击中一块

我正在使用XNA制作一个简单的基于2d瓷砖的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;
            }

        }

    }
public void MovementUpdate(键盘状态ks、游戏时间、列表列表)
{
方向=矢量2.0;
矩形nextPosRec;
if(ks.IsKeyDown(key.Right)){
方向X=向右移动;
}
if(ks.IsKeyDown(Keys.Down))
{
方向Y=向下移动_;
}
if(ks.IsKeyDown(Keys.Up))
{
方向Y=向上移动;
}
if(ks.IsKeyDown(Keys.Left)){
方向X=向左移动;
}
Vector2 nextPos=位置;
nextPos+=方向*速度*(浮动)时间.ElapsedGameTime.TotalSeconds;
nextPosRec=新矩形((int)nextPos.X,(int)nextPos.Y,32,32);
bool-colide=false;
Tile ctile=新的Tile(playerTexture,位置,0);
foreach(t列表中的t块)
{
如果(t.tileRectangle.相交(nextPosRec))
{
colide=真;
ctile=t;
}
}
if(colide==false)
{
位置=nextPos;
}
其他的
{
if(位置Yctile.tileRectangle.Bottom)
{
//碰撞底部
位置Y=ctile.tileRectangle.Bottom;
}
if(位置Xctile.tileRectangle.Right)
{
//对撞
位置.X=ctile.tileRectangle.Right;
}
}
}

谢谢你的帮助

您的冲突逻辑中有一些缺陷:

  • 您正在忽略多个碰撞,而只处理一个碰撞(与ctile的碰撞)
  • 您的碰撞方向逻辑不正确,它会检查是否存在交叉点,但不会检查平铺的哪些边界交叉,这就是粘滞行为的来源
应该对每个相交的平铺进行碰撞处理,而不是像现在这样仅对最后一个平铺进行碰撞处理。在碰撞处理中,可以将对象向后移动其在x轴和y轴上与之碰撞的平铺中的穿透量


如果你真的在使用一个平铺贴图(一个平铺网格),迭代所有的平铺是非常低效的。您可以只计算哪些磁贴与正在移动的对象相交。

这个问题属于gamedev堆栈交换。也许让碰撞成为矢量2?并进行水平和垂直碰撞。