BoundingBoxes的碰撞检测重叠而造成的问题 [英] BoundingBoxes for Collision Detection overlapping and causing issues

查看:155
本文介绍了BoundingBoxes的碰撞检测重叠而造成的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面code是我尝试从通过NPC走停止PC(玩家角色)。

The following code is my attempt at stopping the PC (player character) from walking through an NPC.

  • 在如果语句检查两个矩形(BoundingBox的)相交。
  • collisionBox定义重叠BoundingBoxes面积
  • moveDir定义矢量的变化,PC将被if语句后进行(例如:如果moveDir =(2,0)的PC将移动到右侧的两个像素)
  • currentSpeed​​定义的值被分配给moveDir.X或moveDir.Y依赖于键盘输入(上,下,左,右)

code:

if (PC.charSprite.BoundingBox.Intersects(npc.charSprite.BoundingBox))       
{        
    Rectangle collisionBox = Rectangle.Intersect(PC.charSprite.BoundingBox, npc.charSprite.BoundingBox);

    if (PC.moveDir.X > 0) //Moving Right
    {
        //Unknown Code Goes Here
    }
    else if (PC.moveDir.X < 0) //Moving Left
    {

    }
    else if (PC.moveDir.Y > 0) //Moving Down
    {

    }
    else if (PC.moveDir.Y < 0) //Moving Up
    {

    }
}

如何使它,以便当PC触及一个NPC中,PC停止移动在这个方向,但可自由移动的任何其它三个方向的

How do I make it so that when the PC touches an NPC, the PC stops moving in that direction but is free to move any of the other three directions?

code我曾尝试:

if (PC.moveDir.X > 0) //Moving Right
{
    PC.moveDir = Vector2.Zero;
}
else if (PC.moveDir.X < 0) //Moving Left
{
    PC.moveDir = Vector2.Zero;
}
else if (PC.moveDir.Y > 0) //Moving Down
{
    PC.moveDir = Vector2.Zero;
}
else if (PC.moveDir.Y < 0) //Moving Up
{
    PC.moveDir = Vector2.Zero;
}

^这将锁定PC到位,preventing任何和所有的运动。

^This locks the PC in place, preventing any and all movement.

if (PC.moveDir.X > 0) //Moving Right
{
    PC.moveDir.X = 0;
}
else if (PC.moveDir.X < 0) //Moving Left
{
    PC.moveDir.X = 0;
}
else if (PC.moveDir.Y > 0) //Moving Down
{
    PC.moveDir.Y = 0;
}
else if (PC.moveDir.Y < 0) //Moving Up
{
    PC.moveDir.Y = 0;
}

^这也锁定到位的PC。

^This, also, locks the PC in place.

if (PC.moveDir.X > 0) //Moving Right
{
    PC.moveDir.X = -currentspeed;
}
else if (PC.moveDir.X < 0) //Moving Left
{
    PC.moveDir.X = currentspeed;
}
else if (PC.moveDir.Y > 0) //Moving Down
{
    PC.moveDir.Y = -currentspeed;
}
else if (PC.moveDir.Y < 0) //Moving Up
{
    PC.moveDir.Y = currentspeed;
}

^这个工作在一个非常间歇性的基础。我曾希望通过改变moveDir到多少,它已通过重叠(或更高版本)相反的方向将保持PC在全国人民代表大会的边缘,但prevent重叠。不幸的是,有一半的时间在PC卡在适当位置。

^This works on a terribly intermittent basis. I had hoped that by changing moveDir into the opposite direction of how much it had overlapped by (or greater) would keep the PC at the edge of the NPC but prevent overlap. Unfortunately, half the time the PC gets stuck in place.

两者结合

if (PC.moveDir.X > 0) //Moving Right
{
    PC.moveDir.X = -currentspeed;
    PC.moveDir.X = 0;
}
else if (PC.moveDir.X < 0) //Moving Left
{
    PC.moveDir.X = currentspeed;
    PC.moveDir.X = 0;
}
else if (PC.moveDir.Y > 0) //Moving Down
{
    PC.moveDir.Y = -currentspeed;
    PC.moveDir.Y = 0;
}
else if (PC.moveDir.Y < 0) //Moving Up
{
    PC.moveDir.Y = currentspeed;
    PC.moveDir.Y = 0;
}

正义事业全面禁售。

Just causes overall lockup.

