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

Author Topic: Collision Problem  (Read 1227 times)

0 Members and 1 Guest are viewing this topic.

Njifra

  • Guest
Collision Problem
« 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;
}
 

:(

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: Collision Problem
« Reply #1 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 is wider or taller. If it's wider, move your rect vertically, if it's taller move your rect horizontally.

Njifra

  • Guest
Re: Collision Problem
« Reply #2 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?
« Last Edit: February 22, 2014, 10:09:03 am by Njifra »

Njifra

  • Guest
Re: Collision Problem
« Reply #3 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?