Getting sound to play when object flys over another object

Hi there,

I have a little game that I am writing where I want a sound to play when the plane flys over some island. But I think my collision detection function is incorrect?

Here is the collision detection code and the physics body types for the two display objects:

physics.addBody(plane, "kinematic", {bounce = 0})  
plane.name = "plane"  
  
physics.addBody(island, "static", {bounce = 0})  
island.name = "island"  
  
function plane:collision(event)  
 if(event.phase == "began")then  
 if(event.self.name == "island")then   
 audio.play(sounds.yay)  
 end   
 end   
end  
plane:addEventListener( "collision", plane )  

Thanks [import]uid: 167310 topic_id: 30813 reply_id: 330813[/import]

Hey lblake,

Just at first glance I think line 9 should be;

[lua] if(event.other.name == “island”)then [/lua]

since you attach the collision detection to the plane, the plane would be ‘self’ and the island would be ‘other’ for collision events.

At least that’s just at first glance, I havn’t tested out the code, so let me know what happens.

Brian. [import]uid: 40731 topic_id: 30813 reply_id: 123295[/import]

Hi Brian,

I changed the code as suggested but no sound was played when the plane flew over the island?

I don’t the objects are colliding with each other? I put the following print statement:

if(event.other.name == "island")then  
 print("Began: " .. event.other.name .. "collided with " .. event.target.name)  
 audio.play(sounds.yay)  
 end  

But nothing is printed to the terminal so it’s back to the drawing board.

Thanks

[import]uid: 167310 topic_id: 30813 reply_id: 123311[/import]

Actually after testing it out I found it’s because of the physics body types.

If you do not need island being “static” and the plane being “kinematic” then you can set them to “dynamic” (default).

Although if you need the two bodies to remain the way they are, then I typed out this code for you;

[lua]local W = display.contentWidth
local H = display.contentHeight

local physics = require"physics"

physics.start()

physics.setGravity( 0, 0 )

sqrt = math.sqrt

local playMusic = false

local obj = display.newCircle( 0, 0, 25)
local island = display.newCircle(0,0, 50)
island.x = W/2; island.y = H/2
island.alpha = 0.5
island.isSleepingAllowed = false
island.name = “island”

local function dragit(e)
if e.phase == “moved” then
obj.x = e.x
obj.y = e.y
end
end

Runtime:addEventListener(“touch”, dragit)

function trackImg()
local objX = obj.x --Cache the obj.x position
local objY = obj.y --Cache the obj.y position

local disX = objX - island.x
local disY = objY - island.y

local distance = sqrt(disX*disX + disY*disY) – Calculate the distance between objects

if distance < 40 and playMusic == false then
–Collision
playMusic = true
print(“play music”)
elseif distance > 40 and playMusic == true then
playMusic = false
end

end
Runtime:addEventListener( “enterFrame”, trackImg )[/lua]

This code can track two images without physics. It simply tracks the distance between them, using the distance you can mimic collision.

Hope it helps.

Brian [import]uid: 40731 topic_id: 30813 reply_id: 123319[/import]

Thanks for the information, perhaps I should have said that I have a scrolling background with an island and some clouds scrolling downwards. At the moment the island moves at the same speed as the background. And I have a plane at the bottom of the screen when the plane moves over the island the sound is suppose to play? If I change the plane and island to ‘dynamic’ objects they fall off the screen

Here is my code:

[code]
display.setStatusBar(display.HiddenStatusBar)

require(“physics”)
physics.start()
physics.setGravity(0, 25)

local gameLayer = display.newGroup()
local islandLayer = display.newGroup()
local cloudLayer = display.newGroup()
local halfPlayerWidth
local textureCache = {}
textureCache[1] = display.newImage(“images/island.gif”); textureCache[1].isVisible = false;
textureCache[2] = display.newImage(“images/cloud.gif”); textureCache[2].isVisible = false;

local halfEnemyWidth = textureCache[1].contentWidth * .5

