SFML community forums

Help => Graphics => Topic started by: Njifra on February 21, 2014, 02:33:53 pm

Title: Collision Problem
Post by: Njifra on February 21, 2014, 02:33:53 pm
Hmmmmmmm....
I have problem with rectangle collision.
When i collide on the left or right side of the rectangle, rectangle('character') moves in some corner of other rectangle('test')...
Here is whole code:

#include "SFML/Graphics.hpp"
#include "SFML/System.hpp"
#include "SFML/Audio.hpp"
#include "SFML/Network.hpp"
#include "SFML/Window.hpp"
#include <iostream>
#include <string.h>
#include <string>
#include <ctime>
#include <vector>
#include "Game.h"
#include <fstream>
#include <cstddef>

using namespace std;
#define LEFT  0
#define TOP 1
#define RIGHT   2
#define BOTTOM  3

bool collision(sf::RectangleShape c1, sf::RectangleShape c2)
{
        bool d = false;
        int rect1[4];
        rect1[LEFT] = c1.getPosition().x;
        rect1[TOP] = c1.getPosition().y;
        rect1[RIGHT] = c1.getPosition().x + c1.getSize().x;
        rect1[BOTTOM] = c1.getPosition().y + c1.getSize().y;
        int rect2[4];
        rect2[LEFT] = c2.getPosition().x;
        rect2[TOP] = c2.getPosition().y;
        rect2[RIGHT] = c2.getPosition().x + c2.getSize().x;
        rect2[BOTTOM] = c2.getPosition().y + c2.getSize().y;

        if(rect1[RIGHT] < rect2[LEFT] ||
       rect1[LEFT] > rect2[RIGHT] ||
       rect1[TOP] < rect2[BOTTOM] ||
       rect1[BOTTOM] > rect2[TOP]){
        return false;
    }else{
        return true;
    }
        return d;
}
bool collisionLeft(sf::RectangleShape c1, sf::RectangleShape c2)
{
        bool d = false;
        int rect1[4];
        rect1[LEFT] = c1.getPosition().x;
        rect1[TOP] = c1.getPosition().y;
        rect1[RIGHT] = c1.getPosition().x + c1.getSize().x;
        rect1[BOTTOM] = c1.getPosition().y + c1.getSize().y;
        int rect2[4];
        rect2[LEFT] = c2.getPosition().x;
        rect2[TOP] = c2.getPosition().y;
        rect2[RIGHT] = c2.getPosition().x + c2.getSize().x;
        rect2[BOTTOM] = c2.getPosition().y + c2.getSize().y;

        if(rect1[LEFT] > rect2[LEFT]){
        return false;
    }else{
        return true;
    }
        return d;
}
bool collisionTop(sf::RectangleShape c1, sf::RectangleShape c2)
{
        bool d = false;
        int rect1[4];
        rect1[LEFT] = c1.getPosition().x;
        rect1[TOP] = c1.getPosition().y;
        rect1[RIGHT] = c1.getPosition().x + c1.getSize().x;
        rect1[BOTTOM] = c1.getPosition().y + c1.getSize().y;
        int rect2[4];
        rect2[LEFT] = c2.getPosition().x;
        rect2[TOP] = c2.getPosition().y;
        rect2[RIGHT] = c2.getPosition().x + c2.getSize().x;
        rect2[BOTTOM] = c2.getPosition().y + c2.getSize().y;

        if(rect1[TOP] < rect2[TOP]){
        return false;
    }else{
        return true;
    }
        return d;
}
bool collisionBottom(sf::RectangleShape c1, sf::RectangleShape c2)
{
        bool d = false;
        int rect1[4];
        rect1[LEFT] = c1.getPosition().x;
        rect1[TOP] = c1.getPosition().y;
        rect1[RIGHT] = c1.getPosition().x + c1.getSize().x;
        rect1[BOTTOM] = c1.getPosition().y + c1.getSize().y;
        int rect2[4];
        rect2[LEFT] = c2.getPosition().x;
        rect2[TOP] = c2.getPosition().y;
        rect2[RIGHT] = c2.getPosition().x + c2.getSize().x;
        rect2[BOTTOM] = c2.getPosition().y + c2.getSize().y;

        if(rect1[BOTTOM] > rect2[BOTTOM]){
        return false;
    }else{
        return true;
    }
        return d;
}
bool collisionRight(sf::RectangleShape c1, sf::RectangleShape c2)
{
        bool d = false;
        int rect1[4];
        rect1[LEFT] = c1.getPosition().x;
        rect1[TOP] = c1.getPosition().y;
        rect1[RIGHT] = c1.getPosition().x + c1.getSize().x;
        rect1[BOTTOM] = c1.getPosition().y + c1.getSize().y;
        int rect2[4];
        rect2[LEFT] = c2.getPosition().x;
        rect2[TOP] = c2.getPosition().y;
        rect2[RIGHT] = c2.getPosition().x + c2.getSize().x;
        rect2[BOTTOM] = c2.getPosition().y + c2.getSize().y;

        if(rect1[RIGHT] < rect2[RIGHT]){
        return false;
    }else{
        return true;
    }
        return d;
}

