Simulate collision between two balls of equal mass?

Started by
8 comments, last by squiller 19 years, 2 months ago
Hello all, Have been developing an Air Hockey game in C# and have only really gotten round to the idea of angles / collisions etc. Basically, the user controls the paddle (an ellipse) with the mouse. The puck is just an ellipse also. The puck can sense if a collision occurs (the paddle is inside it) so it's just the matter of figuring out how to simulate a realistic collision (i.e - in the opposite direction to which it was hit from and at a suitable speed). Any tips / advice on how to implement this would be great! Thanks in advance. Brian PS - I have it going the right direction using this code but at an unrealistic speed.

public void Player1Collision()
{
    x_vel = puck_x - paddle1_x;
    y_vel = puck_y - paddle1_y;
}

Advertisement
Simulate collision between two balls...

It must hurt badly ! :)

(sorry I couldn't resist ... sometimes... childish jokes don't hurt)
Try this:

//#define MIN(A, B) (((A) < (B)) ? (A) : (B))int Distance2D(int X, int Y){    X = abs(X);    Y = abs(Y);    int Distance = MIN(X, Y);    return (X + Y - (Distance >> 1) - (Distance >> 2) + (Distance >> 4));}//void Player1Collision(float PaddleForce){    float NormalX = puck_x - paddle1_x;    float NormalY = puck_y - paddle1_y;    float Distance = Distance2D(NormalX, NormalY);    if(Distance <= 2.0f * puck_Radius)    {        NormalX /= Distance;        NormalY /= Distance;        x_vel = (NormalX - -NormalY) * PaddleForce;        y_vel = (NormalY - NormalX) * PaddleForce;    }   }
Cheers for the very useful code, UltimaX.

But your code has made me realise how inexperienced i am in the area of Game Programming and physics as:

(a) i have used no float types.. only ints.
(b) i have no idea what you mean by
#define MIN(A, B) (((A) < (B)) ? (A) : (B))

(c) i have not even calculated a radius with my ellipses (balls)

I think the only one for you and others to understand my plight is for me to post my entire source code. I don't want to do that as it's messy, it's a pain in the ass for people to try and read through and it's unnecessary.

I don't want to pester you people by posting my entire source code and asking you to step through every little fault. It's unfair and like i said, it's un-necessary.

Thank you for the help anyways. It's much appreciated.

PS - Bender.. i would have made that joke if you didn't think of it first! :)
Quote:#define MIN(A, B) (((A) < (B)) ? (A) : (B))

Is just a macro for:
int Min(int A, int B){    if( A < B)        return A;    else        return B;}


Quote:The puck can sense if a collision occurs (the paddle is inside it) so it's just the matter of figuring out how to simulate a realistic collision (i.e - in the opposite direction to which it was hit from and at a suitable speed).


That is a physics question of which you will need to use vectors for "realisitc" collisions. I am underqualified to explain, but maybe someone else can. The idea is that the puck will have a direction and magnitude it is traveling. When the paddle hits it, it too will have a direction and mass. I am thinking if you add the vectors, you will get a resultant of which tells the magnitude and direction it *should* go in. I'm sorry that I do not kave any examples of it, but maybe you can do some research into it as well.

- Drew
NM, someone answered first. :P
-Kramy
Drew..

I think i got an example using vectors on how to simulate a collision between two balls (no jokes, Bender! :D).

But i think it's in C.. can anyone convert this to C# as can't find ways to implement DotProd or Normalise in C#.

