Part23b. Tutorial Stack 15. PlaySoundEffects , ClearActiveSoundPlayers, OptionsApplies, OptonsGrouSetup, InitFiles
When the player shoots, an enemy shoots, an enemy travels onto the screen, or when things explode
PlaySoundEffects is there to give it a voice.
---------- BEGIN ]PlaySoundEffects of the stack script ----------------
Code: Select all
on PlaySoundEffects tType,tSource
--if soundCount is 0 then exit PlaySoundEffects
This commented code is worth a comment. I don't know why but soundCount keeps resetting to 0 when I leave the game to do some programming stuff. The stack locals get reset when switching from browse to pointer tool? Anyway I had to disable that line or the whole handler would stop running before it even got started.
soundEffectPlayers are the actual player objects on the stack, activeSoundPlayers are the player objects playing sounds at the moment.
We want to store their data in temporary variables here so we can filter them without changing them.
Code: Select all
put soundEffectPlayers into tPlayersAvailable
put activeSoundPlayers into tActiveSounds
Here we filter for type, for instance if we pressed the mouse button we'd sent it "PlayerLaser"
Code: Select all
filter tActiveSounds with tType&"*"
filter tPlayersAvailable with tType&"*"
Here's that loop I'd like to get rid of. We remove the active sounds from the available sounds list
Code: Select all
--// don't use an active sound player
repeat for each line L in tAciveSounds
filter tPlayersAvailable without L
end repeat
If there are no players available for this sound type,
ClearActiveSoundPlayers will stop one from playing and give us one to use.
Code: Select all
put the number of lines of tPlayersAvailable into pAva
if pAva < 1 then
ClearActiveSoundPlayers tType
put 1 into pAva
end if
The number of lines of tPlayersAvailable can never be zero with the condition above...This condition will probably get removed.
Of pick a random player object of the available player objects. if we picked a existing player then play the sound it contains in its filename property.
Code: Select all
put random(pAva) into nSound
put line nSound of tPlayersAvailable into tSoundFXPlayer
put cr & tSoundFXPlayer after activeSoundPlayers
filter activeSoundPlayers without empty
if exists (player tSoundFXPlayer) then
play player tSoundFXPlayer
set the lastTime of player tSoundFXPlayer to -1
The
lastTime custom property was carried ovre from music files, to be used in case I had some long play sound for some reason.
None of the sound effects should last more than one second, I think, so we can clear their players often, but not too often.
If the Type is an enemy we store the name of the player we derived above in the enemy graphic object, to be stopped later in it it's
InactivePlayers call. Enemy sounds loop while the enemy is on screen.
Code: Select all
if tType is not "Enemy" then
send ClearActiveSoundPlayers && tType to stack (the mainStack of this stack )in 2 seconds
else
set the looping of player tSoundFXPlayer to true
set the FXplayer of graphic tSource to tSoundFxPlayer
end if
Code: Select all
end if
end if
end PlaySoundEffects
End if available players are > 0
End if there exists a player object with the name randomly selected from available players
end the handler
-------------------END of PlaySoundEffects of stack script --------------------------------------
ClearActiveSoundPlayers Gives us a player of the given type back every 2 seconds.
Code: Select all
on ClearActiveSoundPlayers tType
put activeSoundPlayers into tPlayerList
filter tPlayerList with tType&"*"
put line 1 of tPlayerList into tclearedPlayer
if tclearedPlayer is empty then exit ClearActiveSoundPlayers
if exists (player tClearedPlayer) then
stop player tclearedPlayer
set the lastTime of player tclearedPlayer to -1
end if
filter activeSoundPlayers without tclearedPlayer
end ClearActiveSoundPlayers
Relevant changes to OptionsGroupSetup look like this
Code: Select all
--// sound effects volume
put currentFXVolume into FXVal
put the left of graphic "FXVolumeSlider"+FXVal into FXvolX
set the loc of graphic "FXVolumeSliderRectangle" to FXvolX,item 2 the loc of graphic "FXVolumeSlider"
put FXVal into field "FXVolumeValue"
OptionsApplied gets a little more complicated since we need to isolate song players, update them, then iterate over sound effects players
Code: Select all
--// VOLUME
put the number of players of this stack into nPlayers
if nPlayers > 0 then
repeat with i = 1 to nPlayers
put cr & the short name of player i of this stack after allPlayers
end repeat
Player object names acquired. Update to match changes made in
OptionsGroup
Music
Code: Select all
--// music volume
put the OptionsNewVolume of stack (the mainStack of this stack)into vVal
put allPlayers into MusicPlayers
filter Musicplayers with "Song*"
repeat for each line SoPl in MusicPlayers
set the playLoudness of player SoPl of this stack to vVal
end repeat
put vVal into currentMusicVolume
Then sound effects
Code: Select all
--// sound effects volume
put the OptionsNewFXVolume of stack (the mainStack of this stack)into fxvVal
put allPlayers into soundEffectPlayers
filter soundEffectPlayers without "Song*"
filter soundEffectPlayers without empty
repeat for each line SfxPl in soundEffectPlayers
set the playLoudness of player SfxPl of this stack to fxvVal
end repeat
put fxvVal into currentFXVolume
end if
put the number of lines of soundEffectPlayers into soundCount[/code
InitFiles now manages the startup of the game, files first, fun after
bMusicInitPassed &
bSoundsInitPassed are set true as long as
Initmusic and
InitSoundEffects don't completely fail to run.
Even if their are no sounds or music, the game can contiue.
This is signaled by the "
Play" card script on
OpenCard
Code: Select all
on InitFiles
InitMusic
InitSoundEffects
if bMusicInitPassed is true and bSoundsInitPassed is true then
put true into bInitFilesComplete
InitGame
end if
end InitFiles
Let's see what's in enemy scripts....the get a new local variable
soundActivated that is default to false, then if they are in the screen rect it is set to true, we don't want to keep activing different sound players for one enemy, one will do, so a bool keeps things cool.
The enemy passes it's own name to
PlaySoundEffects , so
PlaySoundEffects can pass a player name back to the enemy to be disabled when they are.
Code: Select all
--// enemy is on screen, shoot at the player
if enemyXY is within stackRect then
if soundActivated is false then
PlaySoundEffects "Enemy",(the short name of me)
put true into soundActivated
end if
Bullets get a one shot activation when they launch at the end of
PrepareToFire
Code: Select all
on PrepareToFire
--//
---// more script here in the bullet script
---//
PlaySoundEffects "Weapon"
BulletFly
end PrepareToFire
Think that covers the sound effects. It's a much more exciting game now.
pew pew pew