Having trouble with stopping sound effects on spawned objects help please!

Hi,
I have a beat em up game and a ‘punch’ sound is played on a timer if an enemy collides with my character as shown below:

local function hitSound()
local hsound = math.random(#sfx.hit)
audio.play(sfx.hit[hsound])</div>
end
--------------------------------------------------CHARACTER COLLISION--------------------------------------
<div>local function guyCollision(self, event)
if event.other.type == "enemy1"then

if event.phase == “began” then
hitTimer = timer.performWithDelay(500,hitSound,0)
event.other:setSequence(“punch”)
event.other:play()
end

if event.phase == “ended” then
timer.pause(hitTimer)
end

This works fine when my character is taking down just one enemy at a time but if there are more than one spawned enemy (which there usually is) fighting my character when i kill them the punching sound remains.

I’ve tried putting the timer.pause in the function where the enemy gets removed which didnt work, tried timer.cancel instead of timer.pause aswell (grasping at straws)!

What i’m thinking is i maybe need an if statement around the audio.play to check if the sound is already playing, if it is then return, if it’s not then play? because the sounds are doubling up the more enemies im fighting then theyre not all getting paused/cancelled when i kill them (which i cant figure out why) just not sure how to check if that sound is playing? am i even on the right lines?

Also when i call audio.fadeout() when my character dies the punch sounds don’t fade out with the other sounds/music :s

Any help appreciated!!! thanks!!!

Sounds like a better approach to this would be to add a timer object to each enemy.

Ie

enemies[currentEnemyIndex].timer = nil

Then assign the timer to the enemy object by passing the table reference to the enemy in question your collision handler.

enemies[currentEnemyIndex].timer = timer.performWithDelay …

That way you will be pausing the timer for the actual enemy. Currently your global variable gets overriden by the last spawned enemy each time one collides with your player you see.

Hope this helps.

Hi, thanks for the reply!

This does sound like a much better way of doing it.

I am still fairly new to corona and am having troubles with my enemy spawn table and referencing the current enemy so hopefully you could help me out by explaining a bit more sorry to be such a chore!

here is the code for my enemy spawn:

local spawnTable2 = {}

local function spawnEnemy()

 enemy1 = display.newSprite( group, sheetE, sequenceData2 )

enemy1.x=math.random(100,1300)

 enemy1.y=math.random(360,760)

 enemy1.gravityScale = 0

 enemy1:play()

 enemy1.type=“coin”

enemy1.objTable = spawnTable2

enemy1.index = #enemy1.objTable + 1

enemy1.myName = “enemy” … enemy1.index

physics.addBody( enemy1, “kinematic”,{ density = 1.0, friction = 0.3, bounce = 0.2 })

enemy1.isFixedRotation = true

 enemy1.type = “enemy1”

 enemy1.enterFrame = moveEnemy

 Runtime:addEventListener(“enterFrame”,enemy1)

enemy1.objTable[enemy1.index] = enemy1

return enemy1

end

and my collision code is above thanks

for anyone interested i got this working by using event.other.timer = timer.performwithdelay… and timer.cancel(event.other.timer).

Only problem im still having is that the audio is not stopping when audio.stop or audio.pause is called…

Hi @f.p.mcmanus,

How are you referencing the audio channel that the sound plays on, and thus, stopping or pausing that channel when the timer completes? Probably the best way is to play the audio, store the returned channel number on the object itself, then when the timer goes off, access that channel number and stop/pause it.

Hope this helps,

Brent

Hi Brent,

I do not specify an audio channel for the sound to be played on, i thought that because the sound could be playing at more than one time (multiple enemys attacking) that the sound would be playing on different channels? Also in general is not specifying a channel good practice? Should i be assigning each sound effect to a specific channel everytime or can i just not specify and let corona do the work? Sometimes one of my sounds doesn’t play when it should, do you think this is because i am not specifying channels? Sorry for all the questions but i’ve been wondering about sound management for a while but didn’t know who to ask!

Thanks!

sorry the timer is on an endless loop and is cancelled when the collision ends with the enemy and my character using timer.cancel(event.other.timer)

Hi @f.p.mcmanus,

You’re correct that, in this case, you don’t need to necessarily specify a channel for each audio to play on. However, if you want to pinpoint a specific audio instance and stop/pause it, you’ll need the channel it’s playing on. You can get this by either gathering the channel that Corona finds/picks when it plays the audio, then setting that number as a property of the object or whatever. Alternatively, you can use the “audio.findFreeChannel()” function in advance, set that number as a property of the object, and then play the audio file on that channel.

http://docs.coronalabs.com/api/library/audio/findFreeChannel.html

That being said, if these audio effects are just playing and finishing in their own time, and you don’t need to micro-manage them, you can just let them play and, when the file is done playing, Corona should free up that channel automatically (assuming the audio isn’t looping endlessly or something like that).

Brent

Thanks Brent that makes sense.

So i assume the reason the sound effect is still playing when i call audio.stop() is because the timer is still running on one or more of the spawned enemys.

In the spawn enemy function given it a timer:

enemy1.timer=nil

then when the collision function on my character is initiated i call:

event.other.timer = timer.performWithDelay(500,hitSound,0)

and when collision ends i call:

event.other.timer=nil

Now when my character dies i call enemy1.timer=nil but this is not stopping the sound. Any suggetions as to what i can do?

Is there a way to address all enemy spawns that are currently active on the screen?

Thanks

Sounds like a better approach to this would be to add a timer object to each enemy.

Ie

enemies[currentEnemyIndex].timer = nil

Then assign the timer to the enemy object by passing the table reference to the enemy in question your collision handler.

enemies[currentEnemyIndex].timer = timer.performWithDelay …

That way you will be pausing the timer for the actual enemy. Currently your global variable gets overriden by the last spawned enemy each time one collides with your player you see.

Hope this helps.

Hi, thanks for the reply!

This does sound like a much better way of doing it.

I am still fairly new to corona and am having troubles with my enemy spawn table and referencing the current enemy so hopefully you could help me out by explaining a bit more sorry to be such a chore!

here is the code for my enemy spawn:

local spawnTable2 = {}

local function spawnEnemy()

 enemy1 = display.newSprite( group, sheetE, sequenceData2 )

enemy1.x=math.random(100,1300)

 enemy1.y=math.random(360,760)

 enemy1.gravityScale = 0

 enemy1:play()

 enemy1.type=“coin”

enemy1.objTable = spawnTable2

enemy1.index = #enemy1.objTable + 1

enemy1.myName = “enemy” … enemy1.index

physics.addBody( enemy1, “kinematic”,{ density = 1.0, friction = 0.3, bounce = 0.2 })

enemy1.isFixedRotation = true

 enemy1.type = “enemy1”

 enemy1.enterFrame = moveEnemy

 Runtime:addEventListener(“enterFrame”,enemy1)

enemy1.objTable[enemy1.index] = enemy1

return enemy1

end

and my collision code is above thanks

for anyone interested i got this working by using event.other.timer = timer.performwithdelay… and timer.cancel(event.other.timer).

Only problem im still having is that the audio is not stopping when audio.stop or audio.pause is called…

Hi @f.p.mcmanus,

How are you referencing the audio channel that the sound plays on, and thus, stopping or pausing that channel when the timer completes? Probably the best way is to play the audio, store the returned channel number on the object itself, then when the timer goes off, access that channel number and stop/pause it.

Hope this helps,

Brent

Hi Brent,

I do not specify an audio channel for the sound to be played on, i thought that because the sound could be playing at more than one time (multiple enemys attacking) that the sound would be playing on different channels? Also in general is not specifying a channel good practice? Should i be assigning each sound effect to a specific channel everytime or can i just not specify and let corona do the work? Sometimes one of my sounds doesn’t play when it should, do you think this is because i am not specifying channels? Sorry for all the questions but i’ve been wondering about sound management for a while but didn’t know who to ask!

Thanks!

sorry the timer is on an endless loop and is cancelled when the collision ends with the enemy and my character using timer.cancel(event.other.timer)

Hi @f.p.mcmanus,

You’re correct that, in this case, you don’t need to necessarily specify a channel for each audio to play on. However, if you want to pinpoint a specific audio instance and stop/pause it, you’ll need the channel it’s playing on. You can get this by either gathering the channel that Corona finds/picks when it plays the audio, then setting that number as a property of the object or whatever. Alternatively, you can use the “audio.findFreeChannel()” function in advance, set that number as a property of the object, and then play the audio file on that channel.

http://docs.coronalabs.com/api/library/audio/findFreeChannel.html

That being said, if these audio effects are just playing and finishing in their own time, and you don’t need to micro-manage them, you can just let them play and, when the file is done playing, Corona should free up that channel automatically (assuming the audio isn’t looping endlessly or something like that).

Brent

Thanks Brent that makes sense.

So i assume the reason the sound effect is still playing when i call audio.stop() is because the timer is still running on one or more of the spawned enemys.

In the spawn enemy function given it a timer:

enemy1.timer=nil

then when the collision function on my character is initiated i call:

event.other.timer = timer.performWithDelay(500,hitSound,0)

and when collision ends i call:

event.other.timer=nil

Now when my character dies i call enemy1.timer=nil but this is not stopping the sound. Any suggetions as to what i can do?

Is there a way to address all enemy spawns that are currently active on the screen?

Thanks