local sounds = {

engine = audio.loadStream(“media/airplane.mp3” ),
thunder = audio.loadSound(“media/fail.caf”),
yay = audio.loadSound(“media/win.caf”)
}
– Adjust the volume
audio.setMaxVolume( 0.95, { channel=1 } )

local island = display.newImage(islandLayer,“images/island.gif”)

island:setReferencePoint(display.CenterReferencePoint)
island.x = display.contentWidth - island.width
island.y = display.contentHeight- island.height
physics.addBody(island, “static”, {bounce = 0})

island.name = “island”

local cloud1 = display.newImage(cloudLayer, “images/cloud.gif”)

cloud1:setReferencePoint(display.CenterRightReferencePoint)
cloud1.x = display.contentCenterX
cloud1.y = display.contentCenterY
physics.addBody(cloud1,“static”, {bounce = 0})

cloud1.name = “cloud1”

local cloud2 = display.newImage(cloudLayer, “images/cloud.gif”)

cloud2:setReferencePoint(display.CenterLeftReferencePoint)
cloud2.x = 50
cloud2.y = 100
physics.addBody(cloud2,“static”, {bounce = 0})

cloud2.name = “cloud2”
– Load and position the plane
plane = display.newImage(“images/plane.png”)
plane.x = display.contentCenterX
plane.y = display.contentHeight - plane.contentHeight
halfPlayerWidth = plane.contentWidth * .5
– Add a physics body. It is kinematic, so it doesn’t react to gravity.
physics.addBody(plane, “kinematic”, {bounce = 0})

plane.name = “plane”

local function movePlane( event )
– Only move to the screen boundaries
if event.x >= halfPlayerWidth and event.x <= display.contentWidth - halfPlayerWidth then
– Update plane x axis
plane.x = event.x
end
end
plane:addEventListener( “touch”, movePlane )
local scrollbg1 = display.newImage(gameLayer,“images/ocean.gif”)
scrollbg1:setReferencePoint( display.CenterLeftReferencePoint )
scrollbg1.x = 0
scrollbg1.y = 0

local scrollbg2 = display.newImage(gameLayer, “images/ocean.gif”)
scrollbg2:setReferencePoint( display.CenterLeftReferencePoint )
scrollbg2.x = 0
scrollbg2.y = 480

local tPrevious = system.getTimer( )

local function move(event)
audio.play(sounds.engine)

local tDelta = event.time - tPrevious
tPrevious = event.time
local yOffset = (0.14 * tDelta)

local islandOffset = (1 * tDelta)

island.y = island.y + yOffset
if(island.y > 480)then
island:translate(0, -320*2)
end

scrollbg1.y = scrollbg1.y + yOffset
scrollbg2.y = scrollbg2.y + yOffset

if (scrollbg1.y > 480)then
scrollbg1:translate(0, -320*2)
end
if (scrollbg2.y > 480) then
scrollbg2:translate( 0, -320*2 )
end
end
Runtime:addEventListener( “enterFrame”, move )
function plane:collision(event)
if(event.phase == “began”)then
if(event.other.name == “island”)then
print("Began: " … event.other.name … "collided with " … event.target.name)
audio.play(sounds.yay)
end

end
end
plane:addEventListener( “collision”, plane )

[/code] [import]uid: 167310 topic_id: 30813 reply_id: 123320[/import]

Two questions for ya.

1- I noticed all the bodies are either “static” or “kinematic”, so what is the purpose of gravity, if there is no purpose I suggest setting it to (0,0)?

2- What is the image dimensions of the island, does it cover the bottom of the screen?

And also as a tip; if you’re using physics collisions the two bodies must be in the same display group (I see island is in a display group, but not the plane)

[import]uid: 40731 topic_id: 30813 reply_id: 123321[/import]

Hello all,
Some points of clarification:

  1. If I recall from some older code I worked on, kinematic bodies don’t collide with static bodies… ever. In general, to be safe, you should set at least one of the bodies to dynamic if you need a collision to occur. I believe this is Box2D behavior beyond Corona’s control.

  2. Objects actually can be in different display groups and still collide. This is not the problem in this case. :wink:

