Gravity Ace

Engine sound breakddown

Gravity Ace is a game about flying a space ship. From the beginning I knew that the sound that the ship makes would have to be interesting. At the same time, it needed to be unobtrusive and, to some extent, blend into the background because it would be heard so often.

I think I achieved both goals. To make it interesting, I created 3 different samples: starting up, running, and shutting down. I usually create sound effecs in Tracktion Waveform using multiple samples and effects until I get it sounding just the way I want. I bake effects right into the samples themselves instead of using Godot’s bus effects.

And to keep it in the background I designed the samples to sound smooth and blend well together and kept their volume low. There are no harsh blips, clicks, pops, or other high frequency notes in any of the samples. They all have a similar low frequency and sound nice together.

How it works

First, play the video (unmute your speakers) to get a quick overview of how it sounds and works:

Here’s the code for handling player input and activating the animations and sound. $thrustIn, $thrustLoop, and $thrustOut are each AnimationPlayer nodes with animations that control the volume of each sound effect. The in animation starts the sound effect and ramps the volume up. The out animation ramps the volume down and then stops the sound effect playback.

$thrusting_last_frame keeps track of the status of the engine from frame to frame so that we know if we need to turn the engine on or off.

var thrusting_last_frame = false

func _phyics_process(delta):
    var thrust = false

    # if Input.is_action_pressed(...):
    #   Your own input handling code would go here.
    #   Mine sets thrust = true when the player wants
    #   to move and thrust = false when they stop.

    if thrust:
        if not thrusting_last_frame:
            $thrustIn.play('in')

        if not $thrustLoopSfx.playing:
            $thrustLoop.play('in')

        if $thrustOutSfx.playing:
            $thrustOut.play('out')

        thrusting_last_frame = true
    else:
        if thrusting_last_frame:
            $thrustLoop.play('out')
            $thrustOut.play('in')

            if $thrustInSfx.playing:
                $thrustIn.play('out')

        thrusting_last_frame = false

When the player wants to move, the thrustIn and thrustLoop effects will fade in; and if thrustOut is playing then it will fade out.

If the player keeps holding the input down then thrustLoop will keep playing in a loop while thrustIn and thrustOut stop.

Then when the player stops moving, thrustLoop will fade out and thrustOut will fade in; and if thrustIn is playing then it will fade out.

This isn’t too complicated and gives you a nice range of dynamic sounds depending on the engine state and how long the player has been running the engine. You just need 3 samples to use this technique. It’s important that the sound samples themselves are well crafted and blend together nicely. And it’ll take some time and iteration to fine tune the samples and when they play.

It’s also possible to layer on even more effects or change the character of sounds playing depending on any number of factors like input, health points, or run time. Imagine a character who makes a panting sound while they run but starts to breathe more heavily as they tire.

I hope this helps you in your game development journey! Join my Discord or follow me on Twitter if you have questions (links below).

Published October 13, 2019

More devlogs...

Game jams for beginners

3 methods for screen shake in Godot Engine

Creating a custom Fixed Joint in Godot Engine

More...