if (PC.moveDir.X > 0) //Moving Right
{
    PC.moveDir.X = -collisionBox.Width;
}
else if (PC.moveDir.X < 0) //Moving Left
{
    PC.moveDir.X = collisionBox.Width;
}
else if (PC.moveDir.Y > 0) //Moving Down
{
    PC.moveDir.Y = -collisionBox.Height;
}
else if (PC.moveDir.Y < 0) //Moving Up
{
    PC.moveDir.Y = collisionBox.Height;
}

^本的几乎的作品完美,但在PC上靠全国人民代表大会和曲折垂直于全国人民代表大会是感人,电脑跳转到一边。此外,大约有一半的时间。

^This almost works perfectly, but when the PC is up against the NPC and turns perpendicular to the NPC it is touching, the PC jumps to one side. Again, about half the time.

尝试通过CSJ的评论的启发:

Attempt inspired from comment by CSJ:

if (PC.charSprite.BoundingBox.Intersects(npc.charSprite.BoundingBox))
{
    Rectangle collisionBox = Rectangle.Intersect(PC.charSprite.BoundingBox, npc.charSprite.BoundingBox);
    if (PC.moveDir.X > 0) //Moving Right
    {
        PC.charSprite.Position = new Vector2(npc.charSprite.BoundingBox.Left - 34, PC.charSprite.Position.Y);
    }
    else if (PC.moveDir.X < 0) //Moving Left
    {
        PC.charSprite.Position = new Vector2(npc.charSprite.BoundingBox.Right + 2, PC.charSprite.Position.Y);
    }
    else if (PC.moveDir.Y > 0) //Moving Down
    {
        PC.charSprite.Position = new Vector2(PC.charSprite.Position.X, npc.charSprite.BoundingBox.Top - 34);
    }
    else if (PC.moveDir.Y < 0) //Moving Up
    {
        PC.charSprite.Position = new Vector2(PC.charSprite.Position.X, npc.charSprite.BoundingBox.Bottom + 2)
    }
}

我再问:我该如何让这个当PC倒是一个NPC,电脑停止朝着这个方向,但可以自由移动的任何其它三个方向的

I ask again: How do I make it so that when the PC touches an NPC, the PC stops moving in that direction but is free to move any of the other three directions?

或者,更通用的术语,我怎么做一个矩形相交与另一矩形失去其走向是相交的,不会影响任何其他方向上的运动矩形的能力?

Or, in more generic terms, how do I make one Rectangle intersecting with another Rectangle lose its ability to move towards the Rectangle it is intersecting without impeding its movement in any other direction?

推荐答案

在[我]多[/ i]于撞头和饮酒,我终于想出了一个解决方案。我甚至把它变成一个类,以便其他人可以用它来帮助他们有类似问题。

After [i]much[/i] headbanging and alcohol drinking, I finally came up with a solution. I even placed it into a class so that others may use it to help them with similar problems.

class Collision
{
    #region Declarations
    private Rectangle rectangle1;
    private Rectangle rectangle2;
    private Rectangle collisionZone;
    #endregion

    #region Constructors
    public Collision(Rectangle R1, Rectangle R2)
    {
        rectangle1 = R1;
        rectangle2 = R2;
        if(AreColliding())
        {
            collisionZone = Rectangle.Intersect(rectangle1, rectangle2);
        }
        else
        {
            collisionZone = Rectangle.Empty;
        }
    }
    #endregion

    #region Properties
    /// <summary>
    /// Returns the x-axis value of the top-left corner of R1
    /// </summary>
    public int TopLeftR1X
    {
        get { return rectangle1.X; }
    }

    /// <summary>
    /// Returns the y-axis value of the top-left corner of R1
    /// </summary>
    public int TopLeftR1Y
    {
        get { return rectangle1.Y; }
    }

    /// <summary>
    /// Returns the x-axis value of the top-right corner of R1
    /// </summary>
    public int TopRightR1X
    {
        get { return rectangle1.X + rectangle1.Width; }
    }

    /// <summary>
    /// Returns the y-axis value of the top-right corner of R1
    /// </summary>
    public int TopRightR1Y
    {
        get { return rectangle1.Y; }
    }

    /// <summary>
    /// Returns the x-axis value of the bottom-left corner of R1
    /// </summary>
    public int BottomLeftR1X
    {
        get { return rectangle1.X; }
    }

    /// <summary>
    /// Returns the y-axis value of the bottom-left corner of R1
    /// </summary>
    public int BottomLeftR1Y
    {
        get { return rectangle1.Y + rectangle1.Height; }
    }