Brent [import]uid: 9747 topic_id: 30813 reply_id: 123369[/import]

Thanks for all the suggestion I’ll take another look at my code to see where I am going wrong… [import]uid: 167310 topic_id: 30813 reply_id: 123372[/import]

Oh cool!

I was living in the past for a while. Thanks for clearing that up. [import]uid: 40731 topic_id: 30813 reply_id: 123423[/import]

Hey lblake,

Just at first glance I think line 9 should be;

[lua] if(event.other.name == “island”)then [/lua]

since you attach the collision detection to the plane, the plane would be ‘self’ and the island would be ‘other’ for collision events.

At least that’s just at first glance, I havn’t tested out the code, so let me know what happens.

Brian. [import]uid: 40731 topic_id: 30813 reply_id: 123295[/import]

Hi Brian,

I changed the code as suggested but no sound was played when the plane flew over the island?

I don’t the objects are colliding with each other? I put the following print statement:

if(event.other.name == "island")then  
 print("Began: " .. event.other.name .. "collided with " .. event.target.name)  
 audio.play(sounds.yay)  
 end  

But nothing is printed to the terminal so it’s back to the drawing board.

Thanks

[import]uid: 167310 topic_id: 30813 reply_id: 123311[/import]

Actually after testing it out I found it’s because of the physics body types.

If you do not need island being “static” and the plane being “kinematic” then you can set them to “dynamic” (default).

Although if you need the two bodies to remain the way they are, then I typed out this code for you;

[lua]local W = display.contentWidth
local H = display.contentHeight

local physics = require"physics"

physics.start()

physics.setGravity( 0, 0 )

sqrt = math.sqrt

local playMusic = false

local obj = display.newCircle( 0, 0, 25)
local island = display.newCircle(0,0, 50)
island.x = W/2; island.y = H/2
island.alpha = 0.5
island.isSleepingAllowed = false
island.name = “island”

local function dragit(e)
if e.phase == “moved” then
obj.x = e.x
obj.y = e.y
end
end

Runtime:addEventListener(“touch”, dragit)

function trackImg()
local objX = obj.x --Cache the obj.x position
local objY = obj.y --Cache the obj.y position

local disX = objX - island.x
local disY = objY - island.y

local distance = sqrt(disX*disX + disY*disY) – Calculate the distance between objects

if distance < 40 and playMusic == false then
–Collision
playMusic = true
print(“play music”)
elseif distance > 40 and playMusic == true then
playMusic = false
end

end
Runtime:addEventListener( “enterFrame”, trackImg )[/lua]

This code can track two images without physics. It simply tracks the distance between them, using the distance you can mimic collision.

Hope it helps.

Brian [import]uid: 40731 topic_id: 30813 reply_id: 123319[/import]

Thanks for the information, perhaps I should have said that I have a scrolling background with an island and some clouds scrolling downwards. At the moment the island moves at the same speed as the background. And I have a plane at the bottom of the screen when the plane moves over the island the sound is suppose to play? If I change the plane and island to ‘dynamic’ objects they fall off the screen

Here is my code:

[code]
display.setStatusBar(display.HiddenStatusBar)

require(“physics”)
physics.start()
physics.setGravity(0, 25)

local gameLayer = display.newGroup()
local islandLayer = display.newGroup()
local cloudLayer = display.newGroup()
local halfPlayerWidth
local textureCache = {}
textureCache[1] = display.newImage(“images/island.gif”); textureCache[1].isVisible = false;
textureCache[2] = display.newImage(“images/cloud.gif”); textureCache[2].isVisible = false;

local halfEnemyWidth = textureCache[1].contentWidth * .5

local sounds = {

engine = audio.loadStream(“media/airplane.mp3” ),
thunder = audio.loadSound(“media/fail.caf”),
yay = audio.loadSound(“media/win.caf”)
}
– Adjust the volume
audio.setMaxVolume( 0.95, { channel=1 } )

local island = display.newImage(islandLayer,“images/island.gif”)

island:setReferencePoint(display.CenterReferencePoint)
island.x = display.contentWidth - island.width
island.y = display.contentHeight- island.height
physics.addBody(island, “static”, {bounce = 0})