int main()
{
        sf::RectangleShape character(sf::Vector2f(48, 48));
        sf::RectangleShape test(sf::Vector2f(64, 64));
        character.setPosition(10, 10);
        test.setPosition(200, 200);
        character.setFillColor(sf::Color(0, 255, 0, 127));
        test.setFillColor(sf::Color(0, 0, 255, 127));

        sf::Text pos;
        sf::Font orbitron;
        orbitron.loadFromFile("orbitron.ttf");
        pos.setFont(orbitron);
        pos.setCharacterSize(14);
        pos.setColor(sf::Color::White);
        pos.setPosition(5, 5);
        pos.setString("No collision");

    window.create(sf::VideoMode(800, 600, 32), "The War Fighters: Testing");

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
             if (event.type == sf::Event::Closed)
             {
                 window.close();
             }
                         else if (event.type == sf::Event::KeyPressed)
                         {
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                                 {
                                         character.move(-3.0f, 0.0f);
                                 }
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                                 {
                                         character.move(0.0f, 3.0f);
                                 }
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                                 {
                                         character.move(3.0f, 0.0f);
                                 }
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                                 {
                                         character.move(0.0f, -3.0f);
                                 }
                         }
        }

                if (!character.getGlobalBounds().intersects(test.getGlobalBounds()))
                {
                        pos.setString("No collision");
                }
                else
                {
                        if (collisionLeft(character, test))
                        {
                                character.setPosition(test.getPosition().x - character.getSize().x, character.getPosition().y);
                        }
                        else if (collisionRight(character, test))
                        {
                                character.setPosition(test.getGlobalBounds().left + test.getGlobalBounds().width, character.getPosition().y);
                        }
                        if (collisionTop(character, test))
                        {
                                character.setPosition(character.getPosition().x, test.getPosition().y + test.getSize().y);
                        }
                        else if (collisionBottom(character, test))
                        {
                                character.setPosition(character.getPosition().x, test.getPosition().y - character.getSize().y);
                        }
                        pos.setString("Collision");
                }

                window.draw(test);
                window.draw(character);
                window.draw(pos);
        window.display();
        window.clear();
    }

    return 0;
}
 

