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\$
4
  • 1
    \$\begingroup\$ In game development, 'it seems to function correctly' is all you need. \$\endgroup\$ Commented Mar 25, 2012 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
    Commented Mar 25, 2012 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\$ Commented Mar 25, 2012 at 5:33
  • \$\begingroup\$ Possibly related: gamedev.stackexchange.com/questions/3430/… \$\endgroup\$
    – Tetrad
    Commented Mar 29, 2012 at 16:27

1 Answer 1

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\$
6
  • \$\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
    Commented Mar 25, 2012 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\$ Commented Mar 25, 2012 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
    Commented Mar 25, 2012 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\$ Commented Mar 25, 2012 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
    Commented Mar 27, 2012 at 5:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .