22. Sfx and Bgm
[[programvideogames]]First, we need to update our Game_State struct to include the sound assets we'll be using.
In src/main.odin, modify the Game_State struct:
Game_State :: struct {
// ... other fields remain ...
sword_swoosh_sound: rl.Sound,
sword_swoosh_sound_2: rl.Sound,
sword_hit_soft_sound: rl.Sound,
sword_hit_medium_sound: rl.Sound,
sword_hit_stone_sound: rl.Sound,
player_jump_sound: rl.Sound,
}
Modifying the Attack Animation
Next, we want to add a sound effect when the player attacks. We'll modify the player_anim_attack animation to include a new timed event that plays the attack sound effect.
In spawn_player, update the player_anim_attack definition:
player_anim_attack := Animation {
// ... other fields remain ...
timed_events = {
{timer = 0.01, duration = 0.01, callback = player_attack_sfx}, // New
{timer = 0.05, duration = 0.05, callback = player_attack_callback},
},
}
Initialising the Audio Device
Before we can play any sounds, we need to initialise the audio device. In the main procedure, add the following line after setting the target FPS:
main :: proc() {
gs = new(Game_State)
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Program Video Games!")
rl.SetTargetFPS(60)
rl.InitAudioDevice() // New
// ...
}
Loading Sound Assets
Next, we'll load our sound effects and background music. Still in the main procedure, after loading textures, add the following lines:
gs.sword_swoosh_sound = rl.LoadSound("assets/sounds/player_sword_swing.wav")
gs.sword_swoosh_sound_2 = rl.LoadSound("assets/sounds/player_sword_swing_2.wav")
gs.sword_hit_soft_sound = rl.LoadSound("assets/sounds/sword_hit_soft.wav")
gs.sword_hit_medium_sound = rl.LoadSound("assets/sounds/sword_hit_medium.wav")
gs.sword_hit_stone_sound = rl.LoadSound("assets/sounds/sword_hit_stone.wav")
gs.player_jump_sound = rl.LoadSound("assets/sounds/player_jump.wav")
bgm := rl.LoadMusicStream("assets/music/bgm.ogg")
rl.PlayMusicStream(bgm)
Updating the Music Stream
In the game loop, we need to update the music stream each frame to keep it playing:
for !rl.WindowShouldClose() {
rl.UpdateMusicStream(bgm)
dt := rl.GetFrameTime()
// Rest of the game loop...
}
Modifying Player Code to Play Sounds
In the try_jump procedure, add a line to play the jump sound when the player jumps:
try_jump :: proc(gs: ^Game_State, player: ^Entity) {
if rl.IsKeyPressed(.SPACE) {
gs.jump_timer = JUMP_TIME
}
if .Grounded in player.flags {
gs.coyote_timer = COYOTE_TIME
}
// Modified condition
if gs.player_movement_state != .Fall && gs.coyote_timer > 0 && gs.jump_timer > 0 {
rl.PlaySound(gs.player_jump_sound) // New
player.vel.y = -player.jump_force
player.flags -= {.Grounded}
switch_animation(player, "jump")
gs.player_movement_state = .Jump
}
}
Playing Attack Sound Effects
Define a new procedure player_attack_sfx to play the sword swoosh sound:
player_attack_sfx :: proc(gs: ^Game_State, player: ^Entity) {
if int(gs.camera.target.x) % 2 == 0 {
rl.PlaySound(gs.sword_swoosh_sound)
} else {
rl.PlaySound(gs.sword_swoosh_sound_2)
}
}
Playing Hit Sounds
In the player_attack_callback procedure, we need to play a hit sound when the player successfully hits an enemy or object.
Modify player_attack_callback as follows:
player_attack_callback :: proc(gs: ^Game_State, player: ^Entity) {
center := Vec2{player.x, player.y}
center += {.Left in player.flags ? -30 + player.collider.width : 30, 20}
for &e, i in gs.entities {
// ...
if rl.CheckCollisionCircleRec(center, 25, e.collider) {
// ...
rl.PlaySound(gs.sword_hit_medium_sound) // New
}
}
for &falling_log in gs.falling_logs {
rect := falling_log.collider
if rl.CheckCollisionCircleRec(center, 25, rect) {
falling_log.state = .Falling
rl.PlaySound(gs.sword_hit_soft_sound) // New
}
}
}
That's it! We've successfully added sound effects and background music to our game. The player now hears a sound when jumping, attacking, and hitting enemies or objects. We also have background music playing throughout the game.
Make sure to include the new sound files (.wav and .ogg files) in your assets/sounds and assets/music directories, respectively. They are available in the download below.