:(
Title: Re: Collision Problem
Post by: G. on February 21, 2014, 09:20:22 pm
Your collision response is applied twice.

Once for the horizontal axis, then once for the vertical axis.
When there is a collision from the left or right, you correct your rectangle horizonal position so the 2 rectangles don't intersect anymore, and then you correct the position AGAIN but vertically. That's why it moves to a corner of your second rectangle.

This shit isn't easy (not for me at least) to get right. You have to decide whether you correct your position horizontally or vertically. In order to do this you could check if the overlapped rectangle (http://www.sfml-dev.org/documentation/2.1/classsf_1_1Rect.php#a5f1874792b04c7e221bb786b31f5836e) is wider or taller. If it's wider, move your rect vertically, if it's taller move your rect horizontally.
Title: Re: Collision Problem
Post by: Njifra on February 21, 2014, 10:47:53 pm
Thanks, but I still have no idea how to fix it :(

[EDIT] Wait, does anyone on forum know how to make colliding? Is it that hard?
Title: Re: Collision Problem
Post by: Njifra on February 22, 2014, 01:01:50 pm
I made another example, which is almost working how it should, but still...
Here's code:
#include "SFML/Graphics.hpp"
#include "SFML/System.hpp"
#include "SFML/Audio.hpp"
#include "SFML/Network.hpp"
#include "SFML/Window.hpp"
#include <iostream>
#include <string.h>
#include <string>
#include <ctime>
#include <vector>
#include "Game.h"
#include <fstream>
#include <cstddef>

using namespace std;

bool dir[4];

int main()
{
        sf::RectangleShape character(sf::Vector2f(32, 32));
        sf::RectangleShape test(sf::Vector2f(32, 32));
        character.setPosition(10, 10);
        test.setPosition(200, 200);
        character.setFillColor(sf::Color(0, 255, 0, 127));
        test.setFillColor(sf::Color(0, 0, 255, 127));

        sf::Text pos;
        sf::Font orbitron;
        orbitron.loadFromFile("orbitron.ttf");
        pos.setFont(orbitron);
        pos.setCharacterSize(14);
        pos.setColor(sf::Color::White);
        pos.setPosition(5, 5);
        pos.setString("No collision");

    window.create(sf::VideoMode(800, 600, 32), "The War Fighters: Testing");

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
             if (event.type == sf::Event::Closed)
             {
                 window.close();
             }
                         else if (event.type == sf::Event::KeyPressed)
                         {
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                                 {
                                         character.move(-3.0f, 0.0f);
                                         dir[0] = true;
                                 }
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                                 {
                                         character.move(0.0f, 3.0f);
                                         dir[1] = true;
                                 }
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                                 {
                                         character.move(3.0f, 0.0f);
                                         dir[2] = true;
                                 }
                                 if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                                 {
                                         character.move(0.0f, -3.0f);
                                         dir[3] = true;
                                 }
                         }
                         else if (event.type == sf::Event::KeyReleased)
                         {
                                 if (event.key.code == sf::Keyboard::A)
                                 {
                                         dir[0] = false;
                                 }
                                 if (event.key.code == sf::Keyboard::S)
                                 {
                                         dir[1] = false;
                                 }
                                 if (event.key.code == sf::Keyboard::D)
                                 {
                                         dir[2] = false;
                                 }
                                 if (event.key.code == sf::Keyboard::W)
                                 {
                                         dir[3] = false;
                                 }
                         }
        }

                if (!character.getGlobalBounds().intersects(test.getGlobalBounds()))
                {
                        pos.setString("No collision");
                }
                else
                {
                        if (dir[0])
                        {
                                character.setPosition(test.getGlobalBounds().left + test.getGlobalBounds().width, character.getPosition().y);
                        }
                        else if (dir[1])
                        {
                                character.setPosition(character.getPosition().x, test.getPosition().y - character.getSize().y);
                        }
                        else if (dir[2])
                        {
                                character.setPosition(test.getPosition().x - character.getSize().x, character.getPosition().y);
                        }
                        else if (dir[3])
                        {
                                character.setPosition(character.getPosition().x, test.getPosition().y + test.getSize().y);
                        }
                        pos.setString("Collision");
                }

                window.draw(test);
                window.draw(character);
                window.draw(pos);
        window.display();
        window.clear();
    }

    return 0;
}
 

When I'm pressing 2 keys at once and colliding with top or down side of second rectangle, my character rectangle moves in corner, BUT ONLY WHEN I'M PRESSING 2 KEYS.
.... Any help?