Every discussion of game audio invariably touches on the essential concept of repetition. And depending on the specifics of the topic, repeated sounds can be viewed from both positive and negative perspectives,
PRO: "Use that jump sound as often as you can so as to reduce overall file size."
CON: "Be careful! That explosion sound starts to sound very tedious after the bajillionth enemy ship has been destroyed…"
Depending on the context, arguments both for and against repeated sounds have merit. This tutorial falls in the against camp.
Why Randomization
Many game genres utilize some sounds more than others. Adventure games are likely to use lots of walking or footstep sounds, shooters have an arsenal of blazing gunfire, platformers have lots of jumping…you get the point. In order to break up the potential monotony players often experience when hearing the same sound play when the same action is required time and time again, it’s helpful to use randomization.
The concept is very simple: when an in-game event occurs, play a sound. But not the same sound. Rather, randomly choose from a selection of available sounds and play that one. Repeat with another, and another, and another… Yes, the events go on indefinitely but with sufficient variety in your bank of available sounds you can create the impression that every event is unique. This step sounds different than the one before. And the one before that. And it will sound different from the next.
In our physical world there are hundreds (perhaps thousands) of variables that could factor into the sound of a single footstep—What shoes am I wearing (if any)? What surface is beneath me? Am I running or walking? What do I carry with me? Is the ground wet or dry? How wet? What made it wet? This could go on forever. The point is that in a constructed game world we know what all of the variables will be and (thankfully) can use those as limiting factors to define the scope of our design work. For example, if you know players will encounter a vast grassland with a few small streams, you would need to prepare a large- or medium-sized bank of "grassy" footsteps and a smaller bank of steps with some mud squelches and splashes of water.
There’s more to say on the matter, but this is a tutorial not a game audio theory lesson, so let’s dive in.
How to do it
First, you must import some sounds.
1. Right-click on the Sounds folder (in the Project tab) and choose Import Sounds.
2. Use the Import Audio button or in Construct 3 simply Drag & Drop files from your computer into the designated area.
3. Construct3 will display "Complete" beside each sound in the Encoding column; then click Import.
For Construct 2, simply choose the encoding quality you want to use, click Import, and then OK. As with all audio, encoding is a tradeoff between quality and file size. 96 kbps will load more quickly but may have noticeable signs of compression; 192 kbps will sound best but will add to load time. If you’re not sure, go with the highest setting and gauge the performance.
With either method, the imported sound files are now available within Construct.
4. The last step is to add an Audio object to your Project. Double-click your Layout, choose Audio, and click Insert. This tells Construct that you will need to play sound files in your game. If you don’t do this you won’t be able to do much with those imported sound files!
As you continue to work, refer to this screenshot. Your Event sheet will look something like it when your randomization is finished.
With sounds now available in your project, it’s essential to organize them so that they can be cued programmatically. For this we will use an Array.
1. Double-click in your layout to create an Array.
2. Find the new Array in the Project tab (in the Object types folder) and give it a name. For this lesson (because we’re using footsteps as an example) I will use the name steps.
3. Go to your Event sheet and (if there’s not one in your game already) add a new System > On start of layout event.
4. Click Add action for the (new) On start of layout event, choose your Array (in this example, steps, and click Next.
5. Choose Set at X and click Next.
6. In the X field enter the number 0. In the Value field enter the name of your first randomized sound file as a string (inside quotation marks, as in "step-01"). This assigns the step-01 sound file to the first slot of your Array. Be sure not to use the file extension! Omit .m4a or .ogg if using Construct 2 and .webm in Construct 3.
Details on the .webm format are here.
7. Repeat this last step for the remaining sound files. For each new Set at X action, increment the value of the X field by 1 so that each subsequent sound is added to the next slot of the Array. Alternately, you can select the first action, press CTRL+C to copy; CTRL+V to paste, and then update the X and Value fields accordingly.
Next, we need to create a global variable. Right-click in your Event sheet and choose Add global variable. Give it the name ranStep (or another name meaningful to your use of this technique). Set Type to Number and Initial Value to 0.
The final step is to create an Event and Actions that put all of these components together to play your sounds in a random fashion. In the provided .capx file, the player sprite walks across a dirt terrain and the steps Array is filled with gritty footfall sounds. Sprites, Events, Conditions, and Actions of your game are likely to be different, so this step will probably require a somewhat different approach to cue the randomized sounds in the way it demands. However, in the provided example, the audio works like so:
The character sprite has the 8Direction Behavior attached to it. An Event that checks 8Direction is moving will yield true if the sprite is in motion and false if it is still: This is part of our sound trigger.
The other part requires a System Event to be coupled with 8Direction is moving. That specific Event is System > Every X seconds. When these Events are paired it means that the game will only trigger a sound at the interval specified by Every X seconds while the player sprite is also in motion. In a way, this interval sets a tempo for the footsteps. In the provided .capx example 0.4 seconds sounded right based on the speed of the 8Direction Behavior. To get everything looking and sounding right in your game it will take some fine-tuning. Experiment with higher and lower values until the sound and animation create the effect you want and don’t be too concerned if your game looks or sounds weird at first.
There are two Actions for this Event and they must be ordered correctly. Complete the first with these steps:
1. Double-click Add Action.
2. Double-click System.
3. Double-click Set value. These three steps essentially create a System Action that will set the value of a variable.
4. Choose ranStep for your Variable.
5. For Value you will need to enter the expression floor(random(steps.Width)). This may look complicated if you’re new to computer languages, but the concept is very simple. steps.Width will return the number of items (.Width) in the steps Array. In our case it will return the number 5 since there are five sound file names stored in our Array. That number then sets the range for a random() function. random() will return a floating point (decimal) number between 0 and one less than the specified range. In this case, we will get something between 4.999 and 0. Finally, floor() rounds that number down to the next integer. If random() produces 2.3, floor() will yield 2. In this example, with a potential maximum of 4.999, floor() will yield 0, 1, 2, 3, or 4 and assign that value to ranStep.
6. Within the same Event, double-click Add Action; double-click Audio; click Play (by name) and click Next.
7. For Folder choose Sounds.
8. For Audio file name, replace the default quotation marks with the expression steps.At(ranStep). This line is what makes the "magic" of randomization audible. Remember how ranStep will be 0, 1, 2, 3, or 4? In this line, our code uses that value as an argument for At() to retrieve a sound from our Array. 0 would give us the first sound of the array; 4 the last, and so on.
9. Set Loop to not looping and Volume and Tag to meet the requirements of your game.
Update
There is a cleaner alternative to the steps outlined above that uses Construct's built-in System Expression choose(). This combines the functionality of the Array and Random() Expression into a single Action.
1. Double-click Add Action.
2. Double-click Audio.
3. Double-click Play (by name). Enter the following into the dialogue box:
Folder: Sounds
Audio file name: choose("step-01","step-02","step-03","step-04","step-05")
4. Set Loop to not looping and Volume and Tag to meet the requirements of your game.
5. Click the Done button. This method will perform identically to steps 1-9 above.
You’re done! Or at least closer to what you set out to do with some tweaks and iterations needed to get things looking and sounding perfect. Remember: This example uses 8Direction and a System-based timer to cue the randomized sounds only as one possible example! You can just as easily associate these last two Actions with any other Event your game requires: collisions, explosions, jumps, voice effects, etcetera.
Thank you and goodbye
In closing, here are a few thoughts that can help as you finesse your sounds into their final form:
Creating the sound files that work in this context is a challenge unto itself. You have to split the difference between extremes: If your sounds are too similar the overall effect is homogenous and you don’t hear the benefits of randomization. Conversely, if the sounds are too different, the randomized effect loses cohesion and sounds scattered, messy, and confusing to your players. Think about your sounds as being members of the same family—they share similar traits but are not fundamentally the same. Incremental variation across every sound in your banks will hold them all together.
What kind of incremental variation? Try experimenting with subtle pitch shifts of 1-3 semitones. Minor EQ adjustments with high- or low-pass filters often work well. If you’re synthesizing your sounds you can make small adjustments to the synthesis parameters and produce unique sounds right at the source.
Changes of volume, duration, and overall envelope can also be effective. If you want to give yourself a new challenge, look for ways to introduce randomized levels, so that each new sound plays within a range of 3-5 dB above or below the ideal level.
Thank you Nathaniel Ferguson for serving as tech editor on this tutorial.