island.name = “island”

local cloud1 = display.newImage(cloudLayer, “images/cloud.gif”)

cloud1:setReferencePoint(display.CenterRightReferencePoint)
cloud1.x = display.contentCenterX
cloud1.y = display.contentCenterY
physics.addBody(cloud1,“static”, {bounce = 0})

cloud1.name = “cloud1”

local cloud2 = display.newImage(cloudLayer, “images/cloud.gif”)

cloud2:setReferencePoint(display.CenterLeftReferencePoint)
cloud2.x = 50
cloud2.y = 100
physics.addBody(cloud2,“static”, {bounce = 0})

cloud2.name = “cloud2”
– Load and position the plane
plane = display.newImage(“images/plane.png”)
plane.x = display.contentCenterX
plane.y = display.contentHeight - plane.contentHeight
halfPlayerWidth = plane.contentWidth * .5
– Add a physics body. It is kinematic, so it doesn’t react to gravity.
physics.addBody(plane, “kinematic”, {bounce = 0})

plane.name = “plane”

local function movePlane( event )
– Only move to the screen boundaries
if event.x >= halfPlayerWidth and event.x <= display.contentWidth - halfPlayerWidth then
– Update plane x axis
plane.x = event.x
end
end
plane:addEventListener( “touch”, movePlane )
local scrollbg1 = display.newImage(gameLayer,“images/ocean.gif”)
scrollbg1:setReferencePoint( display.CenterLeftReferencePoint )
scrollbg1.x = 0
scrollbg1.y = 0

local scrollbg2 = display.newImage(gameLayer, “images/ocean.gif”)
scrollbg2:setReferencePoint( display.CenterLeftReferencePoint )
scrollbg2.x = 0
scrollbg2.y = 480

local tPrevious = system.getTimer( )

local function move(event)
audio.play(sounds.engine)

local tDelta = event.time - tPrevious
tPrevious = event.time
local yOffset = (0.14 * tDelta)

local islandOffset = (1 * tDelta)

island.y = island.y + yOffset
if(island.y > 480)then
island:translate(0, -320*2)
end

scrollbg1.y = scrollbg1.y + yOffset
scrollbg2.y = scrollbg2.y + yOffset

if (scrollbg1.y > 480)then
scrollbg1:translate(0, -320*2)
end
if (scrollbg2.y > 480) then
scrollbg2:translate( 0, -320*2 )
end
end
Runtime:addEventListener( “enterFrame”, move )
function plane:collision(event)
if(event.phase == “began”)then
if(event.other.name == “island”)then
print("Began: " … event.other.name … "collided with " … event.target.name)
audio.play(sounds.yay)
end

end
end
plane:addEventListener( “collision”, plane )

[/code] [import]uid: 167310 topic_id: 30813 reply_id: 123320[/import]

Two questions for ya.

1- I noticed all the bodies are either “static” or “kinematic”, so what is the purpose of gravity, if there is no purpose I suggest setting it to (0,0)?

2- What is the image dimensions of the island, does it cover the bottom of the screen?

And also as a tip; if you’re using physics collisions the two bodies must be in the same display group (I see island is in a display group, but not the plane)

[import]uid: 40731 topic_id: 30813 reply_id: 123321[/import]

Hello all,
Some points of clarification:

  1. If I recall from some older code I worked on, kinematic bodies don’t collide with static bodies… ever. In general, to be safe, you should set at least one of the bodies to dynamic if you need a collision to occur. I believe this is Box2D behavior beyond Corona’s control.

  2. Objects actually can be in different display groups and still collide. This is not the problem in this case. :wink:

Brent [import]uid: 9747 topic_id: 30813 reply_id: 123369[/import]

Thanks for all the suggestion I’ll take another look at my code to see where I am going wrong… [import]uid: 167310 topic_id: 30813 reply_id: 123372[/import]

Oh cool!

I was living in the past for a while. Thanks for clearing that up. [import]uid: 40731 topic_id: 30813 reply_id: 123423[/import]