SDL Collision Library

Started by
21 comments, last by somebodykulj 16 years ago
Quote:Original post by Genjix
thanks. I'm not sure why SDL doesn't have something similar (what with all the unnecessary libs like reading audio cds).


SDL wraps platform dependent functionality in an platform independent way. How to access audio cds is different on Linux and Windows but collision detection is nothing to do with the platform.
Advertisement
Quote:Original post by Rob Loach
Quote:Original post by Genjix
...
I wrote up a bounding circle collision test function a while ago if you're too lazy to write one yourself [smile].

i assume you do something like test if the distances between the 2 points is less than the sum of the radii?... but yeah, give it to me (include your name/email for credit). I spose I should split it into a header and source now.

What do you think of names
SDL_CollidePixel(SDL_Surface*,int,int , SDL_Surface*,int,int , int skip = 0)
SDL_CollideBounding(int,int,int,int , int,int,int,int)
SDL_CollideBounding(SDL_Rect,SDL_Rect)
SDL_CollideCircle(int,int , int,int)
I'd personally would rather have:
SDL_CollidePixel( ... )SDL_CollideBoundingBox( ... )SDL_CollideBoundingBox( ... )SDL_CollideBoundingCircle( ... )

... But that's just me.


As for the credit, just put in "Rob Loach (http://www.robloach.net)" anywhere in there. I'm not really that anal about this kind of thing. You can reformat the documentation as much as you want. I wasn't quite sure about the second SDL_CollideBoundingCircle as sometimes a sprite can be only part of an SDL_Surface......

// Declaration (*.h)bool SDL_CollideBoundingCircle(int x1, int y1, int radius1, int x2, int y2, int radius2, int offset = 0);bool SDL_CollideBoundingCircle(SDL_Surface* a, int x1, int y1, SDL_Surface* b, int x2, int y2, int radius1 = -1, int radius2 = -1, int offset = 0);// Definition (*.cpp)#include <cmath>// SDL_CollideBoundingCircle(x1, y1, radius1, x2, y2, radius2, offset)// Checks a collision using the bounding circle of two different sprite objects// x1 - The x center position of the first object// y1 - The y center position of the first object// radius1 - The radius of the first object// x2 - The x center position of the second object// y2 - The y center position of the second object// radius2 - The radius of the second object// offset - Allow some offset between the two objects (0 default)bool SDL_CollideBoundingCircle(int x1, int y1, int radius1, int x2, int y2, int radius2, int offset){	int distx = abs((int)(x1 - x2));	int disty = abs((int)(y1 - y2));	return(sqrt((distx * distx) + (disty * disty)) - radius1 - radius2 <= offset);}// SDL_CollideBoundingCircle(a, x1, y1, b, x2, y2, radius1, radius2, offset)// Checks a collision using the bounding circle of two different sprite objects// a - The SDL_Surface of the first object// x1 - The left position of the first object// y1 - The y center position of the first object// radius1 - The radius of the first object (-1 defaults to the average of the width and height of the surface)// b - The SDL_Surface of the second object// x2 - The x center position of the second object// y2 - The y center position of the second object// radius2 - The radius of the second object (-1 defaults to the average of the width and height of the surface)// offset - Allow some offset between the two objects (0 default)bool SDL_CollideBoundingCircle(SDL_Surface* a, int x1, int y1, SDL_Surface* b, int x2, int y2, int radius1, int radius2, int offset){	if(radius1 == -1) radius1 = (a->w * a->h) / 2;	if(radius2 == -1) radius2 = (b->w * b->h) / 2;	x1 = x1 + a->w/2;	y1 = y1 + a->h/2;	x2 = x2 + b->w/2;	y2 = y2 + b->h/2;	int distx = abs((int)(x1 - x2));	int disty = abs((int)(y1 - y2));	return(sqrt((distx * distx) + (disty * disty)) - radius1 - radius2 <= offset);}


You can reformat anything as much as you want, I don't mind. You'll have to re-do the documentation to fit into the SDL_Collide.h formatting. Remember that I'm not quite sure about using the second SDL_CollideBoundingCircle as sometimes a sprite can be only part of a SDL_Surface (tiles). I also have yet to compile these renditions, so don't freak out if it pops up a couple of errors.

[Edited by - Rob Loach on March 29, 2005 12:12:51 PM]
Rob Loach [Website] [Projects] [Contact]
As an aside on performance, It may be more efficient to square the radii than to take the square root of the distance.
there you go, a nice new updated SDL Collision library for the community SDL Collide (ive left the original library intact for beginners who may not know how to link, or just want to know the implementation). Feedback welcome.
Very cool, I like it .

One thing though, sometimes you have more then one image on a surface (tiled images), this would mean that the SDL_CollidePixel function wouldn't work. To have it work correctly with a tiled surface image, you'd have to have:
SDL_CollidePixel(SDL_Surface* image1,	int image1TileWidth, int image1TileHeight,	int image1TileX, int image1TileY,	int image1x, int image1y,	SDL_Surface* image2,	int image2TileWidth, int image2TileHeight,	int image2TileX, int image2TileY,	int image2x, int image2y);

... Lots of arguments.... hah, I'll have a stab at it once I get the time.
Rob Loach [Website] [Projects] [Contact]
This article may help you formulate your own algorithm.
Quote:Original post by Ravuya
This article may help you formulate your own algorithm.
Hmmmm, just doing some thinking out loud here... What if you created a bitmask and then made up a polygon to best fit the bitmask. You could then use that new polygon in the collision detection for some awesome speed in collision detection.
Rob Loach [Website] [Projects] [Contact]
I was looking at the SDL_CollidePixel function and noticed two things that I think might cause a problem.



After the nested For-Loops, you don't have a return value; just for the sake of type-correctness, it should probably return a 0 value.

In the nested for-loops you have the line:

if((SDL_CollideTransparentPixelTest(as , x-ax , y-ay)) && (SDL_CollideTransparentPixelTest(bs , x-bx , y-by)))				return 1;


Shouldn't this be:

if((!SDL_CollideTransparentPixelTest(as , x-ax , y-ay)) && (!SDL_CollideTransparentPixelTest(bs , x-bx , y-by)))				return 1;


If both overlapping pixels are not transparent, then a collision has occurred.

Just thought I'd mention it,
Shaun
Hi,

I know this is a long time since the last post, but I'm replying in case someone else stumbles across the thread.

Another nice efficient way to determine collisions is to define a list of points representing a collision polygon in your sprite class.
You pass this point list along with the point to check for into a function which does some cool stuff.
This function should loop through the list of points in pairs.
you determine the angle between the 2 collision poly points and the single point your checking against.
Once you've checked every pair of points in the list, if all the angle added together = 360 degrees then you have a collision.
It's nice to see basic year 7 maths coming back into the picture ;)

This is only to check if a single point entres a polygon, but some simple tweaking could have you have you passing more info into the collision routine if needed.

Anwyay, I though it may interest someone.

Have fun

This topic is closed to new replies.

Advertisement