Monday 11 April 2016

Assignment 2 Creating and applying sounds to a specific game



BTEC Extended Diploma in Games Development

Unit 73: Sound for Computer Games


Plan for the weeks:


·       Week 1

Think about emotion and atmosphere
Consider whether I want the sounds to be mono or stereo - Stereo
What platform is it going to be on – PC/Phone
File Conventions – MP3 (Compressed)
Pitch – Relatively high

·      Week 2

Record sounds
Create Music tracks (Garage Band?)
5 sounds FXs and 2 tracks
Sound FX for =   Picking up an item
                        Jumping
                        Using the lever
                        Rocks breaking
                        Next Level teleporter
Music Tracks for = Main menu
                            Levels

·       Week 3

Edit the recorded sounds using Adobe Audition/Audacity
Edit Music tracks if needed
Put them in the game
Write about the process

·       Week 4

Finishing writing about the process of how I recorded/edited sounds
Start on the evaluation

Finish evaluation by the end of the week


What I have decided to do is create sound effects and music for two games. I have made 3 music tracks for the Space Invaders game and 4 Sound effects and then I have made 2 music tracks for my Snowball platform game and a sound effect for collecting pickups.
The software that I used to edit the sounds was GarageBand, GoldWave ,SoundTrap and Adobe Audition. For the music tracks I used GarageBand and SoundTrap. GarageBand is a piece of music software available on Macs and SoundTrap is an online music website in which is similar to GarageBand however you are limited to what tracks you use.

Music Tracks: Space Invaders








The image above shows the two tracks I have chosen which loop to create a music track for the Space Invaders game. The music track created is for the main menu of the game. I believe that the atmosphere this song gives is a relaxed, sci-fi atmosphere. The top pink track in the image has long soft notes and the purple track beneath the pink one has short notes repeated to create a catchy tune. I thought the Synth instrument was best for the space themed music I was going for due to it's techno sound.









The image above shows 3 tracks, 2 synth tracks and a beat track. The two synth tracks mix well with one another as one track is a high pitch synth and one is a low pitch. The last dark purple track is the beat. I made it fade in slowly until a new bar started. This fade in track builds up anticipation and then it plays in full when a new bar starts. Towards the end of the track, I have made the beat track fade out in a similar fashion to the start of the track so that the full track would loop perfectly.






The image above displays the tracks used for the boss music for the Space Invaders game. The top two tracks are beat tracks and the bottom track is a synth track. Again, I used synth because it gives off a sci-fi vibe and is very techno. The problem I had with the top track was that, when listening to the track through my laptop the bass wasn't coming through. The bass was so low that the integrated speakers couldn't support it. However, when listening to through my headphones I could hear the bass. Considering this game can be a PC/Phone game, when playing on the PC, using headphones, peripheral speaker and earphones are most preferable, when playing on a phone, earphones are preferable but if you use the integrated speakers then this track wouldn't give off a strong tense vibe as it would with the bass.



Sound Effect: Boss Grunt (Space Invaders)




I recorded 4 sounds for the boss grunt sound effect and I chose 3 out of the 4 sounds to edit. The reason behind why I chose 3 out of the 4 sounds to edit was because 2 of the sounds were near enough the same. I had the idea of using all 3 sounds in the game and it will alternate between which sound is played when the boss is hit. This makes it more interesting and less boring for the player to hear the same sound effect being repeated. The changes I made was I made the sound stereo, changed the depth of the sound to 37.6% and added a flanger to 160%. The flanger makes it sound like the 2 of these grunt noises are being played at the same time.





This image above shows what I used to alter the pitch of the sound. I reduced the pitch down to 75 and I kept the tempo because when you make something sound deeper the slower the sound plays. I wanted to keep the speed of what it already plays. Changing the pitch gave me the desired result I was looking for, a deep grunt noise for the boss.


Sound Effect: Bullet Noise (Space Invaders)




The image above shows I have recorded someone in GoldWave making the same noise 5 times. I knew that it wouldn't be the same each time so I listened through them and picked the one I preferred the most.



I wanted to speed up the sound so that it had more of a laser bullet sound effect, quick and short. The image above shows how I managed to speed up the sound. I chose the FFT algorithm because this section changes the length of the wavelength without the pitch changing.




