2D Collision

Started by
4 comments, last by Quest-Master 20 years ago
I''ve been working with SDL and C++ lately, and have read the rectangular collison tutorials here at GameDev, but am wondering; how can I, in real-time, calculate whethere the sprite is colliding with something I don''t want it to?
Advertisement
Give each sprite a collision radius[colr](say you have a craft = a and an enemy bullet = b) then work out if they collide with each other by passing them through a collision function where x and y are their positions on screen

float r=(float)sqrt((a->x-b->x)*(a->x-b->x)+(a->y-b->y)*(a->y-b->y));
if( r<(a->colr+b->colr) )

then they have collided so do something like blow up the craft and make the bullet disappear

Hope this helps
why not just use bounding box collision instead of what he just posted?? im working on a side scroller now, and just starting to add bullets and weapons and stuff, and will work on collision soon. i was just going to do standard BB collision. is this not a good idea? i dont really understand your method, either

Donkey Punch Productions.net
FTA, my 2D futuristic action MMORPG
quote:Original post by CrystalClear
Give each sprite a collision radius[colr](say you have a craft = a and an enemy bullet = b) then work out if they collide with each other by passing them through a collision function where x and y are their positions on screen

float r=(float)sqrt((a->x-b->x)*(a->x-b->x)+(a->y-b->y)*(a->y-b->y));
if( r<(a->colr+b->colr) )

then they have collided so do something like blow up the craft and make the bullet disappear

Hope this helps

In (more readable for non-C++ programmers) pseudo-code, it looks like:
distance = sqrt( (a.x - b.x)^2 + (a.y - b.y)^2 )if distance < (a.radius + b.radius) then colliding(a, b) 

Sqrt is quite slow, and is not really necessary if you only want to compare: the following does just the same thing, but is a lot faster:
distance_square = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)if distance_square < (a.r + b.r) * (a.r + b.r) then colliding(a, b) 

or in C(++):
float r=(float)(a->x-b->x)*(a->x-b->x)+(a->y-b->y)*(a->y-b->y);if( r<(a->colr+b->colr)*(a->colr+b->colr) ) colliding(a, b); 


---
tommy online: http://users.pandora.be/tommycarlier

[edited by - Tommy Carlier on April 15, 2004 4:47:07 AM]
I still don''t understand how to go around creating rectangles for maps and such, such as an RPG where you need rectangular collision to block certain tiles and not others.
If you are doing a basic RPG with rectangular collisions, here''s how I go about it.

First, create a function that not only tests collisions, but also moves the "inferior" object. What is an inferior object, you ask? Well, if a player is walking into a wall, which object gets its way? Does the player push the wall, or does the wall stop the player? Naturally, the wall stops the player, unless you want it otherwise, so the player is the inferior object.

So I would create a function like so:

public static bool defaultCollisionMove(SpriteInfo sprite1, SpriteInfo sprite2){	if(sprite1.x - sprite1.sclX < sprite2.x + sprite2.sclX &&		sprite1.x + sprite1.sclX > sprite2.x - sprite2.sclX &&		sprite1.y - sprite1.sclY < sprite2.y + sprite2.sclY &&		sprite1.y + sprite1.sclY > sprite2.y - sprite2.sclY)	{// looks like we have a collision.  So let''s move the object to the edge		int sideOn = LEFT; // set it to this.  We''ll change this if we need to		float smallest = sprite1.x+sprite1.sclX - (sprite2.x - sprite2.sclX);		if(smallest < 0) smallest *= -1; // this gets us the absolute distance from the left		float currentDistance = sprite1.x - sprite1.sclX - (sprite2.x + sprite2.sclX);		if(currentDistance < 0) currentDistance *= -1;		if(currentDistance < smallest){smallest = currentDistance; sideOn = RIGHT;}		currentDistance = sprite1.y - sprite1.sclY - (sprite2.y + sprite2.sclY);		if(currentDistance < 0) currentDistance *= -1;		if(currentDistance < smallest){smallest = currentDistance; sideOn = TOP;}		currentDistance = sprite1.y + sprite1.sclY - (sprite2.y - sprite2.sclY);		if(currentDistance < 0) currentDistance *= -1;		if(currentDistance < smallest){smallest = currentDistance; sideOn = BOTTOM;}		switch(sideOn)		{			case LEFT:	sprite1.x = sprite2.x - sprite2.sclX - sprite1.sclX;	break;			case RIGHT:	sprite1.x = sprite2.x + sprite2.sclX + sprite1.sclX;	break;			case TOP:	sprite1.y = sprite2.y + sprite2.sclY + sprite1.sclY;	break;			case BOTTOM:sprite1.y = sprite2.y - sprite2.sclY - sprite1.sclY;	break;		}		return true;	}	return false;}


Whoah! So, what''s this code all do? Well, it takes two SpriteInfos, which are my sprite objects. sprite1 will be the inferior sprite, so it will get moved so that it is on the outside of the object. So first we have a 4 part If statement doing basic bounding box colission. By definition, sclX and sclY measure the distance from the center of the sprite to the outside. So a sprites width is 2*sclX. Well, if we do have a collision, then we need to see what side collision is on. We assume it is on the LEFT side, then measure the distance from the left side. Then we see if the sprite is closer to the right than to the left. Then again, we see if the top is closer than whatever was closer before. Finally, we see if the bottom was closer than before.

Once we have determined which side the sprite should be on, we position it with a simple switch statement.

Now, we have ourselves a collision function. Next, we need to actually implement it. What I would do is create an array of objects which the character cannot walk through. These could be sections of walls, trees, ponds, chairs, even other characters. Then I simply loop through the array of all collidable objects, making our character sprite inferior to all other objects.

There are a few drawbacks to this method, and it also requires a little more bit of managing if, say, you have other characters that walk around the town. You wouldn''t want a moving townsman to squeeze your character between a wall and himself, making you jump to one side or the other. But these are concerns for later.

I hope this solves your problem. If not, feel free to IM me on AOL Instant Messenger: ArmySarj.

--Vic--

The future of 2D game development:
Flat Red Ball

This topic is closed to new replies.

Advertisement