Developer Console

Screen Shake

Written in January 2018 by Nathan Ranney, the founder of game development studio Gutter Arcade.

Screen shake is a classic indie effect that is sure to beef up your impacts, explosions, sudden realizations, gunshots, and more. Setting up screen shake doesn't require a lot of work, but as you will see, there are a lot of nuances you can tweak to dramatically impact the feeling of it. This post assumes you are somewhat familiar with views in GameMaker.

Setup

Before we can start shaking the camera around, it is a good idea to initialize some variables that will help us control screen shake, and fine-tune it. The best way to handle this is to do so from a game controller type object. A game controller object is a persistent object that manages many parts of your game. Things like score, the camera, changing levels, controlling menus, and lots of other things can be controlled from your game controller object. If your project does not have a game controller, now would be a good time to add one. Then, let's initialize some variables.

Game controller create event

Copied to clipboard.

shake = false;
shakeDur = 5;
shakeForce = 1;

These three variables will let us easily manage the ferocity of our screen shake, and its duration. The first variable is used to turn the screen shake effect on and off. The second, shakeDur, is the duration the effect lasts. Finally, shakeForce, is how dramatic the shake effect is. Now we need to put these to use.

Game controller step event

Copied to clipboard.

if(shake){
    shakeDur --;
    view_xview += choose(-shakeForce,shakeForce);
    view_yview += choose(-shakeForce,shakeForce);
    if(shakeDur <= 0){
        shake = false;
        shakeDur = 5;
    }
}else{
    view_xview = approach(view_xview,0,0.3);
    view_yview = approach(view_yview,0,0.3);
}

I want to point out this approach script at the bottom. If you don't have the approach script, here it is. Create a new script, name it approach, and throw this code in there.

Approach script

Copied to clipboard.

/// approach(start, end, shift);

if(argument0 < argument1){
    return min(argument0 + argument2, argument1);
}else{
    return max(argument0 - argument2, argument1);
}

Quick shout out to Matt Thorson (Towerfall, Celeste) for this handy script that I have been using for years. This script takes a value, and shifts it towards another value by a set amount each frame. In the instance above, we are using it to reset our camera position back to zero, which is the default camera position. Now, back to the screen shake.

This is a pretty simple bit of code. First, we check to see if shake is true, and if it is, start counting down our shakeDur variable. Once shakeDur reaches zero, shake is set to false, and shakeDur is reset to its maximum value of five. While shakeDur counts down, we move the view around by adding shakeForce to it randomly. If you are unfamiliar with choose, it is pretty self explanatory. It simply chooses one of the arguments provided. In this case, it is choosing either shakeForce or negative shakeForce, so either one or negative one. This means our camera is moving around one pixel up, down, left, or right randomly every frame for five frames. Once shakeDur reaches zero and shake is no longer true, the view is reset back to zero by using the approach script.

Those are the basics of screen shake. If you run the game and you have set a button press or some action to set shake to true, you should get a fairly small screen shake. Here is an example from a little game I have been working on lately.

Tweaking the Variables

Now you have the basics in place. If you haven't already, take some time to mess with the shakeDur and shakeForce variables we created. See what happens if you increase/decrease those variables in the create event of your game controller object. Here are a couple of examples.

In the first animation, we have a shakeDur of 60 and a shakeForce of one. In the second animation, a shakeDur of five and a shakeForce of three.

You can also get a lot of mileage out of messing with the view_angle when shaking the screen. The setup for this is exactly like view_xview and view_yview above. It's fairly subtle in the animation below, but you can see how it adds just a little bit extra oomph to the shake.