Spherical collision in JavaScript

Collision detection is essential for most games. This article discusses an implementation for JavaScript.

Nearly every game requires some collision detection - and spherical collision detection is among the most general and complex types. Rectangles on rectangles is quite easy if we do not take physics into account. Spheres on (fixed) rectangles are easy in general. Problematic are cases where objects are reflected on spheres. Here we have to take several properties into account, like the norm vector, the velocity vector and the various sizes.

In a very specific approximation we set one of the spheres as being fixed. Otherwise we have to take into account their masses (in such cases the masses determine the ratio of being reflected, i.e. a mass of infinity for a sphere will result in that sphere not changing its velocity, if any, at all). What could be done is the following algorithm:

  • Calculate the angle between the centers of the two spheres
  • Place the norm on it (it is perpendicular to the line which connects the centers of the two spheres)
  • Transform the coordinate system to have its origin at the intersection of connecting line to the fixed sphere
  • Rotate the coordinate system in such a way that the norm is the horizontal axis
  • Perform the reflection on the velocity vector
  • Transform back to the original coordinate system

This can be condensed to compute the following:

  • Compute the normalized line vector L (x being delta x, y being delta y)
  • Compute the normalized velocity vector (the total velocity is given by V)
  • Compute the dot product A of the two (remember, this is like taking the cosine, i.e. if both are in the same direction we have the result of 1, otherwise if both are perpendicular we get 0).
  • Finally we shift our velocity by subtracting 2 * A * V * L.

That's it pretty much. The given demo will go into more details. In JavaScript the routine looks like:

function sphereCollide(source, velocity, target) {
	var delta = { x: target.x - source.x, y: target.y - source.y };
	var normD = Math.sqrt(delta.x * delta.x + delta.y * delta.y);
	var normV = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y);
	var v = { x: velocity.x / normV, y: velocity.y / normV };
	delta.x = delta.x / normD;
	delta.y = delta.y / normD;
	var alpha = delta.x * v.x + delta.y * v.y;
	var g = 2 * alpha * normV;
	delta.x = g * delta.x;
	delta.y = g * delta.y;
	return {
		x: velocity.x - delta.x,
		y: velocity.y - delta.y,
		alpha: alpha
	};
}

Usually we first want to detect if the two spheres actually collide. This is actually much simpler to write for spheres than for any other object. The code could be written like:

function intersects(x1, y1, r1, x2, y2, r2) {
	var x = x2 - x1;
	var y = y2 - y1;
	var d = Math.sqrt(x * x + y * y);
	return d <= r1 + r2;
}

That's it! The demo contains a neat canvas playground, which can be used to see the collision detection and reflection in action.

Created .

References

Sharing is caring!