views:

1555

answers:

3

Hello!

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?

A: 

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 ;)

Gambrinus
There is a base building block that i use, abstract class block. This block contains the height and the width of the block along with the X and Y coordinate of where to print it.So the wall object is inherit the base block (same with player) and then the wall class adds the method DetectCollision.The method detect collision takes 2 parameters X and Y and checks if X or Y is inside of the block (wall).
Patrick
Sometimes you just stare yourself blind on the code, the solution was of course to check all the corners of the player object, not just the top left corner and the bottom right. Trace is quite handy sometimes =)
Patrick
A: 

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.

Kylotan
Correct, changed it. But it still doesn't solve the collision detection problem
Patrick
A: 

I'm assuming there isn't anything in your world that is infinitely small (i.e. 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.

Eli