void collision (void){// ball movement (Yes?)x1 += xVect1;y1 += yVect1;x2 += xVect2;y2 += yVect2;// test for collisionif (distance > radius1 + radius2){return;}// if we get here, the balls have collided,// so we do the collision calculationsxVelocity = xVect2 - xVect1;yVelocity = yVect2 - yVect1;// NormalizeNormal (x1 - x2, y1 - y2, normal);approach = DotProd(normal[0], normal[1], xVelocity, yVelocity);// calculate velocity changexNewVect = normal[0] * approach;yNewVect = normal[1] * approach;// change velocitiesxVect1 += xNewVect;yVect1 += yNewVect;xVect2 -= xNewVect;yVect2 -= yNewVect;}
To your first questions:
#define MIN(A, B) (((A) < (B)) ? (A) : (B))//--As Drew pointed out:int Min(int A, int B){    if(A < B)    {        return A;    }    else    {        return B;    }    //--Or like the macro    //-- return (A < B ? A : B)}//--But the macro will also accept other data types like floats, longs, etc.//--Exampleint Min(float A, float B){    if(A < B)    {        return A;    }    else    {        return B;    }    //--Or like the macro    //-- return (A < B ? A : B)}//--Etc.



Quote:
i have used no float types.. only ints.

You really should be using floats, you will get more precise results.


Quote:
i have not even calculated a radius with my ellipses (balls)

For 2D, I usually just guess about what the radius qould be. Try 5, if the collision occurs before it hits the paddle, try 4. If the collision is furthur inside the paddle then try 6. Just keep playing until you get it. It shouldn't be too big of a hassle since there is not going to be hundreds of objects.


Quote:
That is a physics question of which you will need to use vectors for "realisitc" collisions. I am underqualified to explain, but maybe someone else can. The idea is that the puck will have a direction and magnitude it is traveling. When the paddle hits it, it too will have a direction and mass. I am thinking if you add the vectors, you will get a resultant of which tells the magnitude and direction it *should* go in. I'm sorry that I do not kave any examples of it, but maybe you can do some research into it as well.


This is what my first example does in a very simple manner. It's not a true reaction, but for a pong game it will give justified results. If you have VB ans want to see another style look at the demo I made 3 years ago:

(Kinetic Collision Responce)
If you only see only the lines being drawn and nothing but black (Device failed to create) then change D3DSWAPEFFECT_DISCARD to D3DSWAPEFFECT_FLIP in the XEngine class and make sure D3DPP.MultiSampleType is D3DMULTISAMPLE_NONE.
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=36081&lngWId=1



To your last question:
I have never programmed in C#, but here's the Dot Product and Normalize functions (Didn't see them in the source you posted)

DotProduct:
////--If you use vectorsfloat DotProduct(const VECTOR2* Vector1, const VECTOR2* Vector2){    return ((Vector1->X * Vector2->X) + (Vector1->Y * Vector2->Y));}////--If you don't use vectorsfloat DotProduct(const float Vector1_X, const float Vector1_Y, const float Vector2_X, const float Vector2_Y){    return ((Vector1_X * Vector2_X) + (Vector1_Y * Vector2_Y));}


Magnitude (For Normalize):
////--If you use vectorsfloat Magnitude(VECTOR2* Vector){    return sqrtf((Vector->X * Vector->X) + (Vector->Y * Vector->Y));}////--If you don't use vectorsvoid Magnitude(float VectorX, float VectorY){    return sqrtf((VectorX * VectorX) + (VectorY * VectorY));}


Normalize:
////--If you use vectorsvoid Normalize(VECTOR2* Vector){    float Magnitude = 1 / Magnitude(Vector);    Vector->X *= Magnitude;    Vector->Y *= Magnitude;}////--If you don't use vectorsvoid Normalize(float VectorX, float VectorY){    float Magnitude = 1 / Magnitude(VectorX, VectorY);    VectorX *= Magnitude;    VectorY *= Magnitude;}
Cheeers for all the help everyone!

Am trying to implement it right now but very busy with lots of other stuff.

Little things are irritating me though..

Such as the variables x1, y1, x2, y2 - the source code above for void collision (void) is the only code that was available so i have no fit of the context for those variables.

Will work and report when i'm finished (or more than likely, when i'm stuck)

PS - Am taking your advice and am trying to make everything floats.
Am having some problems implementing it in. I'm using floats.. not too sure how to make / use the vectors. Here's my code so far. Can anyone suggest ways to change it? Remember, i had the angles working. It's just an appropriate speed i require. By the way, it checks for a collision between it goes into Player1Collision() method. All you need to know is:
- puck_x and puck_y are the x and y co-ordinates of my puck.
- paddle1_x and paddle1_y are the x and y co-ordinates of my paddle
- x_vel and y_vel are the velocity of the x and y co-ordinates on the puck.

Any suggestions / tips (no matter how big or small) are much appreciated as i'm really not too sure of this area of Vectors / Normalizing etc.

Thanks in advance.

Brian

private void Player1Collision()		{			puck_x += xVect1;			puck_y += yVect1;			paddle1_x += xVect2;			paddle1_y += yVect2;						x_vel = paddle1_x - puck_x;			y_vel = paddle1_y - puck_y;			// Normalize			Normalize(puck_x - paddle1_x, puck_y - paddle1_y);			float approach = DotProduct(VectorX, VectorY, x_vel, y_vel);			// calculate velocity change			xNewVect = VectorX * approach;			yNewVect = VectorY * approach;			puck_x += xNewVect;			puck_y += yNewVect;			paddle1_x -= xNewVect;			paddle1_y -= yNewVect;		}		void Normalize(float VectorX, float VectorY)		{			douVectX = Convert.ToDouble(VectorX);			douVectY = Convert.ToDouble(VectorY);			//float magnitude = 1 / Mag(VectorX, VectorY);			double magnitude = 1 / Mag(douVectX, douVectY);			double doubleMag = Convert.ToDouble(magnitude);			douVectX *= magnitude;			douVectY *= magnitude;		}		float DotProduct(float Vector1_X, float Vector1_Y, float Vector2_X, float Vector2_Y)		{			return ((Vector1_X * Vector2_X) + (Vector1_Y * Vector2_Y));		}		public double Mag(double VectorX, double VectorY)		{			return Math.Sqrt((douVectX * douVectX) + (douVectY * douVectY));		}

This topic is closed to new replies.

Advertisement