After changing the speed of the sound, I felt like there was something missing. Although the sound was quick and short like I wanted it to, it still didn't sound much like a laser/bullet sound. The image above shows how I got the desired sound effect for the players bullet. I used the pre-set "wobble". What this did was add a wobble to the sound. The pre-set frequency bar was originally at 20, I changed it from 20 to 15.743.


Sound Effect: Pick-up (Snowball Game)



I wanted to create a sound for when the player has picked something up/collected something. When the sound is played the player will know for sure that they have picked up something/collected it. I first recorded someone making a sound effect for me which was 3 sounds close together. However, when recording, the first part of the recording was quite quiet. The image above shows how I managed to equal the loudness amongst the three sounds. As you can see in the "Presets" section, I used a pre-set called "Equal loudness". This allowed all 3 parts of the recording to match the same decibel level.




The image above shows how I managed to achieve the final form of the desired sound effect. As you can see in the "Presets" area,  I used a pre-set called "Speed Up" and what this did was change the yellow line which was straight across from 1.0 to it going diagonally up. I then added points into the middle which gave the sound effect a whole different sound, you can hear the pitch changing slightly.




Snowball Game:


The image above displays how I imported the sounds/music into my Snowball Game.


The screenshot above shows the names of what I called the sounds/music so it was easy for me to input them in code.


The image above and below shows the code I used to make the sound/music work in game.




The video above did have annotations and images with it, it was also exported as a MPEG-4 video and it didn't show up. However, you can still hear all of the sounds in the video in which I have used in the two games. The image below is a screenshot of all the annotations and images I used to create the video and it also shows the length of the sounds/music.




Evaluation:

When it came to input the sounds and music into GameMaker, I realised that the music was too loud and you couldn't hear the sound effect sounds. What I had to do was go back into the sound file and edit it again and brought up the decibel level, not too high so that the sound was distorted but loud enough. It wasn't my original intention to work on the Space Invaders inspired game however, I really liked what ideas I had for the sounds and music. I think that the music fits in well for each section it is assigned to, especially the boss music. With the snowball game, I found it quite difficult to make a piece of music and sound effects for the game. I wanted to create a happy/cheery atmosphere but then when I added the InGame music, it gave off a lonely, cold atmosphere. I believe that the music I created to play in the game actually fitted the game well. When playing the Space Invaders inspired game with all the sounds and music in, I believe that it all worked really well and playing the snowball game, it also worked really well even though I did not put in as many sound effects or pieces of music in the game. 
The plan in which I had created at the start of the project was not the plan that I followed. Below are images of my written notes for what sounds I wanted to create, what software I wanted to use, what file extensions I wanted and so on. Furthermore there are written notes of what I decided to do in the end. The reason behind I why I chose to work on the Space Invaders game too was because I had more of an idea of what sort of sounds and music I wanted.






Assessment 2: 3 in 1 gaming

Space Invaders clone game


Sprites:

These are the sprites in which I have created for the game. All of the sprites vary in sizes due to the mechanics of the game. For example the spr_earth is very large as it is displayed at the beginning of the game and it covers most of the bottom of the window. The player lives are smaller than the player sprite as they are placed in the bottom left corner of the screen and there are more of the same image of the unicorn than the player.


Sounds:


This screenshot displays all of the sounds in which I have created for the game. There are 4 sound effects and 3 pieces of music altogether. The file names simply explain what they are used for. There are 3 variations to the "Boss Grunt" sound. The reason for this is so that when the player hits the boss with a bullet, the boss doesn't always make the same sound. There are also 3 music tracks which adds variety to the game.

Paths:

There is only one path I have made for this game. The reason behind why I have made this path is so that the boss has an animation. It makes it looks a bit more interesting instead of it just bouncing around the room at the end. The screenshots show what the paths name is and what the path looks like. In the video later on it will show you what the boss looks like when it follows the path.



Objects:

This screenshot displays all of the objects that I have used within my game. The objects with the blank white squares are objects which cannot be seen in game however, they run code in the background which adds lots of features to the game. For example, the controller runs through all of the variables in game which are then used in the other objects, the obj_menu object runs code which brings up the menu in the game, the one you see at the start of the game and the one you see in the pause menu and the obj_starfield object makes the animated background you see appear in every room of the game. This objects adds a nice visual feature to the game.


Obj_Player:

