4
\$\begingroup\$

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?

\$\endgroup\$

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
    \$\begingroup\$ In game development, 'it seems to function correctly' is all you need. \$\endgroup\$ – Manishearth Mar 25 '12 at 2:01
  • \$\begingroup\$ 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. \$\endgroup\$ – dmckee Mar 25 '12 at 3:47
  • \$\begingroup\$ @dmckee not too much for inelastic, spin behavior makes it evil though(iirc angular impulse and friction come into play) \$\endgroup\$ – Manishearth Mar 25 '12 at 5:33
  • \$\begingroup\$ Possibly related: gamedev.stackexchange.com/questions/3430/… \$\endgroup\$ – Tetrad Mar 29 '12 at 16:27
1
\$\begingroup\$

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 http://mathbin.net/equations/91525_0.png

Simplifying into components, where:

distX equation http://mathbin.net/equations/91527_0.png, same for y:

http://mathbin.net/equations/91527_1.png

http://mathbin.net/equations/91527_2.png

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 http://mathbin.net/equations/91528_0.png

Simplified,

simplified newAngle calculation http://mathbin.net/equations/91529_0.png

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).

\$\endgroup\$
  • \$\begingroup\$ +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 \$\endgroup\$ – John Mar 25 '12 at 15:43
  • \$\begingroup\$ @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? \$\endgroup\$ – Manishearth Mar 25 '12 at 15:51
  • \$\begingroup\$ @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. \$\endgroup\$ – John Mar 25 '12 at 15:54
  • \$\begingroup\$ 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) \$\endgroup\$ – Manishearth Mar 25 '12 at 16:23
  • \$\begingroup\$ This seems like its not getting migrated, therefore you helped me the most so ill give you the credit for the answer \$\endgroup\$ – John Mar 27 '12 at 5:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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