Making gravity fun: adding black holes to Shoot The Rocks, my version of Asteroids

Well, it’s been a while (!) since my last blog post here but, you know, life intervenes. Still, I’ve started working on the site and improving the games again.

I had this idea that I wanted to inject a little chaos and variety into Shoot The Rocks by adding black holes with associated gravity effects. This is something the original Asteroids didn’t have, and I don’t believe they’re in Asteroids Deluxe either. Still, I thought they might make for a fun addition.

If you want to jump straight in an see what effect this has all had on the game, just click here to play.

I want the classic version of the game to be quite close to the original arcade game so black holes only appear in the modern game variant. (I’ll probably add satellites to both classic and modern variants though because Shoot The Rocks is more like Asteroids Deluxe than the original Asteroids!)

Whilst black holes didn’t take ages to implement - really only a couple of afternoons - the road wasn’t totally straight. Much of the time was spent tweaking behaviour until it felt right: it’s more important for any game mechanic I add to be fun than it is for it to be realistic.

Gravity is obviously a real phenomenon so I did start off with a fairly realistic model, in the form of Newton’s Law of Universal Gravitation:

\[F = G\frac{m_1m_2}{r^2}\]

Where:

  • \(F\) is the force in Newtons
  • \(G\) is the gravitational constant
  • \(m_1\) is the mass of our black hole
  • \(m_2\) is the mass of whatever other game object we’re interested in
  • \(r\) is the distance between the black hole and the other object (Strictly, I believe, it’s the radius of the circle whose origin is the centre of mass of the black hole and whose edge would intersect the centre of mass of the other object, or vice versa. Details, details, etc.)

In simple terms, the gravitational force between two objects:

  • Is proportional to both their masses (actually to the product of their masses)
  • Gets weaker the further apart the objects are: i.e., it’s inversely proportional to the square of the distance between them (known as an inverse square law)

Granted, I could have gone more realistic, but worrying about relativity or quantum gravity in a game based on something as inherently unrealistic as an homage to Atari’s Asteroids is clearly ludicrous, and Newton’s law has the advantage of being simple to get to grips with.

Also, I kind of knew from the outset that any changes to increase the fun factor would most likely to simplifications and corners cut, so it makes sense to start off with something simple to begin with. We need to get to the point where gravity effects feel like they fit in with the rest of the game which, to begin with, has very simple mechanics.

The main things to grasp are that the heavier objects are, the stronger the gravitational force between them, and the closer together they are the stronger the force is. The reverse is also true.

Hopefully that’s fairly intuitive and, as you’ll see, the specifics of the equation aren’t really that important from a playability and fun perspective.

Something else to mention is that I want gravity to affect most, if not all, objects on screen when a black hole is present:

  • The player’s ship
  • Asteroids
  • Bullets
  • Flying saucers (and other enemy craft that we might eventually implement)
  • Particles
  • Any power-up collectables we implement

Let’s get down to business and talk about how I made this work.

Simplification, simplification, simplification

Firstly, we’re going to assume that the mass of every object other than the black hole is 1. This simplifies Newton’s law to:

\[F = G\frac{m_1}{r^2}\]

Secondly, we’re going to assume that the gravitational effect of these objects on the black holes, and on eachother, is zero. I.e., black holes are the only objects that exert any gravitational influence. This massively reduces the number of calculations we need to perform.

Thirdly, as I mentioned, G is the gravitional constant. This is a very small number indeed: approximately \(6.674\times10^{-11} m{^3}\cdot kg^{-1}\cdot s^{-2}\). It’s kind of aggro so we’re just going to throw it away and pretend it never existed, which yields:

\[F = \frac{m_1}{r^2}\]

We’re also going to bin off the concept of force, and substitute acceleration straight in there.

\[A = \frac{m_1}{r^2}\]

And this is really where I started with my implementation. I also precalculated everything and chucked it in a lookup table because, of course, we need to separate acceleration along the x and y axes, which requires some trigonometry.

Still, what I found sticking strictly to the inverse square law from Newton is that the gravitational influence of the black holes fell off too quickly. I could, of course, increase the mass of the black holes, but this led to absolutely out of control acceleration of objects very close to them, which also wasn’t what I wanted.

This meant I tried the following:

\[A = \frac{m_1}{r}\]

I.e., rather than an inverse square law, I simplified to a basic inverse law. Unfortunately this now meant that the gravitational effects were felt too strongly on more distant objects, which in practice was equally undesirable, and felt kind of weird.

In the end, after a bit more fiddling around, I settled on the following:

\[A = \frac{m_1}{r^{1.5}}\]

I.e., an inverse square law is an instance of a more general inverse power law, and what I’ve done here is simply to reduce the power to a level where for our purposes it gives a nice balance of stronger affect at close range versus still having some effect at greater distances.

And that means we now have some sort of pseudo-gravity effect that injects some chaos and fun, whilst also working well with the three sizes of black hole I’ve implemented (small, medium, and large). Large black holes are now just about powerful enough to capture flying saucers, but not powerful enough to permanently capture the player’s ship, which is really what I wanted.

They also exert a pleasing, but not out of control ridiculous influence on all other game objects.

As I write this I’m sat approximately 12 miles from Trinity College in Cambridge where Newton was a fellow. Were he still alive, and aware of what I’ve done here (especially given the computing power available even within the average smartphone), I imagine he might have a few stern words to say to me the next time I venture into town.

Still, if you’re of a more forgiving bent and want to have some fun by playing the game and seeing how this has all worked out then click here to play.

Enjoy!

//- For IE11, so that the GDPR script won't break //- Information on use of nomodule came from: //- https://gist.github.com/mgol/560a942d25ee8ab18349