How to add background music to a Small Basic game
A few days ago, an old thread My custom sounds won't repeat. Any idea why? in the Small Basic forum became active again.
Here i will try to show, how you can easily add background music to any of your Small Basic games or programs, just by adding an event subroutine, a Timer.Tick event and a few flags.
The following sample uses Sound.PlayAndWait(filePath) from an event subroutine (Sub BGSound), which is called at the beginning of the program (here before entering the main loop) and cycles as an asynchronous thread, parallel to the main loop. The named subroutine is called via Timer.Tick. Remember that Timer.Tick is the only native event in Small Basic, that also works with TextWindow.
Since Threading is not the easiest subject for beginners and is not very often used for Small Basic programs, you definitely should read LitDev's great Small Basic Threading article about this topic first.
You will know this sample ("Paddle game") from Vijaye Raji's Introducing Small Basic.pdf that ships with your Small Basic installation.
Here it is slightly expanded with a looping sound theme in the background. This should make it easier to view the differences between both versions and apply these changes to your own programs or games.
Paddle Game with background music, ID: BGC193
soundFile = "http://jamsspace.com/songs/SOJA-Strength-To-Survive/03-Everything-Changes.mp3"
soundOff = "True" ' Has BGSound currently stopped playing?
loopAudio = "True" ' Continuously repeat BGSound?
' Start BGSound at least 1x, 1st loop
Timer.Interval = 10 ' call it in 10 [ms]
Timer.Tick = BGSound ' Subroutine where to loop through (and check state of) the BGSound
While soundOff <> "False" ' Wait until BGSound is loaded and began to play before GW is shown
Program.Delay(500)
EndWhile
Program.Delay(3000)
GraphicsWindow.BackgroundColor = "DarkBlue"
paddle = Shapes.AddRectangle(120, 12)
ball = Shapes.AddEllipse(16, 16)
'Mouse.HideCursor()
GraphicsWindow.MouseMove = OnMouseMove
gw = GraphicsWindow.Width
gh = GraphicsWindow.Height
x = 0
y = 0
deltaX = 1
deltaY = 1
RunLoop: ' game loop entrance
'If soundOff = "True" And loopAudio = "True" Then
' Timer.Interval = 10
'EndIf
x = x + deltaX
y = y + deltaY
If (x >= gw - 16 or x <= 0) Then
deltaX = -deltaX
EndIf
If (y <= 0) Then
deltaY = -deltaY
EndIf
padX = Shapes.GetLeft(paddle)
If (y = gh - 28 and x >= padX and x <= padX + 120) Then
Sound.PlayClick() ' intermediate game sound
deltaY = -deltaY
EndIf
Shapes.Move(ball, x, y)
Program.Delay(5)
If (y < gh) Then
Goto RunLoop
' EndIf
Else '' You lost and the current game is over. You can ...
Sound.PlayChime()
GraphicsWindow.ShowMessage("You Lose !!", "Paddle")
'' ... wait for current audio playback to finish, THEN the program will exit.
loopAudio = "False"
GraphicsWindow.DrawText(10,10, "Program will exit automatically when the music's over.")
'Mouse.ShowCursor()
While soundOff = "False"
Program.Delay(200)
EndWhile
Program.End()
EndIf
' ========== EVENTS ==========
Sub OnMouseMove
paddleX = GraphicsWindow.MouseX
Shapes.Move(paddle, paddleX - 60, GraphicsWindow.Height - 12)
EndSub
' Event Subroutine for repetitive parallel playback
Sub BGSound
Timer.Pause()
While loopAudio = "True"
soundOff = "False"
Sound.PlayAndWait(soundFile)
soundOff = "True"
EndWhile
EndSub
Note the two flags named loopAudio and soundOff. They can hold bool values "True" or "False" (resp. anything else than "True") and allow to control the program flow.
loopAudio defines if the audio playback will be repeated at all. If set to "False" at any point or time in the main loop it will stop repetition. The currently playing audio loop will continue until it is finished and then background music stops.
soundOff is used to detect whether the Sound.PlayAndWait command is still active (soundOff = "False") or the sound stopped playing.
For further explanation please read the comments in the upper code sample. You can add more flags or change and play around with the existing flags and 'commented lines, to realize their changes on the program flow. Keep in mind, that all the flag variables are ' global scope' in Small Basic and are valid all across the whole program, in all Sub's as well as the in main loop.