简体   繁体   中英

C# 2D collision detection problem

I am stuck trying to figure out how to alter my collision detection to work correctly, i got all my wall objects stacked inside a List and then when the player moves i loop thru each wall object and call the DetectCollision method, this returns true or false depending on if the object is inside the wall or not.

Wall detect collision (X- and Y-coordinate is the position of the wall)

public bool DetectCollision(float x, float y)
    {
        if ((x >= this.XCoordinate && x <= (this.XCoordinate + this.BlockWidth)) && (y >= this.YCoordinate && y <= (this.YCoordinate + this.BlockHeight)))
            return true;            
        else
            return false;
    }

So in my player function when the player tries to move, i add the movement to a temporary X,Y coordinate and check if those Collide against the wall, if they do nothing happens, otherwise i move the player.

But i have noticed that it doesn't work as it should be, if i add a piece of wall inside of the gamefield it only checks the bottom right corner for collision detection?

Player movement method:

        float x, y;
        if (direction == Direction.E)
        {
            x = LiveObjects.player.XCoordinate - MovementSpeed;
            y = LiveObjects.player.YCoordinate;
        }
        else if (direction == Direction.W)
        {
            x = LiveObjects.player.XCoordinate + MovementSpeed;
            y = LiveObjects.player.YCoordinate;
        }
        else if (direction == Direction.N)
        {
            x = LiveObjects.player.XCoordinate;
            y = LiveObjects.player.YCoordinate - MovementSpeed;
        }
        else
        {
            x = LiveObjects.player.XCoordinate;
            y = LiveObjects.player.YCoordinate + MovementSpeed;
        }

        if (GameMechanics.DetectWallCollision(x, y) || GameMechanics.DetectWallCollision((x + LiveObjects.player.BlockWidth), (y + LiveObjects.player.BlockHeight))
        {
            OnPlayerInvalidMove(null, new PlayerEventArgs());
            return;
        }

and the loop for DetectWallCollision is just:

foreach (Wall wall in LiveObjects.walls)
        {
            if (wall.DetectCollision(x, y))
                return true;
        }
        return false;

Any ideas?

I'm assuming there isn't anything in your world that is infinitely small (ie is the size of a pixel). To have true bounding box collision, you've got to consider the size of both objects, not just one.

boolean intersectsEntity(Entity e)
{
    return (e.position.x <= position.x + size.x) &&
           (e.position.y <= position.y + size.y) &&
           (e.position.x + e.size.x >= position.x) &&
           (e.position.y + e.size.y >= position.y);
}

That's of course assuming an Entity has a vector for its position and for its size. So size.x == width, and size.y == height.

There is something that disturbs me, you said that the DetectCollision method gets the position of the wall - but if I interpret your code correctly you hand to the DetectWallCollision the x and y parameter which is the position (after movement) of the player and hand that position down to the DetectCollision method...

have you debugged your code to see what coordinates are passed to the collision methods and traced the routes your if-statements are going?

if it is not possible to debug your code for whatever reason - write a trace file - I think the solution will fall into your lap ;)

Your east and west are the wrong way around. With a coordinate system of 0,0 at the top left, increasing positively as you move down or to the right, then a movement West would normally mean a movement left, which means decreasing values of X, and the reverse for East. You are doing the opposite.

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