Skip to main content
gamedev.net
🔒 Locked

Basic Collision Detection Problem

Started by egg100 2 replies 600+ views
Original Post
egg100
egg100
This must be a fundamental issue in basic collision detection. I'm trying to make a snooker game and its all working fine except for a major issue with the ball collisions. I iterate through every ball, and create a vector between 2 balls. If the vector magnitude is greater than 2*radius then a collision has happened. All very simple. Problem is that after a collision, the collided balls are closer than 2*radius and do not always seperate in time for the next collision detection. They therefore get stuck permanently colliding with each other. Is there a standard way of getting around this problem?
extralongpants
extralongpants
What you are doing is testing for static object-object intersection. What you are not taking into account is the fact that the balls are moving. This can complicate the collision detection process a lot, especially if both balls being tested for collisions are moving. I believe a moving sphere or circle can be represented as a 2d or 3d capsule, but you should do some research to find out more.

If your balls are not moving too quickly (ie. there is no chance of a ball going straight through another ball), you can get away with static-static intersection tests by adjusting the position of the balls when an intersection is detected, before you do anything physics related or stop the ball. If only one ball is moving, this is very easy: After detecting the collision, keep the vector you used between the two balls. Set its length to 2*radius. Then: MovingBall.Center =StaticBall.Center +DistanceVector (where DistanceVector is the vector between the two balls). This is not all that accurate, but it is very fast and works well in most situations.

After that, you can apply forces to the ball or stop it or whatever it is balls do in a snooker like game :). If both balls are moving, then you have to take their velocities into account. You should be able to find articles on such collision prevention and handling on the Internet.

Hope that helps; good luck :)
egg100
egg100
Ok that seems to make sense.
I dont think there's a chance of the balls going fast enough to completely miss each other so i'll try and adjust the ball positions so the distance is 2*rad before I do anything else. I suppose the difficult thing is that if both balls are moving at different vels then adjusting thier positions acuarately so they are 2*rad apart. I'll give it a go.
Thanks very much for the tip.
adamggg
adamggg
I did something like this to test for moving ball collisions in a billiards game:

**(For some reason all my 'plus' signs disappeared in the preview, so I replaced them with '?')


//update positionball_a[XPOSITION] ? =ball_a[XVELOCITY];ball_a[YPOSITION] ? =ball_a[YVELOCITY];ball_b[XPOSITION] ? =ball_b[XVELOCITY];ball_b[YPOSITION] ? =ball_b[YVELOCITY];//compute the distance between ball centersfloat nabx = (ball_b[XPOSITION] - ball_a[XPOSITION] );float naby = (ball_b[YPOSITION] - ball_a[YPOSITION] );float length = sqrt(nabx*nabx ? naby*naby);// is there a collision?//3*RAD is an experimental value, the faster balls travel the bigger it should be//if balls are within 3*radius, test to see if they collidedif (length <= 3*RAD){	//first put them back where they were at the beginning of the frame	ball_a[XPOSITION]-=ball_a[XVELOCITY];	ball_a[YPOSITION]-=ball_a[YVELOCITY]; 	ball_b[XPOSITION]-=ball_b[XVELOCITY];	ball_b[YPOSITION]-=ball_b[YVELOCITY];	double counter=0;	double steps=MAX_VELOCITY;		//now step through their positions in increments of 1/MAX_VELOCITY	while(counter < steps){		ball_a[XPOSITION]?=(1/steps)*ball_a[XVELOCITY];		ball_a[YPOSITION]?=(1/steps)*ball_a[YVELOCITY];		ball_b[XPOSITION]?=(1/steps)*ball_b[XVELOCITY];		ball_b[YPOSITION]?=(1/steps)*ball_b[YVELOCITY];		//compute the distance again		nabx = (ball_b[XPOSITION] - ball_a[XPOSITION] );		naby = (ball_b[YPOSITION] - ball_a[YPOSITION] );		length = sqrt(nabx*nabx ? naby*naby);						//if they are 2*radius or less, there is a collision at the current positions		//so break out of the loop		if(length<=2*RAD){			break;					}		counter?=1;	}//end while loop	//if length is 2*radius or less, process the collision	if(length<=2*RAD){		process_collision();	}}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.