Skip to content

Basic Sound

noooway edited this page Feb 13, 2017 · 37 revisions

In this part, I'm going to add basic sound effects and music to the game.


Audacity - a free audio editor and recorder.

Sound effects are either synthesized from scratch, or some prerecorded samples are used.

I don't have any experience with sound synthesis, and the only thing I can recommend in this aspect is sfxr/bfxr programs, which are excellent chiptune effects generators (a Lua port of sfxr exists).

Speaking of sound samples, a couple of sites to look for them are OpenGameArt and Freesound. Another possibility is to look for instrument samples pack, bundled with music-making software (such as LMMS or Hydrogen). In dealing with samples, Audacity is immensely helpful tool. It allows to extract a part of the track, normalize volume, suppress certain frequencies, and so on. The number of available editing options is more than enough. Of course, instead of using someone else's samples, you can record your own. Such possibility should not be completely discarded: it is possible to get a decent result (enough to convey the idea) with minimal effort. For example, one of the sounds for this game is a tea cup hit by a pen, recorded on the internal microphone of my computer. Audacity makes the recording process simple enough. When dealing with samples, my advice to keep track of all file renames. They will be necessary to compile a proper credits list.

In LÖVE the sounds are stored and played by audio sources, which are a part of the love.audio module. Each source stores a single sound, which is usually specified on source creation. When needed, the sound can be played with the play method of the source.

For now, I'm going to add sound effects only on ball-bricks collisions and I'll use different sounds for collisions with different brick types.

First, we need to load the sounds from the disk and initialize the audio sources. It is possible to make the sources local variables in the bricks.lua file.

local bricks = {}
.....
local simple_break_sound = love.audio.newSource(
   "sounds/recordered_glass_norm.ogg",
   "static")                                        --(*1)
local armored_hit_sound = love.audio.newSource(
   "sounds/qubodupImpactMetal_short_norm.ogg",
   "static")
local armored_break_sound = love.audio.newSource(
   "sounds/armored_glass_break_short_norm.ogg",
   "static")
local ball_heavyarmored_sound = love.audio.newSource(
   "sounds/cast_iron_clangs_11_short_norm.ogg",
   "static")

(*1): "static" means that the sound is decompressed and stored in the memory, instead of being streamed from the file. This is the preferred method for the small sounds, that are played frequently.

A good place to play the sound is bricks.brick_hit_by_ball function. The sound is chosen according to the brick type.

function bricks.brick_hit_by_ball( i, brick, shift_ball )
   if bricks.is_simple( brick ) then
      table.remove( bricks.current_level_bricks, i )
      simple_break_sound:play()                         --(*1)
   elseif bricks.is_armored( brick ) then
      bricks.armored_to_scrathed( brick )
      armored_hit_sound:play()                          --(*2)
   elseif bricks.is_scratched( brick ) then
      bricks.scrathed_to_cracked( brick )
      armored_hit_sound:play()                          --(*2)
   elseif bricks.is_cracked( brick ) then
      table.remove( bricks.current_level_bricks, i )
      armored_break_sound:play()                        --(*3)
   elseif bricks.is_heavyarmored( brick ) then
      ball_heavyarmored_sound:play()                    --(*4)
   end
end

(*1): simple_break_sound is played on collision of the ball with the 'simple' brick.
(*2): armored_hit_sound if the brick was 'armored' or 'scratched'.
(*3): armored_break_sound if the brick was 'cracked'.
(*4): ball_heavyarmored_sound if the brick was 'heavyarmored'.

Now to the music. Along with the sound effects, some good tracks can be found on Freesound and OpenGameArt. Another resource worth checking is Jamendo. It has a great collection of music, available free of charge for noncommercial applications. However, most tracks require a special license for commercial usage.

In terms of the code, the handling of music is similar to the sound effects. It is necessary to load the track from the hard drive, store it into some source and after that play it. For now, I'll use only a single background track, which I set to loop, so it will automatically restart from the beginning. I want music to start playing in the menu, and then I'm going to manipulate it (pause and rewind) in the other gamestates. So instead of defining the source as a local variable to the "menu" state and passing it between gamestates, I define it global in the main.lua.

music = love.audio.newSource( "sounds/S31-Night Prowler.ogg" )
music:setLooping( true )

The music starts playing in the menu.load:

function menu.load( prev_state, ... )
   music:play()
end

When the game is paused, I pause the track, and resume it, when the game resumes.

function game.keyreleased( key, code )
   .....
   elseif  key == 'escape' then
      music:pause()                         --(*1)
      gamestates.set_state( "gamepaused", { ball, platform, bricks, walls } )
   end    
end

function game.enter( prev_state, ... )
   .....
   if prev_state == "gamepaused" then
      music:resume()                        --(*2)
   end
   .....
end

(*1): the music is paused on transition from the "game" to "gamepaused" state.
(*2): the music is resumed when the game resumes.

If the game is restarted after the "gamefinished" final screen, the track is rewound to the beginning.

function game.enter( prev_state, ... )
   .....
   if prev_state == "gamefinished" then
      music:rewind()
   end
   .....
end

    Home
    Acknowledgements
    Todo

Chapter 1: Prototype

  1. The Ball, The Brick, The Platform
  2. Game Objects as Lua Tables
  3. Bricks and Walls
  4. Detecting Collisions
  5. Resolving Collisions
  6. Levels

    Appendix A: Storing Levels as Strings
    Appendix B: Optimized Collision Detection (draft)

Chapter 2: General Code Structure

  1. Splitting Code into Several Files
  2. Loading Levels from Files
  3. Straightforward Gamestates
  4. Advanced Gamestates
  5. Basic Tiles
  6. Different Brick Types
  7. Basic Sound
  8. Game Over

    Appendix C: Stricter Modules (draft)
    Appendix D-1: Intro to Classes (draft)
    Appendix D-2: Chapter 2 Using Classes.

Chapter 3 (deprecated): Details

  1. Improved Ball Rebounds
  2. Ball Launch From Platform (Two Objects Moving Together)
  3. Mouse Controls
  4. Spawning Bonuses
  5. Bonus Effects
  6. Glue Bonus
  7. Add New Ball Bonus
  8. Life and Next Level Bonuses
  9. Random Bonuses
  10. Menu Buttons
  11. Wall Tiles
  12. Side Panel
  13. Score
  14. Fonts
  15. More Sounds
  16. Final Screen
  17. Packaging

    Appendix D: GUI Layouts
    Appendix E: Love-release and Love.js

Beyond Programming:

  1. Game Design
  2. Minimal Marketing (draft)
  3. Finding a Team (draft)

Archive

Clone this wiki locally