Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am making a Pong based game where a puck hits a paddle and bounces off. Both the puck and the paddles are Circles. I came up with an algorithm to calculate the resultant vector of the puck once it meets a paddle. The game seems to function correctly but I'm not entirely sure my algorithm is correct. Here are my variables for the algorithm:

Given:
velocity = the magnitude of the initial velocity of the puck before the collision
x = the x coordinate of the puck
y = the y coordinate of the puck
moveX = the horizontal speed of the puck
moveY = the vertical speed of the puck

otherX = the x coordinate of the paddle
otherY = the y coordinate of the paddle
piece.horizontalMomentum = the horizontal speed of the paddle before it hits the puck
piece.verticalMomentum = the vertical speed of the paddle before it hits the puck

slope = the direction, in radians, of the puck's velocity
distX = the horizontal distance between the center of the puck and the center of the paddle
distY = the vertical distance between the center of the puck and the center of the paddle

Algorithm solves for:
impactAngle = the angle, in radians, of the angle of impact.
newSpeedX = the speed of the resultant vector in the X direction
newSpeedY = the speed of the resultant vector in the Y direction


Here is the code for my algorithm:

int otherX = piece.x;
int otherY = piece.y;
double velocity = Math.sqrt((moveX * moveX) + (moveY * moveY));

double slope = Math.atan(moveX / moveY);
int distX = x - otherX;
int distY = y - otherY;

double impactAngle = Math.atan(distX / distY);

double newAngle = impactAngle + slope;
int newSpeedX = (int)(velocity * Math.sin(newAngle)) + piece.horizontalMomentum;
int newSpeedY = (int)(velocity * Math.cos(newAngle)) + piece.verticalMomentum;

for those who are not program savvy here is it simplified:

velocity = √(moveX² + moveY²)
slope = arctan(moveX / moveY)
distX = x - otherX
distY = y - otherY

impactAngle = arctan(distX / distY)

newAngle = impactAngle + slope
newSpeedX = velocity * sin(newAngle) + piece.horizontalMomentum
newSpeedY = velocity * cos(newAngle) + piece.verticalMomentum

My Question:
Is this algorithm correct? Is there an easier/simpler way to do what I'm trying to do?

share|improve this question

migrated from physics.stackexchange.com Mar 29 '12 at 0:28

This question came from our site for active researchers, academics and students of physics.

1  
In game development, 'it seems to function correctly' is all you need. –  Manishearth Mar 25 '12 at 2:01
    
I haven't attempted to dissect your code, but...a elastic circle--circle collision is easy looked at in the right way. It's the same old angle of impact equals angle of rebound you get with a circle--plane collision, only you measure relative their common tangent at the point of impact. If you want to include inelastic behavior or spin effect things get rather harder. –  dmckee Mar 25 '12 at 3:47
    
@dmckee not too much for inelastic, spin behavior makes it evil though(iirc angular impulse and friction come into play) –  Manishearth Mar 25 '12 at 5:33
    
Possibly related: gamedev.stackexchange.com/questions/3430/… –  Tetrad Mar 29 '12 at 16:27
add comment

1 Answer 1

up vote 1 down vote accepted

As I said in the comments, for games, all you need is "it seems to function correctly".

I'm not sure if your code is correct (looks a bit off, but I haven't looked at it too closely).

Here's a more efficient formula that avoids trig and square roots:

math formula

Simplifying into components, where:

distX equation, same for y:

In code:

 int otherX = piece.x;
 int otherY = piece.y;
 int distX = x - otherX;
 int distY = y - otherY;    
 double dotprod=(distX*moveX+distY*moveY)/(distX*distX+distY*distY)
 newSpeedX=2distX*dotprod+moveX
 newSpeedY=2distY*dotprod+moveY

For newAngle

AFAICT, you only need this variable for calculating the velocities, but if you need it for something else as well, you may use this:

newAngle can be calculated by:

newAngle calculation

Simplified,

simplified newAngle calculation

In code:

newAngle=arccos(dotprod*Math.sqrt((distX*distX+distY*distY)/(moveX*moveX+moveY*moveY)))

Or, you could use your old method to calculate newAngle, this one involves an inverse trig function and a square root, while yours involves two inverse trig functions--pretty much the same load on the computer IMO (both functions are solved via power series usually).

share|improve this answer
    
+1 Thank you for the answer, I'm going to use your algorithms to simplify my code, if nothing better comes up when its migrated ill give you the answer –  John Mar 25 '12 at 15:43
    
@John. No problem.. DavidZaslavsky is going to be inactive for this week, so I asked dmckee to do the migration... Just out of interest, do you need newAngle anywhere else in the code after this collision bit? If so, why? –  Manishearth Mar 25 '12 at 15:51
    
@Manishhearth i might use it later depending if i want the player to be able to spin the ball, but I'm not sure if I'm going to add that or not. I left it in the question just in case. –  John Mar 25 '12 at 15:54
    
In that case its better to just use a collision simulating API. The people at gamedev may know a few. (I think Box2D may work, but I'm no expert) –  Manishearth Mar 25 '12 at 16:23
    
thank you for all of the info, its helped me out a lot! –  John Mar 25 '12 at 16:46
show 3 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.