Here is a screenshot of all the events which are contained within the player object. The create event sets out a variable called "bulletdelay" to 0 and "image_speed" to 0.05. The player sprite has a certain number of images in the image index to appear animated in game so this was a suitable speed for the image index to play through. The bulletdelay variable is used in the alarm event. In the alarm event is one line of code which is "bulletdelay = 0". In the space key event is a few lines of code.

Space Key Event

if (keyboard_check_pressed(vk_space) && (bulletdelay = 0)) && (room != menu) then
    {
        instance_create(x,y,obj_player_bullet)
        bulletdelay = 1
        alarm[0] = 30
    }

What this is doing is checking whether the player has pressed the spacebar, the bulletdelay is set to 0 and checking whether they are still in the menu, if they are not in the menu then what happens is a bullet will spawn, then bulletdelay will be changed to 1, acting like a switch, and then an alarm is activated. This alarm is the delay.

Left and Right Key event

if keyboard_check(vk_left) && room != menu
{
x -= 4
}

if keyboard_check(vk_right) && room != menu
{
x += 4
}

This code checks whether the left or right arrow key has been pressed on the keyboard and the player is not on the menu then it either moves to the left at the speed of 4 pixels per script run.

Collision Event (Enemy):

if global.dead = true { 
    lives = -1
    effect_create_above(ef_explosion, x, y, 2, c_red);
    instance_destroy()
    if lives < 0 {
        global.myscore = score
        show_message("You let the asteroids invade Earth!")
        room_goto(hiscore)
    }
}
}  

If the player collides with an enemy (so the enemy has reached near the bottom of the screen) then the player dies. When the player is dead, it creates an explosion effect and takes you to the "hiscore" room.

Collision Event (Bullet):

In this event is a drag and drop "Destroy the instance" with "other" selected. What this does is destroys the obj_bullet.

Collision Event (Wall):

In this event is a drag and drop "Bounce against solid objects". The reason behind why I have done this is so that the obj_player is not able to go through the wall.


Obj_enemy:

Here is a screenshot displaying the events within the enemy object.











Create Event:
In the create event are two actions. The first action is a code action containing:

image_speed = 0.45

if room = menu then {
    global.enemyspeed = 0
    global.enemyshoot = 0
}


If the player is on the menu then the enemy doesn't move or shoot.

The second action is a drag and drop "Start moving in a direction" with the speed being "global.enemyspeed". This variable is a pre-set variable made in the controller event.

Step Event:

if irandom(global.enemyshoot) = 1 && (room != menu) then {
    instance_create(self.x, self.y - 5, obj_bullet)
}