    /// <summary>
    /// Returns the x-axis value of the bottom-right corner of R1
    /// </summary>
    public int BottomRightR1X
    {
        get { return rectangle1.X + rectangle1.Width; }
    }

    /// <summary>
    /// Returns the y-axis value of the bottom-right corner of R1
    /// </summary>
    public int BottomRightR1Y
    {
        get { return rectangle1.Y + rectangle1.Height; }
    }

    /// <summary>
    /// Returns the x-axis value of the top-left corner of R2
    /// </summary>
    public int TopLeftR2X
    {
        get { return rectangle2.X; }
    }

    /// <summary>
    /// Returns the y-axis value of the top-left corner of R2
    /// </summary>
    public int TopLeftR2Y
    {
        get { return rectangle2.Y; }
    }

    /// <summary>
    /// Returns the x-axis value of the top-right corner of R2
    /// </summary>
    public int TopRightR2X
    {
        get { return rectangle2.X + rectangle2.Width; }
    }

    /// <summary>
    /// Returns the y-axis value of the top-right corner of R2
    /// </summary>
    public int TopRightR2Y
    {
        get { return rectangle2.Y; }
    }

    /// <summary>
    /// Returns the x-axis value of the bottom-left corner of R2
    /// </summary>
    public int BottomLeftR2X
    {
        get { return rectangle2.X; }
    }

    /// <summary>
    /// Returns the y-axis value of the bottom-left corner of R2
    /// </summary>
    public int BottomLeftR2Y
    {
        get { return rectangle2.Y + rectangle2.Height; }
    }

    /// <summary>
    /// Returns the x-axis value of the bottom-right corner of R2
    /// </summary>
    public int BottomRightR2X
    {
        get { return rectangle2.X + rectangle2.Width; }
    }

    /// <summary>
    /// Returns the y-axis value of the bottom-right corner of R2
    /// </summary>
    public int BottomRightR2Y
    {
        get { return rectangle2.Y + rectangle2.Height; }
    }

    /// <summary>
    /// Returns the rectangle formed by how much the rectangles overlap.
    /// </summary>
    public Rectangle Overlap
    {
        get { return collisionZone; }
    }

    #endregion

    #region Methods

    public bool AreColliding()
    {
        if (rectangle1.Intersects(rectangle2))
        {
            return true;
        }
        else
        {
            return false;
        }

    }

    public Vector2 StopOnCollision(Vector2 position, Vector2 moveDir, int currentspeed)
    {
        if (Overlap.Width < Overlap.Height)
        {
            if (position.X < rectangle2.Left)
            {
                if (moveDir.X > 0) //Moving Right
                {
                    moveDir = Vector2.Zero;
                }
                else
                {
                    moveDir.X = -currentspeed;
                    moveDir.Y = 0;
                }
            }
            //else if ((position.X + 33) > rectangle2.Right)
            else if (position.X < rectangle2.Right)
            {
                if (moveDir.X < 0) //Moving Left
                {
                    moveDir = Vector2.Zero;
                }
                else
                {
                    moveDir.X = currentspeed;
                    moveDir.Y = 0;
                }
            }
        }
        else
        {
            if (Overlap.Y == rectangle2.Top)

            {
                if (moveDir.Y > 0) //Moving Down
                {
                    moveDir = Vector2.Zero;
                }
                else
                {
                    moveDir.Y = -currentspeed;
                    moveDir.X = 0;
                }
            }

            else
            {
                if (moveDir.Y < 0) //Moving Up
                {
                    moveDir = Vector2.Zero;
                }
                else
                {
                    moveDir.Y = currentspeed;
                    moveDir.X = 0;
                }
            }
        }

        return moveDir;
    }

    #endregion
}

这有点简单:   - 你实例化类与两个碰撞盒(矩形)你检查。   - 您可以检查,以确保他们,其实,发生碰撞。   - 要使用StopOnCollision,你输入的任何移动(在x,y的基准坐标)的位置,你想用它来改变或妨碍它的运动矢量,并以飞快的速度在物体移动(每帧像素)

It's somewhat simple: - You instantiate the class with the two collision boxes (rectangles) you are checking. - You can check to make sure that they, in fact, are colliding. - To use StopOnCollision, you input the position of whatever is moving (the x,y coordinate of reference), the vector that you wish to use to alter or impede its movement, and the speed at which the object is moving (pixels per frame)

我希望这可以帮助其他人一样,因为它帮助我

I hope this helps everyone else as much as it helped me

这篇关于BoundingBoxes的碰撞检测重叠而造成的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