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

Author Topic: Collision with intersects  (Read 1798 times)

0 Members and 1 Guest are viewing this topic.

pascalb

  • Newbie
  • *
  • Posts: 7
    • View Profile
Collision with intersects
« on: June 20, 2014, 11:34:13 pm »
Hi..

I can not seem to manage collisions in my program. I have a character that I move with the mouse, and I have another square that has a fixed position.

I managed to handle collision for the right and left side of the character, but when I try to manage those at the top and bottom, my program is still doing collision for the left and right .. This is hard to explain for a beginner and a French like me so I did a little simple video:

http://videobam.com/JnqjK

This is my code :

class Player : public sf::RectangleShape {
private:
        sf::Texture m_playerTexture;
       
        float m_playerSpeed;
public:
        Player();

        void update(sf::Vector2i mousePosition, Level *level);
};

void Player::update(sf::Vector2i mousePosition, Level *level) {
        sf::Vector2f position = getPosition();
       
        m_delta.x = mousePosition.x - position.x;
        m_delta.y = mousePosition.y - position.y;
       
        move(m_delta.x * m_playerSpeed, m_delta.y * m_playerSpeed);
       
        sf::FloatRect playerRect = getGlobalBounds();
       
        sf::FloatRect levelTemp;
        levelTemp.top = 10 * CELL_SIZE;
        levelTemp.left = 10 * CELL_SIZE;
        levelTemp.width = levelTemp.height = CELL_SIZE;
       
        sf::FloatRect intersection;
       
        if (playerRect.intersects(levelTemp, intersection)) {
                if (playerRect.left + PLAYER_SIZE / 2 > levelTemp.left + CELL_SIZE / 2) {
                        move(intersection.width, 0);
                }
                else if (playerRect.left + PLAYER_SIZE / 2 < levelTemp.left + CELL_SIZE / 2) {
                        move(-intersection.width, 0);
                }
                else if (playerRect.top + PLAYER_SIZE / 2 > levelTemp.top + CELL_SIZE / 2) {
                        move(0, intersection.height);
                }
                else if (playerRect.top + PLAYER_SIZE / 2 < levelTemp.top + CELL_SIZE / 2) {
                        move(0, -intersection.height);
                }
        }
}

I try to do it with a single square before doing so for the full level

I hope you can help me. I tried and tried but I can not find a solution.
Thank you in advance!
« Last Edit: June 20, 2014, 11:42:43 pm by pascalb »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Collision with intersects
« Reply #1 on: June 20, 2014, 11:57:06 pm »
I believe it's generally easier to check for potential collisions before moving the character, rather than moving him first and then trying to unmove him if he collides.

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: Collision with intersects
« Reply #2 on: June 21, 2014, 12:09:10 am »
You could seperate your movement/collision.  You first move on the X-axis, then check for collision (left/right) and then you move on the Y-axis and check again (top/down).
Failing to succeed does not mean failing to progress!

pascalb

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Collision with intersects
« Reply #3 on: June 21, 2014, 01:18:16 am »
Now I check if there is a collision at the next position. If there is a collision, I remain in the same position. If not, I move to the next position.

void Player::update(sf::Vector2i mousePosition, Level *level) {
        sf::Vector2f currentPosition = getPosition();

        m_delta.x = mousePosition.x - currentPosition.x;
        m_delta.y = mousePosition.y - currentPosition.y;

        sf::Vector2f nextPosition = currentPosition;
        nextPosition.x += m_delta.x * m_playerSpeed;
        nextPosition.y += m_delta.y * m_playerSpeed;

        sf::FloatRect nextPositionRect(0.f, 0.f, PLAYER_SIZE, PLAYER_SIZE);
        nextPositionRect.left = nextPosition.x - PLAYER_SIZE / 2;       // Player origin is 10x, 10y, his size is 20x 20y
        nextPositionRect.top = nextPosition.y - PLAYER_SIZE / 2;

        sf::FloatRect levelTemp;
        levelTemp.top = 10 * CELL_SIZE;
        levelTemp.left = 10 * CELL_SIZE;
        levelTemp.width = levelTemp.height = CELL_SIZE;

        if (nextPositionRect.intersects(levelTemp)) {
                setPosition(currentPosition);
        }
        else {
                setPosition(nextPosition);
        }
}

Now the problem is that the player will not move if it touches the square.

http://videobam.com/jiAhW

pascalb

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Collision with intersects
« Reply #4 on: June 21, 2014, 03:50:24 am »
Finally : http://videobam.com/JsqXw

Now I'm trying to do it with more square. But it does not work as expected. The player behaves oddly when in collision with multiple tiles. There's a video : http://videobam.com/sNYzG

void Player::update(sf::Vector2i mousePosition, Level *level) {
        m_position = getPosition();

        m_delta.x = mousePosition.x - m_position.x;
        m_delta.y = mousePosition.y - m_position.y;

        move(m_delta.x * m_playerSpeed, m_delta.y * m_playerSpeed);

        sf::FloatRect playerRect = getGlobalBounds();

        int startX = (int)(m_position.x / CELL_SIZE - 1);
        int startY = (int)(m_position.y / CELL_SIZE - 1);
        int endX = startX + 2;
        int endY = startY + 2;

        sf::FloatRect levelTemp(0, 0, CELL_SIZE, CELL_SIZE);
        sf::FloatRect area;

        for (int y = startY; y <= endY; y++) {
                for (int x = startX; x <= endX; x++) {
                        if (level->get(x,y) == 1) {
                                levelTemp.left = x * CELL_SIZE;
                                levelTemp.top = y * CELL_SIZE;

                                if (playerRect.intersects(levelTemp, area)) {
                                        if (area.width > area.height) {
                                                if (playerRect.top < levelTemp.top + levelTemp.width &&
                                                    playerRect.top > levelTemp.top) {
                                                        move(0, area.height);
                                                }
                                                else if (playerRect.top + playerRect.height > levelTemp.top &&
                                                          playerRect.top + playerRect.height < levelTemp.top + levelTemp.height) {
                                                        move(0, -area.height);
                                                }
                                        }
                                        else if (area.width < area.height) {
                                                if (playerRect.left < levelTemp.left + levelTemp.width &&
                                                    playerRect.left > levelTemp.left) {
                                                        move(area.width, 0);
                                                }
                                                else if (playerRect.left + playerRect.width > levelTemp.left &&
                                                    playerRect.left + playerRect.width < levelTemp.left + levelTemp.width) {
                                                        move(-area.width, 0);
                                                }
                                        }
                                }
                        }
                }
        }
}

Collisions are only possible with the 8 tiles surrounding the player
« Last Edit: June 21, 2014, 05:09:04 am by pascalb »