Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] AABB Collision Detection - Checking which side  (Read 9451 times)

0 Members and 2 Guests are viewing this topic.

Eulavvalue

  • Newbie
  • *
  • Posts: 9
    • View Profile
[Solved] AABB Collision Detection - Checking which side
« on: November 09, 2013, 10:27:30 am »
I'm working on some code to check which side of the box had collided, and then I align the first object to the second one like in 2D games. I know *what* is happening, but I'm pretty confused as to how I would fix it.

The following code will iterate through every tile and check the player against it. Best way I know how to explain the issue is by an example, so here goes.
http://imgur.com/l4ND9Xc
If the above picture continues on its course upwards it will register as a top and right collision. It will register as a right collision and be aligned as such, but then register as a top collision and align as such in one iteration. I'm trying to figure out a way so the following scenario would register as top collision only, and ignore side scenarios (typical 2D collision game play). However, if the user was colliding to the bottom and right like so:
http://imgur.com/wAbBYUp
It should keep the character in position.

BoundingBox and playerSprite has to do with the Player class.
object is a tile or rectangle.

Simply not sure how to go on about this issue since the way I'm thinking of now is checking (colLeft && (!colTop&&!colBottom) then performing proper movement for left collision, but that would be a lot of if-statements. I figured there was someone more experienced that could offer some insight.

// Move sprite
        playerSprite.move(movement * deltaTime.asSeconds());

        // Set bounding box to current position
        boundingBox.setPosition(playerSprite.getPosition());

        // Check for collision
        for (auto layer = myLoader.GetLayers().begin(); layer != myLoader.GetLayers().end(); ++layer)
        {
                if (layer->name == "Collision")
                {
                        for (auto object = layer->objects.begin(); object != layer->objects.end(); ++object)
                        {
                                // collision = object->GetAABB().intersects(boundingBox.getGlobalBounds());    
                                if ((boundingBox.getPosition().x + boundingBox.getGlobalBounds().width > object->GetPosition().x &&
                                        boundingBox.getPosition().x < object->GetPosition().x + object->GetAABB().width) &&
                                        (boundingBox.getPosition().y + boundingBox.getGlobalBounds().height > object->GetPosition().y &&
                                        boundingBox.getPosition().y < object->GetPosition().y + object->GetAABB().height))
                                {
                                        if ((boundingBox.getPosition().x > object->GetPosition().x) &&
                                                (boundingBox.getPosition().x + boundingBox.getGlobalBounds().width > object->GetPosition().x + object->GetAABB().width))
                                        {
                                                boundingBox.setPosition(object->GetPosition().x + object->GetAABB().width, boundingBox.getPosition().y);
                                                std::cout << "Collide on left" << std::endl;
                                        }
                                        else if ((boundingBox.getPosition().x < object->GetPosition().x) &&
                                                (boundingBox.getPosition().x + boundingBox.getGlobalBounds().width < object->GetPosition().x + object->GetAABB().width))
                                        {
                                                boundingBox.setPosition(object->GetPosition().x - boundingBox.getGlobalBounds().width, boundingBox.getPosition().y);
                                                std::cout << "Collide on right" << std::endl;
                                        }
                                        else if ((boundingBox.getPosition().y > object->GetPosition().y) &&
                                                (boundingBox.getPosition().y + boundingBox.getGlobalBounds().height > object->GetPosition().y + object->GetAABB().height))
                                        {
                                                boundingBox.setPosition(boundingBox.getPosition().x, object->GetPosition().y + object->GetAABB().height);
                                                std::cout << "Collide on top" << std::endl;
                                        }
                                        else if ((boundingBox.getPosition().y < object->GetPosition().y) &&
                                                (boundingBox.getPosition().y + boundingBox.getGlobalBounds().height < object->GetPosition().y + object->GetAABB().height))
                                        {
                                                boundingBox.setPosition(boundingBox.getPosition().x, object->GetPosition().y - boundingBox.getGlobalBounds().height);
                                                std::cout << "Collide on bottom" << std::endl;
                                        }
                                }
                        }
                }
        }

        playerSprite.setPosition(boundingBox.getPosition());
 
« Last Edit: November 09, 2013, 08:55:08 pm by Eulavvalue »

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: AABB Collision Detection - Checking which side
« Reply #1 on: November 09, 2013, 11:02:40 am »
Testing all tiles in the whole world for a collision sounds like an extremely contrived way to find coordinates of the player sprite. Why dont you check only the tiles positioned on the way from the old position to the possible new position, whether they are walkable?

Eulavvalue

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: AABB Collision Detection - Checking which side
« Reply #2 on: November 09, 2013, 11:12:44 am »
That's something I plan to do after I figure out collision. There's a query tree I can use that comes with the Tiled map loader to reduce the tiles I'm checking collision against to those within what I specify. Also it only checks tiles that I specify as solid, so the white rectangles in the pictures are the only checked rectangles.

Edit: After reading your post again it seems you may have misunderstood my problem possibly? I'm not trying to find coordinates of the player sprite since I already have that.
« Last Edit: November 09, 2013, 11:40:34 am by Eulavvalue »