If 1 is chosen out of 2001 (global.enemyshoot for room0 (the first room we go in) and the room is not the menu room then a bullet spawns in where the enemy is.

Collision Event (Wall):

There are two actions within this event, "Reverse horizontal direction" and "Jump to position(0,10). What these do is check to see whether the enemy has made contact with the wall, if it has then it reverses direction horizontally and moves down as it hits the wall.

obj_player_bullet:

Here is a screenshot which displays the 4 events used within the player bullet object. I am going to talk about three of these events fully and the create event briefly. All the create event does is set the vertical speed of the bullet and contains one line of code which tells the game to play a sound when the bullet is shot.



Collision Event (Enemy):

Within the collision event for the enemy are 4 drag and drops, "Set the score relative to 10" which adds 10 score everytime the bullet collides with the enemy, "Destroy the instance" which destroy the player bullet, "Destroy the instance" which destroys the enemy and "Create a firework at (0,0)" which creates and effect in the place where the enemy was destroyed.

Collision Event (MiniBoss):
This collision event is with the mini boss which spawns in the last two rooms before the player is confronted with the main boss. In this event is one action, code.

global.minihealth -= 5
score += 2
instance_destroy()

if global.minihealth <= 0 then
    {
        with obj_miniboss instance_destroy()
    }
   
What this code does is, when the player bullet comes in contact with the miniboss, the miniboss loses 5 health, the player gains 2 points added on to their score and the bullet is destroyed. The if statement checks whether the miniboss health is equal to 0 and if it is then miniboss is destroyed.

Collision Event (Boss):


if global.bossmoving = 1 then {
if irandom(25) = 0 then {
    health -= 10
    score += 15
    instance_destroy()
} else {
    health -= 1
    score += 2
    instance_destroy()
}
} else if global.bossmoving = 0 then {
    instance_destroy()
}

The first if statement checks whether the boss is still following the path made for it previously, if it is then the bullet is just destroyed when it hits the boss without it losing any health. If the boss is not following the path anymore then when the player bullet hits the boss, it has a 1 in 26 chance of a "Critical hit", this dealing 10 damage ( taking 10 health of the boss) and adding 15 score to the players score, every other time the random number chosen is not 0 then when the player bullet hits the boss it deal 1 damage and gives the player 2 score.


var hitsound = irandom(2) // 0, 1 or 2 (3 sounds)

switch(hitsound) {
    case 0:
        audio_play_sound(BossGrunt1, 0, 0)
    break
    case 1:
        audio_play_sound(BossGrunt2, 0, 0)
    break
    case 2:
        audio_play_sound(BossGrunt3, 0, 0)
    break
}

This section of code focuses purely on the sound effects. A random number is chosen, 0, 1 or 2. If the number 1 is chosen, it will go through the switch statement until it reaches case 1, then it will play that sound effect.

Obj_Boss:

Within the boss are 4 events, create, step, collision and an other event. Within the create event are two actions, code and setting a path drag and drop. The code action contains two variables set to 0 and the path drag and drop contains which path is selected for the object to follow and which speed it follows it.  




Step Event:

if global.bossmoving = 1 then {
    if irandom(9) = 1 motion_set(random(360), 1 + random(3))
    if irandom(50/global.runthrough) = 1 then {
        instance_create(self.x, self.y - 5, obj_bullet)
    }
}

If the boss is not following the path anymore then, if 1 is chosen from 0 - 9, the boss has a chance to move in any direction which is chosen randomly from 0 - 360 (in this circumstance would be a full circle) and then the speed is chosen at what rate it moves at by picking a number from 0 to 3. The reason why the "1 +" is put in just before it picks a number is so that if the number chosen was 0 then 1 would be added which means it will always be moving and not stationary. The next if statement decides on when the bullet should be fired. If the number 1 is chosen out of 0 to 50 then it creates a bullet. The global.runthrough is a variable which is used when the player has gone through all the room and defeated the boss and it lets the player go through all the rooms again but is harder. Global.runthrough at first would = 1 and then through the second runthrough it will = 2. With this piece of code above, when it is the second runthrough of the levels, the boss will have double the amount of chance of firing a bullet than before.


Obj_ Controller:

There are 3 events within the controller object. The first event which is the create event contains only one action which is to execute a piece of code.








Create Event:

if room != menu && room != hiscore {
    instance_create(room_width/2, 560, obj_player)
    global.enemyspeed = 0
    global.enemyshoot = 0
}

if room = room0 then {
    global.enemyspeed = 0.5*(global.runthrough)
    global.enemyshoot = 2000 // 1 in 2001 chance to shoot
}

if room = room1 then {
    global.enemyspeed = 1*(global.runthrough)
    global.enemyshoot = 1500 // 1 in 1501 chance to shoot
}
if room = room2 then {
    global.enemyspeed = 1.5*(global.runthrough)
    global.enemyshoot = 1000 // 1 in 1001 chance to shoot
}
if room = room3 then {
    global.enemyspeed = 2*(global.runthrough)
    global.enemyshoot = 750 // 1 in 751 chance to shoot
}


What this large section of code does is decides on how difficult the each room is. You can see that it gets progressively difficult due to the higher the room number the higher the chance it is for the enemy to shoot a bullet. Furthermore, the enemyspeed is increased by the number (for example 1 from room1) times by the global.runthrough (for example, 2nd runthrough = 2), the speed of enemy for room 1 would be then be 2.
Step Event:

if audio_is_playing(InGameMusic) && room = boss then {
    audio_stop_all()
    audio_play_sound(BossMusic, 0, 200)
    audio_sound_gain(BossMusic, global.musicvol, 1)
}

if audio_is_playing(BossMusic) && room != boss then {
    audio_stop_all()
    audio_play_sound(InGameMusic, 0, 200)
    audio_sound_gain(InGameMusic, global.musicvol, 1)
}


This section of code above tells the game when to play a certain music track or not. For example, the first if statement checks to see whether the InGameMusic is playing and checking whether the player is in the boss room. If the player is in the boss room and the InGameMusic is playing then it stops all music together. Then it starts to play the boss music instead. The second if statement follows a similar pattern.

if (instance_exists(obj_miniboss) = 0) && (instance_exists(obj_enemy) = 0) && (room != menu) && (room != boss) && (room != hiscore) then {
    room_goto_next()
}


This next section of code checks to see whether any of the enemies have been left in the room, if some of them are still left and the player is not in the hiscore room, menu or boss room then the player gets automatically moved to the next room.


if keyboard_check_pressed(vk_escape) then {
    instance_create(0, 64, obj_menu)
    audio_stop_all()
    audio_play_sound(MenuMusic, 0, 200)
    audio_sound_gain(MenuMusic, global.musicvol, 400)
    with obj_menu instance_deactivate_all(true)
}

This last section of code checks whether "ESC" has been pressed, if it has then it stops all of the music and then plays the menu music. Furthermore, when the menu is up it deactivates all objects except the menu.

Draw Event:

There are 2 actions within the draw event in the controller, "Draw the lives as image" which displays the amount of lives I want on screen as the spr_lives, "Execute a piece of code" which contains code on the colour of the score font and displays the word "score" in the chosen font.

Hiscore_room:


Here is a screenshot which shows the 3 events contained within the hiscore object. These 3 event help to display the hiscore at the end of the game and saves the previous hiscores obtained by players.







Create Event:

scoredraw = 0
get_string_async("Enter your name...", "Noob")

This section of code brings up the user input box with the message "Enter your name..." and the default text within the input box is "Noob".

Dialog Event:


highscore_add(string(ds_map_find_value(async_load, "result")), global.myscore)

This section of code above is basically saving your score and name.

for (k = 1; k <= 5; k+=1) {
    names[k] = highscore_name(k)
    scores[k] = highscore_value(k)
   
    if (names[k] = "<nobody>") then {
        names[k] = "--"
        scores[k] = "--"
    }
}

scoredraw = 1

This section of code takes what was already saved in the hiscore leaderboards and puts it as a local variable and the last section just replaces the word "nobody" to a "--".


Draw Event:

The draw event in this object contains 3 actions. These 3 actions all work well with one another to display the hiscores in the hiscore room.


Boss Controller:


This object is for the final boss in the last room. It contains 3 events. The create event holds one event which gives the boss a health bar of 100.







Step Event:

if (health <= 0) then {
    with obj_boss instance_destroy()
    room_goto(room0)
    global.runthrough = 2
    global.myscore = score
}


This if statement checks whether the boss health is equal to or less than 0, if it is then the boss is destroyed, the player can run through all the levels again but this time a bit harder. The global.runthrough is now changed to 2 which is like changing the difficulty setting in a game.

Draw Event:

if (global.drawhealth = 1) then {
    draw_healthbar((room_width/2)-256, 50, (room_width/2)+256, 70, health, c_black, c_red, c_green, 180, true, true)
}



All this section of code does is draws the health bar in a certain position in the room and with the colours that I wanted it to use.

Obj_menu:

The object menu has 3 events inside, create, step and draw. Within the Create event is one action, "execute a piece of code".







Create Event:

if room = menu {
    global.play = 0
    global.bulletdelay = 1
    global.options = 0
    global.runthrough = 1
    menuSelPos = 0
    score = 0
    global.myscore = 0
    global.playerspeed = 4
    global.dead = false
    lives = 3
    global.musicvol = 0.5
    drawres = 0
    drawvol = 0
    global.minihealth = 50
} else if room != menu {
    global.bulletdelay = 0
    global.options = 0
    menuSelPos = 0
}

audio_play_sound(MenuMusic, 0, 200)
audio_sound_gain(MenuMusic, global.musicvol, 1)


The reason behind why all the variables are defined within this section is so that, when the player goes through all of the levels again, the variables are not reset. For example; if lives = 3 was actually in room1 and then carried out through all the rooms, when the player goes back to room1 they will have 3 lives again. The audio section at the bottom just simply tells the game to play a certain track when obj_menu is open.
MenuSelPos = The top position. Example; Play or Fullscreen.
Global.runthrough = First runthrough = * 1 , Second runthrough = * 2

Step Event:

if keyboard_check_pressed(vk_up) && menuSelPos > 0 {
    menuSelPos -= 1
} else if keyboard_check_pressed(vk_up) && menuSelPos = 0 {
    menuSelPos = 3
}
if keyboard_check_pressed(vk_down) && menuSelPos < 3 {
    menuSelPos += 1
} else if keyboard_check_pressed(vk_down) && menuSelPos = 3 {
    menuSelPos = 0
}

This section above is how I managed to make the player be able to move the menu selector cursor up and down.

// Menu selections
if global.options = 0 then {
if keyboard_check_pressed(vk_enter) {
switch(menuSelPos) {
    case 0:
        if room = menu then {
            global.play = 1
            audio_sound_gain(MenuMusic, 0, 400) // Fade menu music
            if room != boss then {
                audio_play_sound(InGameMusic, 0, 200)
                audio_sound_gain(InGameMusic, global.musicvol, 1)
            } else if room = boss then {
                audio_play_sound(BossMusic, 0, 200)
                audio_sound_gain(BossMusic, global.musicvol, 1)
            }
            instance_destroy()
        }
    break
    case 1:
        if room != menu then {
            instance_activate_all()
            audio_sound_gain(MenuMusic, 0, 400) // Fade menu music
            if room != boss then {
                audio_play_sound(InGameMusic, 0, 200)
                audio_sound_gain(InGameMusic, global.musicvol, 1)
            } else if room = boss then {
                audio_play_sound(BossMusic, 0, 200)
                audio_sound_gain(BossMusic, global.musicvol, 1)
            }
            instance_destroy()
        }
    break
    case 2:
        global.options = 1
    break
    case 3:
        game_end()
    break
}
}

This section of code above contains a switch statement. The switch statement contains 4 cases, each case represents a section on the menu, Case 0 = play, Case 1 = continue, Case 2 = options and Case 3 = quit. When case 1 is selected then music is stopped and then another music track is played (the in game music track), the second case follows a similar pattern. If Case 2 is chosen then global.options is turned on which is another menu and when Case 3 is chosen then the game stops running.

}
// Menu-Options selections
if global.options = 1 then {
if keyboard_check_pressed(vk_enter) {
switch(menuSelPos) {
    case 0:
        if window_get_fullscreen() = true then {
            window_set_fullscreen(false)
        } else {
            window_set_fullscreen(true)
        }
    break
    case 3:
        global.options = 0
    break
}
}
switch(menuSelPos) {
    case 0:
        drawres = 0
        drawvol = 0
    break
    case 1:
        drawres = 1
        drawvol = 0
        if keyboard_check_pressed(vk_right)
    break
    case 2:
        drawres = 0
        drawvol = 1
        if keyboard_check_pressed(vk_right) && audio_get_master_gain(0) < 1 {
            audio_set_master_gain(0, audio_get_master_gain(0) + 0.1)
        }
        if keyboard_check_pressed(vk_left) && audio_get_master_gain(0) > 0 {
            audio_set_master_gain(0, audio_get_master_gain(0) - 0.1)
        }
    break
    case 3:
        drawres = 0
        drawvol = 0
    break
}
}

This last section of the code is another switch statement similar to the one further above. It contains cases in which allows the player to choose what they want. However, with this options menu, the code contains 2 switch statements but they are the same. One switch statement requires you to press enter which is the first switch statement for Case 1 (Which is allowing the player to select fullscreen when pressing enter). Then the second switch statement is a switch statement which doesn't allow you to press enter on any of options (you don't need to press enter to access any of the cases). The only case which does something in the second switch statement is 2. What this section of code lets the player do is, when they press left or right on the keyboard, the volume either decreases or increases in volume, 0.1 = 10% and 1 = 100%.


Draw Event:

For the draw event, it contains two 1D arrays. The first 1D array is for the main menu and the 2nd 1D array is for the option menu. The rest of the code which is contained within the draw event is deciding on what colour font the words are going to be in the menu. The colours are either white or grey, grey meaning they cannot be used.


Rooms:


Here are the rooms in which I have created for the game. There are 4 rooms which contain the smaller enemies and mini boss then there is a boss/final room. Once the player has defeated the final boss they are able to go back through the levels again at a higher difficulty. The hiscore and menu rooms are bonus rooms to the game.