简体   繁体   中英

C# XNA Collision Detection

I am having difficulties getting my collision detection algorithm to work properly. I am reading in data from a .txt that contains 0s and 1s (0s are empty spaces 1s cannot be walked through). My algorithm catches sometimes other times it doesn't and ultimately is not working. My current algorithm is posted below where sep is a separation value to keep my spirits from overlapping.

private void collisionDetect()
{
    float diffxleft, diffxright, diffytop, diffybottom;
    float diffx, diffy;

    hit = false;
    foreach (Block b in blocks)
    {
        if (hit)
            break;
        if (inside(charPos, sep, b))
        {
            hit = true;
            diffxleft = Math.Abs(charPos.X + sep - b.pos.X);
            diffxright = Math.Abs(charPos.X - sep - (b.pos.X + b.rect.Width));
            diffytop = Math.Abs(charPos.Y + sep - b.pos.Y);
            diffybottom = Math.Abs(charPos.Y - sep - (b.pos.Y + b.rect.Height));
            diffx = Math.Min(diffxleft, diffxright);
            diffy = Math.Min(diffytop, diffybottom);
            if (diffx < diffy)
            {
                charVel.X = 0;
                if (diffxleft < diffxright)
                    charPos.X = b.pos.X - sep;
                else
                    charPos.X = b.pos.X + b.rect.Width + sep;
            }
            else
            {
                charVel.Y = 0;
                if (diffytop < diffybottom)
                    charPos.Y = b.pos.Y - sep;
                else
                    charPos.Y = b.pos.Y + b.rect.Height + sep;
            }
        }
    }

    foreach (Block b in blocks)
    {
        b.disp.X = b.pos.X + 10 - bkgdisplay.X;
        b.disp.Y = 470 - b.pos.Y;
    }
    charPosDisp.X = charPos.X - bkgdisplay.X;
    charPosDisp.Y = 480 - charPos.Y;
}

Help!

I would change how you handle the collisions slightly to make it easier to read and implement.

Say for each block(or tile) the 0 or 1 value represents whether the block is collidable or not. You can then use an intersect method between the block position and sprite position to see if they are currently intersecting. If they do intersect and the boolean for the tile is set to 1 then we have a collision and you can then handle the collision ie stop sprite moving, bounce it back etc. If the value is 0 then the sprite can be moved over the current block position.

This is easy to implement using the following pseudo-code.

Step 1: Read in the value for the block and set a boolean member variable in the class to say if it is collidable or not ie Parse Value from string, if value is 0 then bool = false else bool = true.

Step 2: Created a method in the block class to return the collidable member variable and which would do something like bool is_collidable() const { return collide; } bool is_collidable() const { return collide; }

Step 3: Use the Rectangle.Intersect method between the sprite rect and the block rect.

Step 4: After seeing if we have an intersection between block and sprite then test the block member variable to see if it is true or false.

Step 5: If value is true then we cannot pass over the tile, otherwise we can.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM