Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've written a tile editor and game in XNA, with velocities and gravity, and am having trouble with some of my collision detection things. It works okay, but seems to glitch between just inside and outside the tile the player is on. Here's my collision detection function and the other functions it uses:

void SolveCollisions(List<Tile> tiles, Vector2 screensize)
    {
        if (position.X < 0)
        {
            position.X = 0;
        }
        if (position.X + 32 > screensize.X)
        {
            position.X = screensize.X - 32;
        }
        if (position.Y < 0)
        {
            position.Y = 0;
        }
        if (position.Y + 32 > screensize.Y)
        {
            position.Y = screensize.Y - 32;
        }

        foreach (Tile t in tiles)
        {
            if (absTilePos(position.X) == absTilePos(t.position.X))
            {
                if (intersect(position.Y, t.position.Y, 32, 32))
                {
                    if (position.Y > 0)
                    {
                        velocity.Y = 0;
                        position.Y = tilePos(position.Y);
                    }

                    if (position.Y < 0)
                    {
                        velocity.Y = 0;
                        position.Y = tilePos(position.Y) + 32;
                    }
                }
            }

            if (absTilePos(position.Y) == absTilePos(t.position.Y))
            {
                if (intersect(position.X, t.position.X, 32, 32))
                {
                    if (position.X > 0)
                    {
                        velocity.X = 0;
                        position.X = tilePos(position.X);
                    }
                    if (position.X < 0)
                    {
                        velocity.X = 0;
                        position.X = tilePos(position.X) + 32;
                    }
                }
            }
        }
    }

    bool intersect(float p1, float p2, float s1, float s2)
    {
        if (p1 < p2 && p1 + s1 > p2)
        {
            return true;
        }
        if (p2 < p1 && p2 + s2 > p1)
        {
            return true;
        }

        return false;
    }

    float tilePos(float f)
    {
        int i = (int)f;
        i /= 32;
        i *= 32;
        return (float)i;
    }

    float absTilePos(float f)
    {
        int i = (int)f;
        i /= 32;
        return (float)i;
    }

The player also glitches into blocks on it's top and right ( http://puu.sh/2cVQf ) when it hits them instead of bouncing off them - it just goes straight into them.

Does anyone know how to remedy this? Thanks!

share|improve this question
    
Have you tried using Rectangles for collision? It has an intersects method msdn.microsoft.com/en-us/library/y10fyck0.aspx –  Savlon Mar 6 '13 at 7:12
    
Yeah, I have, but it meant I couldn't move to the side as it also triggered the collision for the other axis. –  supr_g33k_7120 Mar 6 '13 at 8:48
    
Voting to close as too localized. Please read the FAQ about what types of questions to ask here. Since this specific code is unlikely to help any future visitors, I think it's too localized. –  Byte56 Mar 6 '13 at 16:03
add comment

closed as too localized by Sean Middleditch, bummzack, Byte56, Trevor Powell, Josh Petrie Apr 5 '13 at 4:28

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

1 Answer

up vote 0 down vote accepted

Here's how I would solve this problem. The code written below is written out of memory, not tested - you will obviously have to make it legal C# code and adapt it to your project.

class AABB // make your game objects have an AABB
{
    Vector2 position, size; // position is the top-left position
    float getLeft() { return position.X; }
    float getRight() { return position.X + size.X; }
    float getTop() { return position.Y; }
    float getBottom() { return position.Y + size.Y; }

    bool isIntersecting(AABB other)
    {
        return getRight() > other.getLeft() && 
        getLeft() < other.getRight() && 
        (getBottom() > other.getTop() && 
        getTop() < other.getBottom());
    }
}

void SolveCollisions(AABB aabb, List<Tile> tiles, Vector2 screensize)
{
    if (aabb.getLeft() < 0) aabb.position.X = 0;
    if (aabb.getRight() > screensize.X) aabb.position.X = screensize.X - aabb.size.X;
    if (aabb.getTop() < 0) aabb.position.Y = 0;
    if (aabb.getBottom() > screensize.Y) aabb.position.Y = screensize.Y - aabb.size.Y;

    foreach (Tile t in tiles)
    {
        AABB other = t.getAABB(); // getAABB() would return the tile's axis aligned bounding box

        if (!aabb.isIntersecting(other)) continue; // no collision with this tile, check the next one

        // let's find the shortest distance to "push out" the object and resolve collision

        float left = other.getLeft() - aabb.getRight(); 
        float right = other.getRight() - aabb.getLeft();
        float minXPush = Math.Abs(left) < Math.Abs(right) ? left : right;

        float top = other.getTop() - aabb.getBottom(); 
        float bottom = other.getBottom() - aabb.getTop();
        float minYPush = Math.Abs(top) < Math.Abs(bottom) ? top : bottom;

        if(Math.Abs(minXPush) < Math.Abs(minYPush)) // x pushing distance is minor than y
        {
            aabb.position.X += minXPush;
        }
        else
        {
            aabb.position.Y += minYPush;
        }

        // collision should be resolved now
    }
}

This solution is the most basic one, and has many problems. I wrote some articles about 2D collision I advise you to read:

http://veegamedev.wordpress.com/2012/08/14/getting-2d-collisions-right-part-one/ http://veegamedev.wordpress.com/2012/08/14/getting-2d-collisions-right-part-two/

share|improve this answer
    
This seems to work, but the tile goes into the ground about 10 pixels and can't move in one direction along the X axis (stuck on tiles? It moves in a bit when holding the motion button for that direction, but bounces back), which seems to change based on height. –  supr_g33k_7120 Mar 7 '13 at 7:35
    
Ok, after some experimentation it seems it slowly pushes down (isn't pushed out enough). Do you know what this could be? –  supr_g33k_7120 Mar 9 '13 at 3:35
    
Without velocities it works fine though. (Sorry about the spam!) –  supr_g33k_7120 Mar 9 '13 at 3:40
    
Wait, I was updating in the wrong spot. It's all fixed now - thanks heaps! –  supr_g33k_7120 Mar 9 '13 at 4:22
    
You're welcome! You can check out my better implementation on GitHub (it's C++ though), google for "SSVSCollision" –  Vittorio Romeo Mar 9 '13 at 13:35
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.