Hi all. I need help to solve this problem. The game is similar to a pinball game. The problem is that the sound of the ball is triggered simultaneously when it collides with two objects at the same time and the result is a stronger sound. In the picture you can better appreciate what I am describing. Any help on how to solve this?
Can you make a small sample that demonstrates the physics interaction? Then people can take a swing and helping implement the sound part.
I usually just put a cooldown bool on objects, set it to true when a sound is played, set to false again after a short delay. Then in collision function only play a sound if cooldown is false on that object
Question - Are you saying:
- You want only one sound to play no matter how many collisions occur in a short period?
- OR -
- You want to play sound A for single collision, B for ‘dual’ collision, C …?
If #1, then do what Nick says, or use/look at my sound lib which has a built-in limiter.
https://roaminggamer.github.io/RGDocs/pages/SSK2/libraries/soundMgr/#adding-sounds
-- Boing sound can only be played every 200 ms or less frequently soundMgr.add( "boing", "sounds/sfx/boing.mp3", { soundType = "effect", preload = true, minTweenTime = 200 } )
Note: Nick’s solution is associated with the ‘ball’ so it makes more sense in this case. My code would limit playing the ‘boing’ sound (shared) for all balls.
If #2, that is something you’ll need to use a delay for probably. i.e. Accumulate, then one frame later play sound.
What I want is that the sound is heard in each collision, regardless of when the collisions occur, they can be fractions of a second or up to 2 seconds (+, -). What I do not want is that if in a particular case the ball collides with two objects with similar physical properties and similar sound, the sound effect will be heard harder. What I think happens is that as the sound is not assigned to a specific channel and when it collides with two objects at the same time you hear the same sound twice causing the sound increase in volume because two channels are playing the same sound at the same time.
I am trying to attach a .rar to show the example but I do not have permission to upload this type of files. Any suggestions?
I think it’s simpler this way. Just copy this code and paste it in a new project main.lua and add any sound with the name boing.
-- sound test to the forums local centerX = display.contentCenterX local centerY = display.contentCenterY local obt local boing = audio.loadSound("boing.wav") local physics = require( "physics" ) physics.start() --collision local function onLocalCollision( self, event ) if ( event.phase == "began" ) then if (self.id == "ball" and event.other.id == "bars") then audio.play( boing ) display.remove( obj[1]) end end end --ball local ballColor = { 0, 128, 0 } local ball = display.newCircle( centerX, centerY-400, 30 ) --300 ball.fill = ballColor ball.id = "ball" physics.addBody( ball, { density=0.8, friction=1.0, bounce=0.5, radius=30 } ) ball.collision = onLocalCollision ball:addEventListener( "collision", ball ) --objects obj = {} local numOfObj = 3 for i = 1, numOfObj do obj[i] = display.newRect( 0, 0, 30, 50 ) obj[i]:setFillColor( 255, 0, 0 ) obj[i].id = "bars" physics.addBody( obj[i], "static", { friction=0, bounce=0 } ) end obj[1].x = centerX obj[1].y = centerY-65 obj[2].x = centerX-25 obj[2].y = centerY+75 obj[3].x = centerX+25 obj[3].y = centerY+75
Geesh… just have 2 sounds. 1 for a single hit and another for a dual hit.
(Corona will not play the same sound twice if the first sound is currently playing)
Thanks @SGS but 2 sounds do not resolve my problem… Is a pinball like game… At least it would need 45 equal sounds but with different names for each dual hit collision.
@Dodi - That site gets flagged as unsafe for me.
In the future I suggest using a reputable download source like Github (you can create a free account) or dropbox (again free).
Yeah, you can’t really do that. The sounds won’t sum. i.e. simultaneous sounds are not additive
The best you can do is defer the sound and play just one sound louder, but you’ll have to start at something below 1.0 to increase.
https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2019/04/dodi_sound.zip
io.output():setvbuf("no") display.setStatusBar(display.HiddenStatusBar) -- ===================================================== --require "ssk2.loadSSK" --\_G.ssk.init( { measure = false } ) --ssk.meters.create\_fps(true) --ssk.meters.create\_mem(true) --ssk.misc.enableScreenshotHelper("s") -- ===================================================== local cx = display.contentCenterX local cy = display.contentCenterY local fullw = display.actualContentWidth local fullh = display.actualContentHeight local left = cx - fullw/2 local right = cx + fullw/2 local top = cy - fullh/2 local bottom = cy + fullh/2 -- == Uncomment following lines if you need physics local physics = require "physics" physics.start() physics.setGravity(0,10) physics.setDrawMode("hybrid") -- ===================================================== -- YOUR CODE BELOW -- ===================================================== -- sound test to the forums local centerX = display.contentCenterX local centerY = display.contentCenterY local obt local boing = audio.loadSound("boing.mp3") local physics = require( "physics" ) physics.start() local baseVolume = 0.25 local function onTimer( self ) local channel = audio.findFreeChannel( 1 ) self.boing = (self.boing or 1) print( "BOING ", baseVolume \* self.boing ) audio.setVolume( baseVolume \* self.boing, { channel = channel } ) -- set the volume on channel 1 audio.play( boing, { channel = channel } ) self.boingTimer = nil self.boing = 1 end --collision local function onLocalCollision( self, event ) if ( event.phase == "began" ) then if (self.id == "ball" and event.other.id == "bars") then --audio.play( boing ) self.boing = (self.boing) and (self.boing + 1) or 1 if( self.boingTimer ) then timer.cancel(self.boingTimer) end self.boingTimer = timer.performWithDelay( 1,self ) display.remove( obj[1]) end end end --ball local ballColor = { 0, 128, 0 } local ball = display.newCircle( centerX, centerY-400, 30 ) --300 ball.fill = ballColor ball.id = "ball" physics.addBody( ball, { density=0.8, friction=1.0, bounce=0.5, radius=30 } ) ball.collision = onLocalCollision ball:addEventListener( "collision", ball ) ball.timer = onTimer --objects obj = {} local numOfObj = 3 for i = 1, numOfObj do obj[i] = display.newRect( 0, 0, 30, 50 ) obj[i]:setFillColor( 255, 0, 0 ) obj[i].id = "bars" physics.addBody( obj[i], "static", { friction=0, bounce=0 } ) end obj[1].x = centerX obj[1].y = centerY-65 obj[2].x = centerX-25 obj[2].y = centerY+75 obj[3].x = centerX+25 obj[3].y = centerY+75
I want to thank all those who contributed their help. After playing hours with the roaminggamer’s code, I return to the topic and read well the comment of nick_sherman. I have added this function and the problem has been solved. Here I leave the code for those who want to try. Apparently the physical objects do not collide at the same time in any situation, there is always a small delay.
-- sound test to the forums local centerX = display.contentCenterX local centerY = display.contentCenterY local obt local boing = audio.loadSound("boing.wav") local soundValue = true local physics = require( "physics" ) physics.start() --prevent boing sound from being heard twice------------------------------- local function playBoingSound( event ) if (soundValue == true) then audio.play( boing ) soundValue = false end timer.performWithDelay(10, function() soundValue = true end ) end ----------------------------------------------------------------------------- --collision local function onLocalCollision( self, event ) if ( event.phase == "began" ) then if (self.id == "ball" and event.other.id == "bars") then playBoingSound() --audio.play( boing )------------------------------function added display.remove( obj[1]) end end end --ball local ballColor = { 0, 128, 0 } local ball = display.newCircle( centerX, centerY-400, 30 ) --300 ball.fill = ballColor ball.id = "ball" physics.addBody( ball, { density=0.8, friction=1.0, bounce=0.5, radius=30 } ) ball.collision = onLocalCollision ball:addEventListener( "collision", ball ) --objects obj = {} local numOfObj = 3 for i = 1, numOfObj do obj[i] = display.newRect( 0, 0, 30, 50 ) obj[i]:setFillColor( 255, 0, 0 ) obj[i].id = "bars" physics.addBody( obj[i], "static", { friction=0, bounce=0 } ) end obj[1].x = centerX obj[1].y = centerY-65 obj[2].x = centerX-25 obj[2].y = centerY+75 obj[3].x = centerX+25 obj[3].y = centerY+75
Can you make a small sample that demonstrates the physics interaction? Then people can take a swing and helping implement the sound part.
I usually just put a cooldown bool on objects, set it to true when a sound is played, set to false again after a short delay. Then in collision function only play a sound if cooldown is false on that object
Question - Are you saying:
- You want only one sound to play no matter how many collisions occur in a short period?
- OR -
- You want to play sound A for single collision, B for ‘dual’ collision, C …?
If #1, then do what Nick says, or use/look at my sound lib which has a built-in limiter.
https://roaminggamer.github.io/RGDocs/pages/SSK2/libraries/soundMgr/#adding-sounds
-- Boing sound can only be played every 200 ms or less frequently soundMgr.add( "boing", "sounds/sfx/boing.mp3", { soundType = "effect", preload = true, minTweenTime = 200 } )
Note: Nick’s solution is associated with the ‘ball’ so it makes more sense in this case. My code would limit playing the ‘boing’ sound (shared) for all balls.
If #2, that is something you’ll need to use a delay for probably. i.e. Accumulate, then one frame later play sound.
What I want is that the sound is heard in each collision, regardless of when the collisions occur, they can be fractions of a second or up to 2 seconds (+, -). What I do not want is that if in a particular case the ball collides with two objects with similar physical properties and similar sound, the sound effect will be heard harder. What I think happens is that as the sound is not assigned to a specific channel and when it collides with two objects at the same time you hear the same sound twice causing the sound increase in volume because two channels are playing the same sound at the same time.
I am trying to attach a .rar to show the example but I do not have permission to upload this type of files. Any suggestions?
I think it’s simpler this way. Just copy this code and paste it in a new project main.lua and add any sound with the name boing.
-- sound test to the forums local centerX = display.contentCenterX local centerY = display.contentCenterY local obt local boing = audio.loadSound("boing.wav") local physics = require( "physics" ) physics.start() --collision local function onLocalCollision( self, event ) if ( event.phase == "began" ) then if (self.id == "ball" and event.other.id == "bars") then audio.play( boing ) display.remove( obj[1]) end end end --ball local ballColor = { 0, 128, 0 } local ball = display.newCircle( centerX, centerY-400, 30 ) --300 ball.fill = ballColor ball.id = "ball" physics.addBody( ball, { density=0.8, friction=1.0, bounce=0.5, radius=30 } ) ball.collision = onLocalCollision ball:addEventListener( "collision", ball ) --objects obj = {} local numOfObj = 3 for i = 1, numOfObj do obj[i] = display.newRect( 0, 0, 30, 50 ) obj[i]:setFillColor( 255, 0, 0 ) obj[i].id = "bars" physics.addBody( obj[i], "static", { friction=0, bounce=0 } ) end obj[1].x = centerX obj[1].y = centerY-65 obj[2].x = centerX-25 obj[2].y = centerY+75 obj[3].x = centerX+25 obj[3].y = centerY+75
Geesh… just have 2 sounds. 1 for a single hit and another for a dual hit.
(Corona will not play the same sound twice if the first sound is currently playing)
Thanks @SGS but 2 sounds do not resolve my problem… Is a pinball like game… At least it would need 45 equal sounds but with different names for each dual hit collision.