Now that I’m gamplay-ing things up, let’s add some screen shake (and another excuse for posting more GIFs).
This is actually not the simplest topic out there (at least since I’m over-complicating everything) and I’ve given it some extra thought. Bad screen shake can even ruin a game. Good screen shake can enhance the experience. I believe good screen shake is subtle screen shake and subtle means a well-designed algorithm that doesn’t get in the way. If you remember that a game has screen shake, it probably had too much. I think part of the reason is because most games simply move the camera in a random location for a set period of time; however randomness ensures that all the bad extremes eventually pop out. Anyway, this is how I am going about it.
Firstly, my “shake” is a single spike in a random direction — camera briefly jumps there. A single event in the game (like the player getting hit) will only get a single spike. This is because my shake is short (both time- and distance-wise). Plus the events of the game (like fire a weapon) can happen in quick succession, thus producing multiple consecutive spikes anyway. A spike here means an offset from the camera in a random direction of a certain distance. This distance is determined by the shake amount by whatever source it comes from (fire pistol — small, jump on grenade — big).
Now, I can’t just send the camera to the “shake location”, as that’s a jarring jump. And who even knows what happens with multiple shakes… So I considered multiple ways of doing the math for this, but went with a “dampened spring” (which is totally not a term I made up). This is very similar to my weapon kick and reticle expansion, except better controlled and with some extra logic. I think a picture is at least some 100 words here, so this is how it goes:
There are two “moving parts” — the shake and the camera offset. The shake is simply the amount (and direction) in which the camera is supposed to move. The shake decays over time unless a new shake is applied. The camera then moves towards the shake position. It moves faster towards an active shake (shake distance > camera offset) than back towards the shake/player. This means initial camera spike is more abrupt, but return is more gradual. Sort of what you expect when you punch something elastic.
This is all parametrized for me to tweak:
And this looks like this (greatly exaggerated for visual purposes):
Another important point while designing this is that the screen shake can “survive” multiple shakes without any jarring jumps. This is a problem I’ve seen in other games where a new shake completely negates what the old one was doing. In my case, if a new shake appears, this just means a new target for the camera:
Additionally, I make sure that the random angle I choose for the shake is neither too close to or too far from the previous angle it jumped to:
This makes sure that the camera doesn’t stay put and it doesn’t just fly over the player to the opposite side. Sort of like when you hit a punching bag again, it will move to the side and not stay or somehow move in the opposite direction it was going. It’s almost impossible to notice in-game that there are no large angle jumps like this — it just “looks random”; but it would certainly be noticeable if there were occasional 180 degree jumps.
Here’s an in-game “player getting hit” shake that’s closer to the actual amount I would have:
You can see the single spike reasoning in action here: the player gets hit so many times, that there is no need for multiple shakes per hit. (Emergent gameplay… visuals or something.)
It’s almost sad to see all that math become so subtle no one will ever know it’s there. But, at the same time, I know that if I get this wrong, everyone will know it’s there.
I am also specifying the amount of shake different events apply, so I can change those as appropriate for gameplay:
In addition, each weapon gets its own extra multiplier when fired:
So, for example, a shotgun blast shakes the screen more than a pistol.
Finally, screen shake is one of those optional features that should be in game options, so I am having a selector for the amount of shake the game has (if not an actual option screen yet):
I considered doing like slider for this, but I’m pretty sure most players don’t care about such precision. Mostly, they just come to options to toggle the shake off or reduce it. A radio button for this seems like an easier, more intuitive choice than some sort of number, even if it’s a percentage.
I don’t yet have a whole lot of effects in-game that can cause screen-shake, like explosions and bosses and stuff. But once I do, I have a perfect feedback for those.
(Subtle) wee: