HOW TO Add Sound Effects & Music To Your Game Using Love2D!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] sound effects and music in your game what to do we won't do it using any existing libraries instead you will learn to create your own i believe this is the better way to learn if you think this plan is sound make sure to like the video and subscribe so you don't miss any future content we will start by creating a new file which i will name sound.lua inside we're going to create a new local table which i will name sound it's always good practice to keep as much as possible local it is even more important to do so if you intend to make a library in order for us to be able to reach this local variable outside of this file we need to return it at the bottom inside of this sound table i'm going to add two additional tables named active and source the source table will store all of the loaded sound effects while the active table will store and handle all currently playing sounds similarly to when drawing images we need to first load in the asset to do this i will create a new function named init this function will take three arguments id source and sound type id will be a unique string which will be mapped to the sound itself the id is later used to trigger the specific sound that we want to play since it needs to be unique we can add an assert below an assert is a function which checks if a condition is met and if it is not then it crashes the game with a custom error message in this case we can add a check which looks if sound.source id in brackets is equal to nil and then some kind of a useful message that will let us know what went wrong another way we could deal with duplicates would be to simply override the sound that existed on that id as with everything else i show it is up to you to make these decisions the next argument is the source which we will load into the id key we do that by typing self.source id in brackets equal to love.audio.new source and pass in source this function takes another argument as well the sound type which is our third argument there are two different types static and stream this dictates if the sound should be loaded into ram or be streamed a good rule of thumb is to keep music streaming and sound effects static now that we can load sounds into our source table we should implement a function that plays the sound i will create a new function named play which will have two arguments initially id and channel id will simply refer to the particular sound that we wish to trigger when you have a lot of different types of sound effects it can be useful to have them playing in separate groups or channels this allows you to for example adjust the volume of all sounds in a channel named sound effects while not affecting sounds playing in another channel for example music to make it more convenient for the person who will be using this library which most likely is you we will add a default channel this way you can call the play function and only pass in the id if it is not important that it belongs to any particular channel to accomplish this we will create a local variable name channel and set it to be equal to channel or a string name default this means that if you do pass in a specific channel the local variable will be set to that otherwise it will be set to the default value now we get to a critical part while we could just call play on the sound.source id that would break the second we try to play the same sound again before the first sound has finished the solution is to clone the source and we do that by calling clone on the sound source i will store it in a local variable named clone clone compared to just calling new source will take a lot less time and space while also not causing a memory leak all that remains to get the sound to play is to call play on the clone to be able to reach and modify this sound effect while it's playing we are going to insert it into a channel first we need to make sure that the channel exists we can do this by checking if the channel doesn't exist and create it if that is the case then we can go ahead and insert the clone into it using table.insert we have now done enough to be able to test our code to make sure that it's sound i have an empty main.lua file which contains the three base love functions load update and draw as well as the love.keypressedcallback function at the top i will create a new local variable named sound and set it to be equal to require sound now we can go ahead and load a sound by calling sound init as the first argument i will pass in test which is just a random name that i will assign to the sound itself next is the path to the sound effect since this is a sound effect i will pass in static as the final argument to play the sound i will create an if statement inside of the key pressed function which will check if the pressed key is equal to a if that is the case then i will just call sound play and pass in the sound effect which i want to play in this case it's test then i will pass in a channel name sfx if we run the game you can hear a coin effect play each time i press the a button if i spam it you are also able to hear that we can have multiple instances of the same sound playing at the same time currently we are filling up the active table with sound effects but we never remove them when they are done playing to do this i will go back to the sound.lua file and create a new function which i will name update inside we will create a loop which will iterate through the sound.active table inside we will create an if statement which will check if this channel is not empty by checking that the first index of that channel is not equal to nil then we will also check that the sound is not playing by calling is playing on it if both of these statements are true it means that we have a sound which has stopped playing so we can go ahead and remove the first index of the channel note that this only checks the first index meaning the oldest created sound this means that if you triggered a music track which is 5 minutes long and then a bunch of shorter sound effects those short sound effects will finish and have to wait for the longer sound to be removed first the benefit of this is that it's slightly more efficient than iterating through all of the sound effects each frame depending on your needs you may want to change this but since each channel checks their own sounds you should never end up in a situation where a bunch of sound effects are waiting for a music track to check that this is working we can add a print which prints out the number of elements inside of the channel before running the game we also need to make sure to call the update function inside of love.update in the main lua file if we run the game you can see that the number keeps going back down to zero meaning that our cleanup is working let's implement a function that will stop all sounds which are currently playing on a channel this could be to interrupt a long voice line or to silence music i will create a new function which i will name stop it will have one argument the channel that we wish to stop inside we will create a loop which will iterate through the selected channel and call stop on each of the sounds inside of it finally let's add an assert which will check that the past in channel actually exists and then some kind of useful message that will let us know what went wrong a very useful feature is to be able to set the volume of specific sounds and channels first of all i'm going to add another argument to the play function named volume we can then call set volume on the clone and pass in the volume in the same way as with the channel we will add a default value which will be used in case the volume argument is nil i will set it to be equal to 1 which means 100 volume next i will create a new function named set volume this will be used to change the volume of all sounds of a specific channel it will take two arguments the target channel and the new volume next we are going to loop through all of the sounds of that channel and call set volume with the past in volume as the argument just like the stop function we will add an assert which will check that the channel actually exists and leave a message if it doesn't another useful feature is to be able to set the pitch of sound effects i personally like shifting the pitch slightly on sound effects that will trigger often to make them sound more organic and less like the exact same sound effect we will do this basically the same way as we handled the volume let's start by adding a new argument to the play function then call set pitch on the clone and pass in the pitch or 1 in case it's nil next we can copy and paste the set volume function all we need to do is to change the name of the function as well as change the function call from set volume to set pitch and change the name of the argument sometimes you will have ambient sounds or music that you want to loop we can add another argument to the play function i will name it loop now we just need to call set looping on the clone and pass in loop or false so that it does not loop by default if you have multiple versions of a sound effect for example multiple footstep sounds then being able to trigger a random sound effect from a pool is very useful let's make us able to load in multiple sound effects to one id and then make it so that when we call play on that id it will pick one of those sound effects at random and play it first we will head over to the init function and add an if statement here we need to check if the past in source is a table or just a single sound effect we can do that by using the type function this is a function which will return the type of data that we passed in if it is a table it will return a string table this means that we can pass in the source argument and check if it's equal to table if it's not a table we will add an else statement and load the source like normal however when the source is a table instead of loading a sound we will create a table at that index then we will loop through the pass in table and insert each of the sounds into our newly created table make sure that you don't just type source but also add the index this might look a bit intimidating let's run over how it works again we get the size of the past in source table by adding a hashtag in front of it let's say that we sent in three sound effects then the loop would run three times if the id was footstep it will load the first sound at self.source footstep 1 the second at footstep 2 etc now that we are able to load in a table of sound effects we need to make sure that we can also play them to be able to play a sound effect from this table we need to first modify our play function a little bit this will resemble the init code we need to create an if statement which checks whether or not the type of the sound source is a table i will create a new local variable named source but i will declare it outside of the if statement elsewhere would only have access to the variable inside of the if statement and not outside of it if the sound source is a table then we will set the source to be equal to a random sound inside of it we can accomplish that by setting it to be equal to a random number between 1 and the number of sounds in the table all that remains is to create an else statement here we will just set the source to be equal to sound.source id finally we need to replace the sound.source id with source on the line where we create the clone let's go ahead and test the functionality that we have implemented if i want a table of sound effects i load it fairly similarly to the first test example just make sure to wrap the paths in a table and separate each of them with a comma sign i will name this sound multiple and change the sound id that gets played to it if we run the game you can hear that it plays a random sound effect each time i press the button let's change it back to the first test sound and add some extra arguments the next argument is the volume which i will set to 1 or in other words 100 volume then comes the pitch i will set that to be equal to 0.3 and run the game again and as you can hear the pitch has indeed changed next we can make this sound effect loop by adding a true at the end i will also add another if statement which will check if the key s is pressed if this is the case i want to stop all sound effects currently playing on the sfx channel so i will call sound stop and pass in sfx now the sound will continue to loop infinitely until i press the s button which causes it to stop currently we have a lot of control over sounds when we create them but after that you can only modify them through the channel we can very easily make us able to modify a specific sound effect all we need to do is to head over to the play function and return the clone at the bottom to demonstrate this let's head over to the main.lua file and store the looping sound effect in a variable we can now call all of the normal methods directly on this sound so i can for example make it no longer loop if i run the game and press a you can hear that the sound effect no longer loops if you have a smaller game without a ton of music and sound effects you don't really need to worry about the initializing sounds which are not currently needed however if you intend to have a ton of music and sound effects it can be beneficial to be able to unload certain sounds which are not needed in order to free up ram the function for this is going to be very simple i will name it clean and have it take one argument the id which we wish to de-initialize then all that remains is to set that sound to be equal to nil all you need to do in order to remove a sound is to call this function and pass in the same id which you use to initialize it thank you for watching remember to like the video if it helped you and subscribe so you don't miss the next episode if you have any issues let me know in the comments below i read and try to help with any issues as often as possible [Music] you
Info
Channel: DevJeeper
Views: 844
Rating: undefined out of 5
Keywords: programming, coding, lua, love2d, game development, sound effects, sfx, music, sound, 2d, platformer, rpg, rogue like, roguelite, rogue lite, roguelike, game, gamedev, game jam
Id: M8oZ-XF1jiI
Channel Id: undefined
Length: 16min 14sec (974 seconds)
Published: Sun Apr 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.