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

Author Topic: Help with Collision  (Read 5689 times)

0 Members and 1 Guest are viewing this topic.

krrice

  • Newbie
  • *
  • Posts: 26
    • View Profile
Help with Collision
« on: October 30, 2013, 02:28:59 am »
Hi, I am having problems with my collisions. I know how 2 check if a collision has happened but having trouble with the sprite repositioning. I some minimal code  to show what I have. Right now the code is working for side collisions but for the top it is not. I know why the commented code isn't working, one the first 2 conditions will be true. Is there something simple that I am not seeing or do I need a lot more code to get this done. I have searched for answers but what I found is way different than what I have.

#include <SFML/Graphics.hpp>

int main()
{
        sf::RenderWindow window(sf::VideoMode(800,600), "SFML");
        window.setFramerateLimit(60);
        sf::Clock frameTime;

        sf::RectangleShape square(sf::Vector2f(40.f,40.f));
        square.setFillColor(sf::Color::Red);
        square.setPosition(200.f,500.f);

        sf::RectangleShape square2(sf::Vector2f(40.f,100.f));
        square2.setFillColor(sf::Color::Green);;
        square2.setPosition(275.f,275.f);
       
        sf::Vector2f speed(150.f,150.f);

        while(window.isOpen())
        {
                float dt =  frameTime.restart().asSeconds();
               
                sf::Event event;

                while(window.pollEvent(event))
                {
                        if(event.type == sf::Event::Closed)
                                window.close();
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                        square.move(speed.x * dt,0.f);
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                        square.move(-speed.x * dt,0.f);
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                        square.move(0.f,speed.y * dt);
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                        square.move(0.f,-speed.y * dt);
               

                if(square.getPosition().x + square.getSize().x > square2.getPosition().x &&
                        square.getPosition().x < square2.getPosition().x + square2.getSize().x &&
                        square.getPosition().y + square.getSize().y > square2.getPosition().y &&
                        square.getPosition().y < square2.getPosition().y + square2.getSize().y)
                {        
                        //left side of square 2 collision
                        if(square.getPosition().x < square2.getPosition().x )
                                square.setPosition(square2.getPosition().x - square2.getSize().x,square.getPosition().y);
                        //right side of square2 collision
                        if(square.getPosition().x > square2.getPosition().x)
                                square.setPosition(square2.getPosition().x + square2.getSize().x,square.getPosition().y);
                        //top of square2 collision
                        //if(square.getPosition().y + square.getSize().y > square2.getPosition().y)
                                //square.setPosition(square.getPosition().x,square2.getPosition().y - square.getSize().y);
                       
                }

                window.clear();
                window.draw(square);
                window.draw(square2);
                window.display();
        }

        return 0;
}
 

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Help with Collision
« Reply #1 on: October 30, 2013, 02:47:00 am »
You appear to be checking for collisions from the left, right, and bottom...but not the top.  See if simply adding the fourth case fixes it for you.

krrice

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: Help with Collision
« Reply #2 on: October 30, 2013, 02:53:05 am »
You appear to be checking for collisions from the left, right, and bottom...but not the top.  See if simply adding the fourth case fixes it for you.

I was trying to get the top working first, I had the fourth case but removed it for now.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Help with Collision
« Reply #3 on: October 30, 2013, 03:10:19 am »
Well, after some testing, I still think that third case is testing for a collision from the bottom, not from the top, and that's why it's "not working" when you try a collision from the top.  You do need that fourth/top case.

But there's a more general problem.  Because no collision detection happens during the initial movement, your collision logic doesn't know what the square's previous position was, which means any way you tweak this you're likely to have it guessing wrong and making the square warp around the object it collides with.  Movement and collision should be dealt with at the same time, after input is handled.
« Last Edit: October 30, 2013, 03:16:07 am by Ixrec »

krrice

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: Help with Collision
« Reply #4 on: October 30, 2013, 03:23:30 am »
Well, after some testing, I still think that third case is testing for a collision from the bottom, not from the top, and that's why it's "not working" when you try a collision from the top.  You do need that fourth/top case.

But there's a more general problem.  Because no collision detection happens during the initial movement, your collision logic doesn't know what the square's previous position was, which means any way you tweak this you're likely to have it guessing wrong and making the square warp around the object it collides with.  Movement and collision should be dealt with at the same time, after input is handled.

I commented out the first and second case and top collision works and if I add

if(square.getPosition().y < square2.getPosition().y + square2.getSize().y)
                                square.setPosition(square.getPosition().x,square2.getPosition().y + square2.getSize().y);
 

the bottom works.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Help with Collision
« Reply #5 on: October 30, 2013, 04:35:16 am »
The "general problem" I was describing is what happens when you have all four cases uncommented.  I've already said what to do about it.

krrice

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: Help with Collision
« Reply #6 on: October 30, 2013, 12:59:34 pm »
The "general problem" I was describing is what happens when you have all four cases uncommented.  I've already said what to do about it.

I have tried it with all cases uncommented. I can get it to work with getting previous position then after collision setting it back but it is not consistent. Sometimes after collision I am not right next to the rectangle.
I am at work right now later I will do the previous position code and post it. Thanks for helping me try to figure this out.

The Hatchet

  • Full Member
  • ***
  • Posts: 135
    • View Profile
    • Email
Re: Help with Collision
« Reply #7 on: October 30, 2013, 09:04:33 pm »
I've always found it's better to check collision first then move if not colliding than to move first, check collision and move back if you are.

Basically create whatever temp variables you need to check the collision, move the temps, check for collision and only allow the REAL object to move if there is no collision.  If a collision is detected for the temp object then you can calculate the difference of the distance between the two objects and move your REAL object that amount, thus having your real object move directly up against the other object.

This approach generally stops the 'My object1 got stuck inside object2 and now can't get out because my checking is always returning true and thus nothing gets moved" scenario

krrice

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: Help with Collision
« Reply #8 on: October 31, 2013, 12:37:02 am »
I've always found it's better to check collision first then move if not colliding than to move first, check collision and move back if you are.

Basically create whatever temp variables you need to check the collision, move the temps, check for collision and only allow the REAL object to move if there is no collision.  If a collision is detected for the temp object then you can calculate the difference of the distance between the two objects and move your REAL object that amount, thus having your real object move directly up against the other object.

This approach generally stops the 'My object1 got stuck inside object2 and now can't get out because my checking is always returning true and thus nothing gets moved" scenario

Thanks, I will try to implement it that way.

krrice

  • Newbie
  • *
  • Posts: 26
    • View Profile
Re: Help with Collision
« Reply #9 on: November 02, 2013, 04:59:15 pm »
Thanks for all the replies. Finally figured it out,here is the updated code.

#include <SFML/Graphics.hpp>
#include <iostream>

bool Collision(sf::RectangleShape square,sf::RectangleShape square2)
{
        if(square.getPosition().x + square.getSize().x > square2.getPosition().x &&
                square.getPosition().x < square2.getPosition().x + square2.getSize().x &&
                square.getPosition().y + square.getSize().y > square2.getPosition().y &&
                square.getPosition().y < square2.getPosition().y + square2.getSize().y)
        {
                std::cout << "collide" << std::endl;
                return true;
        }
        else
                return false;
}

int main()
{
        sf::RenderWindow window(sf::VideoMode(800,600), "SFML");
        window.setFramerateLimit(60);
        sf::Clock frameTime;

        sf::RectangleShape square(sf::Vector2f(40.f,40.f));
        square.setFillColor(sf::Color::Red);
        square.setPosition(200.f,500.f);

        sf::RectangleShape square2(sf::Vector2f(40.f,100.f));
        square2.setFillColor(sf::Color::Green);;
        square2.setPosition(275.f,275.f);
       
        sf::Vector2f speed(150.f,150.f);

        while(window.isOpen())
        {
                float dt =  frameTime.restart().asSeconds();
               
                sf::Event event;

                while(window.pollEvent(event))
                {
                        if(event.type == sf::Event::Closed)
                                window.close();
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                        square.move(speed.x * dt,0.f);
                        if(Collision(square,square2))
                        {
                                square.setPosition(square2.getPosition().x - square.getSize().x,square.getPosition().y);
                        }
                }
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                {
                        square.move(-speed.x * dt,0.f);
                        if(Collision(square,square2))
                        {
                                square.setPosition(square2.getPosition().x + square2.getSize().x,square.getPosition().y);
                        }
                }
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                {
                        square.move(0.f,speed.y * dt);
                        if(Collision(square,square2))
                        {
                                square.setPosition(square.getPosition().x,square2.getPosition().y - square.getSize().y);
                        }
                }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                {
                        square.move(0.f,-speed.y * dt);
                        if(Collision(square,square2))
                        {
                                square.setPosition(square.getPosition().x,square2.getPosition().y + square2.getSize().y);
                        }
                }

                window.clear();
                window.draw(square);
                window.draw(square2);
                window.display();
        }

        return 0;
}
 

Janacek

  • Newbie
  • *
  • Posts: 9
    • View Profile
    • Email
Re: Help with Collision
« Reply #10 on: November 06, 2013, 11:27:00 am »
Maybe you could use getGlobalBounds() to get a FloatRect which allows you to use the intersects method of the Rect class ?