Eulavvalue

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: AABB Collision Detection - Checking which side
« Reply #3 on: November 09, 2013, 08:48:54 pm »
I managed to figure this out while thinking about it at work. If anyone has a solution to this similar problem I would be interested to see how you checked for collision.

// Move sprite
        playerSprite.move(movement * deltaTime.asSeconds());

        // Set bounding box to current position
        boundingBox.setPosition(playerSprite.getPosition());

        // Check for collision
        bool collide = false;
        float left = 1000;
        float right = 1000;
        float top = 1000;
        float bottom = 1000;
        for (auto layer = myLoader.GetLayers().begin(); layer != myLoader.GetLayers().end(); ++layer)
        {
                if (layer->name == "Collision")
                {
                        for (auto object = layer->objects.begin(); object != layer->objects.end(); ++object)
                        {
                                // collision = object->GetAABB().intersects(boundingBox.getGlobalBounds());    
                                if ((boundingBox.getPosition().x + boundingBox.getGlobalBounds().width > object->GetPosition().x &&
                                        boundingBox.getPosition().x < object->GetPosition().x + object->GetAABB().width) &&
                                        (boundingBox.getPosition().y + boundingBox.getGlobalBounds().height > object->GetPosition().y &&
                                        boundingBox.getPosition().y < object->GetPosition().y + object->GetAABB().height))
                                {
                                        left = 1000;
                                        right = 1000;
                                        top = 1000;
                                        bottom = 1000;
                                        if ((boundingBox.getPosition().x > object->GetPosition().x) &&
                                                (boundingBox.getPosition().x + boundingBox.getGlobalBounds().width > object->GetPosition().x + object->GetAABB().width))
                                        {
                                                // boundingBox.setPosition(object->GetPosition().x + object->GetAABB().width, boundingBox.getPosition().y);
                                                left = object->GetPosition().x + object->GetAABB().width - boundingBox.getPosition().x;
                                                std::cout << "Left: " << left << std::endl;
                                                std::cout << "Collide on left" << std::endl;
                                                collide = true;
                                        }
                                        if ((boundingBox.getPosition().x < object->GetPosition().x) &&
                                                (boundingBox.getPosition().x + boundingBox.getGlobalBounds().width < object->GetPosition().x + object->GetAABB().width))
                                        {
                                                // boundingBox.setPosition(object->GetPosition().x - boundingBox.getGlobalBounds().width, boundingBox.getPosition().y);
                                                right = boundingBox.getPosition().x + boundingBox.getGlobalBounds().width - object->GetPosition().x;
                                                std::cout << "Right: " << right << std::endl;
                                                std::cout << "Collide on right" << std::endl;
                                                collide = true;
                                        }
                                        if ((boundingBox.getPosition().y > object->GetPosition().y) &&
                                                (boundingBox.getPosition().y + boundingBox.getGlobalBounds().height > object->GetPosition().y + object->GetAABB().height))
                                        {
                                                // boundingBox.setPosition(boundingBox.getPosition().x, object->GetPosition().y + object->GetAABB().height);
                                                top = (object->GetPosition().y + object->GetAABB().height) - boundingBox.getPosition().y;
                                                std::cout << "Top: " << top << std::endl;
                                                std::cout << "Collide on top" << std::endl;
                                                collide = true;
                                        }
                                        if ((boundingBox.getPosition().y < object->GetPosition().y) &&
                                                (boundingBox.getPosition().y + boundingBox.getGlobalBounds().height < object->GetPosition().y + object->GetAABB().height))
                                        {
                                                // boundingBox.setPosition(boundingBox.getPosition().x, object->GetPosition().y - boundingBox.getGlobalBounds().height);
                                                bottom = (boundingBox.getPosition().y + boundingBox.getGlobalBounds().height) - object->GetPosition().y;
                                                std::cout << "Bottom: " << bottom << std::endl;
                                                std::cout << "Collide on bottom" << std::endl;
                                                collide = true;
                                        }

                                        if (collide)
                                        {
                                                if (left < bottom && left < top && left < right)
                                                {
                                                        boundingBox.setPosition(object->GetPosition().x + object->GetAABB().width, boundingBox.getPosition().y);
                                                }
                                                else if (right < bottom && right < top && right < left)
                                                {
                                                        boundingBox.setPosition(object->GetPosition().x - boundingBox.getGlobalBounds().width, boundingBox.getPosition().y);
                                                }
                                                else if (top < right && top < left && top < bottom)
                                                {
                                                        boundingBox.setPosition(boundingBox.getPosition().x, object->GetPosition().y + object->GetAABB().height);
                                                }
                                                else if (bottom < right && bottom < left && bottom < top)
                                                {
                                                        boundingBox.setPosition(boundingBox.getPosition().x, object->GetPosition().y - boundingBox.getGlobalBounds().height);
                                                }
                                        }
                                }
                        }
                }
        }

        playerSprite.setPosition(boundingBox.getPosition());