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

Author Topic: Collision Detection Function Doing Weird Things  (Read 2472 times)

0 Members and 1 Guest are viewing this topic.

Mr. Morg

  • Newbie
  • *
  • Posts: 2
    • View Profile
Collision Detection Function Doing Weird Things
« on: June 12, 2011, 03:15:07 am »
Code: [Select]

#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <cmath>
//Stuff Included
int speed= 10;
//Global Speed For Player
bool coll(sf::Sprite& s1, sf::Sprite& s2)
// Collision Function
{
float left1, left2, right1, right2, top1, top2, bot1, bot2;
//Floats for our bounding boxes
left1= s1.GetPosition().x;
left2=s2.GetPosition().x;
right1=s1.GetPosition().x +s1.GetSize().x;
right2=s2.GetPosition().x +s2.GetSize().x;
top1=s1.GetPosition().y;
top2=s2.GetPosition().y;
bot1=s1.GetPosition().y+s1.GetScale().y;
bot2=s2.GetPosition().y+s2.GetScale().y;
//All of the Bounding Boxes' floats now have values!
if(bot1>top2)
{
return true;
}
else if(top1<bot2)
{
return true;
}
else if(right1>left2)
{
return true;
}
else if(right2>left1)
{
return true;
}
//return true if the sides of the Rectangles intersect
else
{
return false;
}
//return false if no sides intersect
}

int main()
{
sf::RenderWindow w(sf::VideoMode(500,500,32),"Scout-Man");
//Putting up the Render Window
sf::Image Scout;
if(!bat.LoadFromFile("Scout.png"))
{
return EXIT_SUCCESS();
}
//Loading Player Image
sf::Image wall;
if(!wall.LoadFromFile("wall.png"))
{
return EXIT_SUCCESS();
}
//Loading Wall Image
sf::Sprite pc;
sf::Sprite w1;
w1.SetImage(wall);
sf::Sprite w2;
w2.SetImage(wall);
w1.SetPosition(100,460);
w2.SetPosition(280,460);
pc.SetImage(Scout);
pc.SetPosition(250,250);
//Setting up the sprites and their values
while(w.IsOpened())
//Main Loop
{
sf::Event Event;
while(w.GetEvent(Event))
//Get Events
{
if(Event.Type==sf::Event::Closed)
{
w.Close();
}
//Close the Window if User Exits
if(Event.Type==sf::Event::KeyPressed && Event.Key.Code==sf::Key::W)
{
pc.SetPosition(pc.GetPosition().x, pc.GetPosition().y-speed);
}
else if(Event.Type==sf::Event::KeyPressed && Event.Key.Code==sf::Key::S)
{
pc.SetPosition(pc.GetPosition().x, pc.GetPosition().y+speed);
}
else if(Event.Type==sf::Event::KeyPressed && Event.Key.Code==sf::Key::A)
{
pc.SetPosition(pc.GetPosition().x-speed, pc.GetPosition().y);
}
else if(Event.Type==sf::Event::KeyPressed && Event.Key.Code==sf::Key::D)
{
pc.SetPosition(pc.GetPosition().x+speed, pc.GetPosition().y);
}
//Allow the Player to Move if he presses one of the WASD Keys
   if(coll(pc,w2) || coll(pc,w1))
{
speed= -12;
}
else
{
speed= 10;
}
           //If the Player Collides with one of the Walls, he will be stopped
}
       
w.Clear();
w.Draw(pc);
w.Draw(w1);
w.Draw(w2);
w.Display();
//Draw and Display
}
return EXIT_SUCCESS();
//Exit The Game after the While Loop Ends
}

All my code just in case

I've been looking at Some simple Collision Detection Algorithms and they all look very nice, but none of them have worked so far!

What Will happen is my character will move in the opposite directions (like W goes down, A goes right)  if I include the function in my Main Loop. I know it's not the movement code, as I've taken out the collision algorithm and it worked fine. And to add insult to injury, the you don't even collide wit the stupid walls! javascript:emoticon(':cry:')

P.S Yeah the codes not great, but I'm going for an incredibly simple first project game. Sorta like Pac-Man. Yes I know a tile system would be better, but I don't feel like setting one up for my first project in SFML when free movement will work fine when I can get it to work.

Thanks in Advance! javascript:emoticon(':D')


[/i]

Nolan

  • Newbie
  • *
  • Posts: 6
    • View Profile
Collision Detection Function Doing Weird Things
« Reply #1 on: June 12, 2011, 04:02:52 am »
If you have multiple objects, why not just use distance formula?



Code: [Select]

bool cool(x1,y1,x2,y2)
{
  int distance = sqrt(pow((x1-x2),2) + pow((y1-y2),2));
  if distance < 1
     return true
  return false
}

Nolan

  • Newbie
  • *
  • Posts: 6
    • View Profile
Collision Detection Function Doing Weird Things
« Reply #2 on: June 12, 2011, 04:03:14 am »
x1,y1,x2,y2 being the sprite's centers.

Mr. Morg

  • Newbie
  • *
  • Posts: 2
    • View Profile
Collision Detection Function Doing Weird Things
« Reply #3 on: June 12, 2011, 06:57:42 am »
Thank you for a quick answer! However, it did not work. The player still goes through the blocks, but that weird thing where he goes the opposite direction is gone now! :D

I think that, for some reason, the collision isn't being detected somehow, because when I changed the sign, I got the opposite direction glitch.

Dimple

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Collision Detection Function Doing Weird Things
« Reply #4 on: June 12, 2011, 03:00:39 pm »
First, you should know the difference between collision detection and collision response. Collision detection means detecting if a collision has happened (and often finding out the exact collision point). Collision response, on the other hand, means reacting to the collision that has been detected. Your function is actually very close to being correct, it only returns true if the sprites are not colliding and false if they are colliding. You need to swap the returning values:

Code: [Select]

bool coll(sf::Sprite& s1, sf::Sprite& s2)
// Collision Function
{
float left1, left2, right1, right2, top1, top2, bot1, bot2;
//Floats for our bounding boxes
left1= s1.GetPosition().x;
left2=s2.GetPosition().x;
right1=s1.GetPosition().x +s1.GetSize().x;
right2=s2.GetPosition().x +s2.GetSize().x;
top1=s1.GetPosition().y;
top2=s2.GetPosition().y;
bot1=s1.GetPosition().y+s1.GetScale().y;
bot2=s2.GetPosition().y+s2.GetScale().y;
//All of the Bounding Boxes' floats now have values!
if(bot1>top2)
{
return false;
}
else if(top1<bot2)
{
return false;
}
else if(right1>left2)
{
return false;
}
else if(right2>left1)
{
return false;
}
//return false if no sides intersect

else
{
return true;
}
//return true if the sides of the Rectangles intersect
}

That will also fix the movement bug. The movement bug exists because that function returns true when the sprites are not colliding, so it's returning it almost all the time. In the main function you have this piece of code:
Code: [Select]

if(coll(pc,w2) || coll(pc,w1))
{
    speed= -12;
} else {
    speed= 10;
}
  //If the Player Collides with one of the Walls, he will be stopped
}

That won't cause the player to stop when he hits the wall, it will cause him to move to the other direction (if you press w, it will move backwards etc.) So the player will move in the opposite directions when he's not colliding with the walls and move normally when he is colliding. Fixing the return values is the first step forward. The second step is fixing the reaction to the collision.

If you only wanted the player to stop, you could do this:
Code: [Select]

if(coll(pc,w2) || coll(pc,w1))
{
    speed= 0;
} else {
    speed= 10;
}
  //If the Player Collides with one of the Walls, he will be stopped
}

However, that is not a good solution since the player can't move at all when he collides with the wall. He will be stuck there forever. The solution is to move the player every time he hits the wall so that afterwards he won't be inside the wall anymore. For this you need to figure out which side of the wall the player collides and move the player accordingly. For example, if the player hits the wall from the left, you would move him to (wall.x - player.GetWidth()/2, player.y).