Jump to content



How to see if two sprites are intersecting in SFML

  • You cannot reply to this topic
14 replies to this topic

#1 SoulHeart   Members   -  Reputation: 100

Like
0Likes
Like

Posted 10 February 2012 - 07:26 PM

What would be the easiest way to have a sprite bounce off another sprite when they intersect.
would it be to find the corners of the sprite and setup an if statement or does sfml offer another way to do this?
I've been stuck on this for awhile now so thanks for your help.

Ad:

#2 Jebbles   Members   -  Reputation: 121

Like
0Likes
Like

Posted 10 February 2012 - 10:43 PM

What you would want to do is create a boundary for each sprite. SFML has a defined rectangle class that you can use just for this as it provides functionality for seeing when two rectangles intersect.

#3 Cornstalks   Members   -  Reputation: 1216

Like
0Likes
Like

Posted 11 February 2012 - 01:27 AM

Yes, SFML's Rect class will be able to tell you if two rectangles are intersecting. If you need more control or information though (i.e. maybe to know which side of the rectangle, so you know how to change the rectangle's velocity so it bounces in the right direction), you can look into AABB collision detection. The Separating Axis Theorem is really simple for AABBs, should you need to implement it (here's one of my favorite references).
[ Realistic Rendering ] [ School + Dublin = Boom ] [ I've been ninja'd 70 times ] [ f.k.a. MikeTacular ] [ My Blog ]

#4 SoulHeart   Members   -  Reputation: 100

Like
0Likes
Like

Posted 11 February 2012 - 09:17 AM

I'm not sure how to use the sfml rectangle class. I'm trying to see if a paddle and a ball intersect.
In my Global.h

sf::IntRect ppaddleRect(

        ppaddle.GetPosition().x,
        ppaddle.GetPosition().y,
        ppaddle.GetSize().x,
        ppaddle.GetSize().y);


sf::IntRect pballRect(
        pball.GetPosition().x,
        pball.GetPosition().y,
        pball.GetSize().x,
        pball.GetSize().y);

In my Update Function
if(pballRect.Intersects(ppaddleRect))
    {
	    Xballspeed = -Xballspeed;
    }

However, it seems that the two are always intersecting, so the ball now moves up and down. Does anyone know why. (when I comment out the if statement above the ball moves fine, but obviously doesn't bounce off the paddle either)

#5 Cornstalks   Members   -  Reputation: 1216

Like
0Likes
Like

Posted 11 February 2012 - 09:31 AM

Are you sure you want those in Global.h declared like that? Each source file that includes Global.h is going to get its own copy of the variables. If you really are going to use globals like that, you should declare and define them in one source file, and then in the Global.h file put "extern sf::IntRect ppandlRect" and "extern sf::IntRect pballRect".


Not that I recommend using globals.
[ Realistic Rendering ] [ School + Dublin = Boom ] [ I've been ninja'd 70 times ] [ f.k.a. MikeTacular ] [ My Blog ]

#6 BeerNutts   Members   -  Reputation: 241

Like
0Likes
Like

Posted 11 February 2012 - 09:52 AM

View PostSoulHeart, on 11 February 2012 - 09:17 AM, said:

I'm not sure how to use the sfml rectangle class. I'm trying to see if a paddle and a ball intersect.
In my Global.h

sf::IntRect ppaddleRect(

		ppaddle.GetPosition().x,
		ppaddle.GetPosition().y,
		ppaddle.GetSize().x,
		ppaddle.GetSize().y);


sf::IntRect pballRect(
		pball.GetPosition().x,
		pball.GetPosition().y,
		pball.GetSize().x,
		pball.GetSize().y);

In my Update Function
if(pballRect.Intersects(ppaddleRect))
	{
		Xballspeed = -Xballspeed;
	}

However, it seems that the two are always intersecting, so the ball now moves up and down. Does anyone know why. (when I comment out the if statement above the ball moves fine, but obviously doesn't bounce off the paddle either)

Are you updating the Rectangle's location every frame? Go ahead and print out the X, Y, width and height of the rectangles when they intersect, and you should see what's happening. All an intersection is a check like this (checking Rect1 and Rect2 intersect or not):
if (Rect1.X <= Rect2.X + Rect2.Width &&
	Rect1.X + Rect1.Width >= Rect2.X &&
	Rect1.Y <= Rect2.Y + Rect2.Height &&
	Rect1.Y + Rect1.Height >= Rect2.Y)

BTW, I've started using a 2d physics library (chipmunk-physica, see my old blog link in my sig). it's simplifies things so much for me. No longer do I have to worry about collision detection, collision response, object movement, etc. the 2d physics library handles all that for me.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#7 SoulHeart   Members   -  Reputation: 100

Like
0Likes
Like

Posted 14 February 2012 - 03:06 PM

Ok this is what i put
if (pball.GetPosition().x <= ppaddle.GetPosition().x + ppaddle.GetSize().x &&
    pball.GetPosition().x + pball.GetSize().x >= ppaddle.GetPosition().x &&
    pball.GetPosition().y <= ppaddle.GetPosition().y + ppaddle.GetSize().y &&
    pball.GetPosition().y + pball.GetSize().y >= ppaddle.GetPosition().y)
    {
	    Xballspeed = -Xballspeed;
    }
sometimes the collision happens way to the right of the paddle, other times the collisions happens when the ball is coming from behind the paddle(the ball bounces off all of the walls for now) and other times the ball completely ignores the paddle. I must be missing something vital in my code.

#8 BeerNutts   Members   -  Reputation: 241

Like
0Likes
Like

Posted 14 February 2012 - 04:11 PM

View PostSoulHeart, on 14 February 2012 - 03:06 PM, said:

Ok this is what i put
if (pball.GetPosition().x <= ppaddle.GetPosition().x + ppaddle.GetSize().x &&
	pball.GetPosition().x + pball.GetSize().x >= ppaddle.GetPosition().x &&
	pball.GetPosition().y <= ppaddle.GetPosition().y + ppaddle.GetSize().y &&
	pball.GetPosition().y + pball.GetSize().y >= ppaddle.GetPosition().y)
	{
		Xballspeed = -Xballspeed;
	}
sometimes the collision happens way to the right of the paddle, other times the collisions happens when the ball is coming from behind the paddle(the ball bounces off all of the walls for now) and other times the ball completely ignores the paddle. I must be missing something vital in my code.

Lets just look at the case where it happens way to the right of the paddle.

The only way a collision is possible is
if (pball.GetPosition().x <= ppaddle.GetPosition().x + ppaddle.GetSize().x)
is true

How can that be true, if the ball is way to the right? That line says, "The left side of the ball is to the left or equal to the right side of the paddle"

So, something is wrong in your code. Is GetSize() returning the right value? Are you drawing the objects based on the GetPosition() values? Print out the values when it collides, and check what it's telling you about the position and size of the objects.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#9 SoulHeart   Members   -  Reputation: 100

Like
0Likes
Like

Posted 20 February 2012 - 12:14 PM

ok i finally got back to programming.(being 14 its hard to find time sometimes) The prints were fine except the sizes of the paddle were mixed up. I believe it is because I rotated the sprite before i drew it so it would be in the right direction. Do you think this is true? When I rotated the sprite back to its original rotation the collision detection worked perfectly. Also, how would i need to change my if statement above to make this work.

#10 BeerNutts   Members   -  Reputation: 241

Like
0Likes
Like

Posted 20 February 2012 - 04:41 PM

View PostSoulHeart, on 20 February 2012 - 12:14 PM, said:

ok i finally got back to programming.(being 14 its hard to find time sometimes) The prints were fine except the sizes of the paddle were mixed up. I believe it is because I rotated the sprite before i drew it so it would be in the right direction. Do you think this is true? When I rotated the sprite back to its original rotation the collision detection worked perfectly. Also, how would i need to change my if statement above to make this work.

Well, if getSize() returns the sprite before rotation, you have 2 options:
#1 (easiest) draw the paddle upright, not on it's side or,
#2, create your own GetSize(), which takes into account the current rotation of the sprite.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#11 Washu   Senior Moderators   -  Reputation: 2448

Like
0Likes
Like

Posted 20 February 2012 - 05:06 PM

Assuming you have two sprites, and that they may be rotated you can get an AABB (Axis Aligned Bounding Box, that is aligned to the X/Y axes) using the Sprite::TransformToGlobal method against the vectors <0,0>, <0,1>, <1,0> and <1,1> (which forms your box). You can then do a simple axis aligned by taking those resulting vectors and constructing and IntRect and calling the Intersection method against the other sprite's IntRect, which will return true if there is an intersection of the bounding boxes.

See herefor more information
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX

#12 SoulHeart   Members   -  Reputation: 100

Like
0Likes
Like

Posted 22 February 2012 - 06:30 PM

I'm sorry guys but I still just don't get it. I can get collisions to work like this
if (pball.GetPosition().x <= ppaddle.GetPosition().x + ppaddle.GetSize().x &&
    pball.GetPosition().x + pball.GetSize().x >= ppaddle.GetPosition().x &&
    pball.GetPosition().y <= ppaddle.GetPosition().y + ppaddle.GetSize().y &&
    pball.GetPosition().y + pball.GetSize().y >= ppaddle.GetPosition().y)
but i can't get it to work when i rotate the sprite.(which I need it rotated)
The sfml collision tests don't make sense to me and there is hardly any tutorials out there. I need someone to put it in black and white for me.(I'm a NOOB still lol)
Thanks guys

#13 Cornstalks   Members   -  Reputation: 1216

Like
0Likes
Like

Posted 22 February 2012 - 06:34 PM

View PostSoulHeart, on 22 February 2012 - 06:30 PM, said:

I'm sorry guys but I still just don't get it. I can get collisions to work like this
if (pball.GetPosition().x <= ppaddle.GetPosition().x + ppaddle.GetSize().x &&
	pball.GetPosition().x + pball.GetSize().x >= ppaddle.GetPosition().x &&
	pball.GetPosition().y <= ppaddle.GetPosition().y + ppaddle.GetSize().y &&
	pball.GetPosition().y + pball.GetSize().y >= ppaddle.GetPosition().y)
but i can't get it to work when i rotate the sprite.(which I need it rotated)
Definitely not. That collision testing code is for AABBs (Axis-Aligned Bounding Boxes), i.e. boxes which are never rotated. If you're going to be intersecting two OBBs (Oriented Bounding Boxes, or boxes which may be rotated), something like SAT (Separating Axis Theorem) would work well. The site I linked to (here) gives a nice intro to SAT, which you can use to apply to your OBBs. Googling should give you some good results too.
[ Realistic Rendering ] [ School + Dublin = Boom ] [ I've been ninja'd 70 times ] [ f.k.a. MikeTacular ] [ My Blog ]

#14 BeerNutts   Members   -  Reputation: 241

Like
0Likes
Like

Posted 23 February 2012 - 04:27 PM

View PostSoulHeart, on 22 February 2012 - 06:30 PM, said:

I'm sorry guys but I still just don't get it. I can get collisions to work like this
if (pball.GetPosition().x <= ppaddle.GetPosition().x + ppaddle.GetSize().x &&
	pball.GetPosition().x + pball.GetSize().x >= ppaddle.GetPosition().x &&
	pball.GetPosition().y <= ppaddle.GetPosition().y + ppaddle.GetSize().y &&
	pball.GetPosition().y + pball.GetSize().y >= ppaddle.GetPosition().y)
but i can't get it to work when i rotate the sprite.(which I need it rotated)
The sfml collision tests don't make sense to me and there is hardly any tutorials out there. I need someone to put it in black and white for me.(I'm a NOOB still lol)
Thanks guys

Are you still talking about just the paddles being rotated? If you're paddles just stay up-right all the time (like classic PONG), then you should take your source image, and rotate it, and save it up-right, instead of rotating it after you load it. As I already suggested.

If you have a special pong where your paddle circles around the edge of the screen (or around a corner), then you're going to have to do a little bit of work, and it won't be beginner-easy work either.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#15 SoulHeart   Members   -  Reputation: 100

Like
0Likes
Like

Posted 24 February 2012 - 05:24 PM

Alright I'll give it a try. I guess I didn't interpret you right the first time.






We are working on generating results for this topic
PARTNERS