How to calculate bounce angle?

I think an easier way to do this is to use the velocity of the missile instead of calculating angles. Say you have a missile that has xVelocity and yVelocity to represent its movement horizontally and vertically. Those velocities can be positive or negative to represent left, right, up, or down.

  • If a missile hits a top or bottom border reverse the sign of the yVelocity.
  • If a missile hits a left or right border reverse the sign of the xVelocity.

This will keep the movement in the opposite axis the same.

Borrowing the image from ChrisF's answer, let's say the missile starts out at position I.

Angle of Reflection

With the xVelocity and yVelocity both being positive (in 2D graphics right and down are typically positive) the missile will travel in the direction indicated. Let's just assign values of

xVelocity = 3
yVelocity = 4

When the missile hits the wall at position C, its xVelocity shouldn't change, but its yVelocity should be reversed to -4 so that it travels back in the up direction, but keeps going to the right.

The benefit to this method is that you only need to keep track of a missile's xPosition, yPosition, xVelocity, and yVelocity. Using just these four components and your game's update rate, the missile will always get redrawn at the correct position. Once you get into more complicated obstacles that are not at straight angles or are moving, it will be a lot easier to work with X and Y velocities than with angles.


You might think that because your walls are aligned with the coordinate axes that it makes sense to write special case code (for a vertical wall, negate the x-coordinate of the velocity; for a horizontal wall, negate the y-coordinate of the velocity). However, once you've got the game working well with vertical and horizontal walls, probably the next thing you'll think is, "what about walls at arbitrary angles?" So it's worth thinking about the general case from the beginning.

In the general case, suppose your missile has velocity v and hits a wall with surface normal n.

Missile with vector v about to obliquely hit a wall with surface normal n.

Split v into components u perpendicular to the wall and w parallel to it.

Right-angled triangle with hypotenuse for v, short side u parallel to wall and long side w parallel to wall.

Where:

u = (v · n / n · n) n
w = vu

Here, v · n is the dot product of the vectors v and n. See the link for an explanation of how to compute it. The dot product n · n evaluates to the square of the length of the normal vector; if you always keep your normals in the form of unit vectors then n · n = 1 and you can omit the division.

After bouncing, the component of motion parallel to the wall is affected by friction f, and the component perpendicular to the wall is affected by elasticity, which can be given in the form of a coefficient of restitution r.

So the velocity after the collision is v′ = f wr u. In a perfectly elastic, frictionless collision, v′ = wu; that is, the motion is reflected about the normal at the point of collision, as in the diagram given in Bill's answer.

This approach works just the same in three dimensions too.

(Obviously this is a very simplified notion of bouncing; it takes no account of angular momentum or deformation. But for many kinds of video games this kind of simplification is perfectly adequate.)


For perfect particles (& light) the angle of reflection is equal to the angle of incidence, as illustrated by this diagram (from commons.wikimedia.org).

Angle of Reflection

The Wikipedia page on reflection is quite good at explaining how it works.

It's a little bit more complicated when you take into account the elasticity and materials of the object and the obstacles, but this is probably good enough for most applications.


I've had this problem, the only way I found was separating the axes of collision!

Try it:

x += velocity * Math.cos(angle * Math.PI /180);
y += velocity * Math.sin(angle * Math.PI /180);

if (x < 0 || x > canvas.width) {
     angle = 180 - angle;   
}
else if (y < 0 ||y > canvas.height) {
     angle = 360 - angle; 
}

I hope this helps you!

Tags:

C#

Physics

Xna