Non physics collision problems

So I am trying to make two non physics objects interact with each other,but I’m doing something bad somewhere.

The console still prints “works” even when obj.y is different than beam.y-90. Here’s the code.

local ufo = display.newImageRect("ufo2.png" ,100,90) ufo.x = 100 ufo.y = 100 local beam = display.newImageRect("Beam.png" ,90,200) beam.isVisible = false local obj = display.newImageRect ("Icon.png",70,70) obj.x = 100 obj.y = 300 local sheetData = {width = 100,height = 90,numFrames = 8,sheetContentWidth = 200,sheetContentHeight = 360} local mySheet = graphics.newImageSheet ("ufo.png",sheetData) local sequenceData = {name = "ufo1",start = 1,count = 8,time = 950,loopcount = 0,looDirection = "forward"} local ufo1 = display.newSprite (mySheet,sequenceData) ufo1.x = 150 ufo1.y = 200 ufo1.isVisible = false function beamOn (event) if event.phase == "began" then beam.isVisible = true beam.x = ufo.x beam.y = ufo.y + 110 if beam.x \< 50 then beam.isVisible = false end end end ufo:addEventListener ("touch",beamOn) function beamOff (event) if event.phase == "ended" then beam.isVisible = false end end ufo:addEventListener ("touch",beamOff) function roads (event) if obj.x \< - 10 then obj.x = 300 else obj.x = obj.x - 1 end end Runtime:addEventListener ("enterFrame",roads) function onCollision( event ) if event.phase == "began" then if beam.y == obj.y - 90 then print("works") end elseif event.phase == "ended" then print("worked") end return true end Runtime:addEventListener ("touch",onCollision)

I also tried to look up at the Non physics collision detection tutorial,but I haven’t understand anything.Maybe some other examples…

Okay,meanwhile I copied a tutorial and addapted to another scene. But how do I implement it in my code above?                                                      

local ball = display.newImageRect("ball.png",100,100) ball.x = 100 ball.x = 50 local ground = display.newImageRect ("Icon.png",100,100) ground.x = 100 ground.y = 50 function hasCollided (event) if ball == nil then return false end if ground == nil then return false end local left = ball.contentBounds.xMin \<= ground.contentBounds.xMin and ball.contentBounds.xMax \>= ground.contentBounds.xMin local right = ball.contentBounds.xMin \>= ground.contentBounds.xMin and ball.contentBounds.xMin \<= ground.contentBounds.xMax local up = ball.contentBounds.yMin \<= ground.contentBounds.yMin and ball.contentBounds.yMax \>= ground.contentBounds.yMin local down = ball.contentBounds.yMin \>= ground.contentBounds.yMin and ball.contentBounds.yMin \<= ground.contentBounds.yMax return (left or right) and (up or down) end function onCollision(event) if hasCollided (ball,ground) then print ("works") end end Runtime:addEventListener ("enterFrame",onCollision)

When you use physics, Corona SDK will generate an event, i.e. it will notify your app that the collision has happened.  When you see this code:

function onCollision( event ) &nbsp;&nbsp;&nbsp; if event.phase == "began" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- do stuff &nbsp;&nbsp;&nbsp; elseif event.phase == "ended" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("worked") &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; return true end Runtime:addEventListener ("touch",onCollision)

Then that’s code that works **with** physics.

Physics based collisions are the only thing built into Corona SDK.  However as you found the non-physics collisions, you can do box overlap detection with some simple math.  However you are responsible for checking your objects yourself.    There are two basic concepts and are based on how you are moving your objects.

If you are using touch-drag to move an object, you can check, during the “moved” phase in the touch handler if your event.target (the object you’re dragging) has touched and objects you care about.  The best way to do that is have those objects in an array and run a simple for loop:

local function handleTouch( event ) &nbsp;&nbsp;&nbsp;&nbsp; ... &nbsp;&nbsp;&nbsp;&nbsp; if event.phase == "moved" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, #objectsICareAbout do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if hasCollided( event.target, objectsICareAbout[i]) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- do what you want to do when they collide &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- do a break statement if you can only collide with one thing for performance reasons &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true end

You of course are responsible in this case of adding a touch handler to the object you are dragging and to get your objects you care about colliding with into a table/array that you can easily test against.

Now if you’re moving your object through code, like a transition.to() or an “enterFrame” event, then you should use an enterFrame event to watch for collisions:

local function checkCollisions()

     for i = 1, #objectsICareAbout do

           if hasCollieded( myObject, objectsICareAbout[i] then

               – do what you want to do when they collide

               – do a break statement if you can only collide with one thing for performance reasons

           end

     end

end

Runtime:addEventListener( “enterFrame”, checkCollisions )

Rob

Hey Rob,

  Manage to do it,everything works fine.But there’s a catch. The system prints evrika nonstop and when hasCollided function is called the system also prints woks a couple of times. I only need to print works and evrika once. How to do that?

Plus I need 2 hascollided functions and 2 ednCollision functions in my final game,will that affect the performance really hard? I also need to improove the performance.

Here’s the code.  I got 99 lines of code and a bug in one :)) j/k

local ufo = display.newImageRect("ufo2.png" ,100,90) ufo.x = 100 ufo.y = 100 local beam = display.newImageRect("Beam.png" ,90,200) beam.isVisible = false local obj = display.newImageRect ("Icon.png",70,70) obj.x = 100 obj.y = 300 local sheetData = {width = 100,height = 90,numFrames = 8,sheetContentWidth = 200,sheetContentHeight = 360} local mySheet = graphics.newImageSheet ("ufo.png",sheetData) local sequenceData = {name = "ufo1",start = 1,count = 8,time = 950,loopcount = 0,looDirection = "forward"} local ufo1 = display.newSprite (mySheet,sequenceData) ufo1.x = 150 ufo1.y = 200 ufo1.isVisible = false function beamOn (event) if event.phase == "began" then beam.isVisible = true beam.x = ufo.x beam.y = ufo.y + 110 if beam.x \< 50 then beam.isVisible = false end end end ufo:addEventListener ("touch",beamOn) function beamOff (event) if event.phase == "ended" then beam.isVisible = false end end ufo:addEventListener ("touch",beamOff) function roads (event) if obj.x \< - 10 then obj.x = 300 else obj.x = obj.x - 1 end end Runtime:addEventListener ("enterFrame",roads) function hasCollided (event) if beam == nil then return false end if obj == nil then return false end local left = beam.contentBounds.xMin \<= obj.contentBounds.xMin and beam.contentBounds.xMax \>= obj.contentBounds.xMin local right = beam.contentBounds.xMin \>= obj.contentBounds.xMin and beam.contentBounds.xMin \<= obj.contentBounds.xMax local up = beam.contentBounds.yMin \<= obj.contentBounds.yMin and beam.contentBounds.yMax \>= obj.contentBounds.yMin local down = beam.contentBounds.yMin \>= obj.contentBounds.yMin and beam.contentBounds.yMin \<= obj.contentBounds.yMax return (left or right) and (up or down) end function endCollision (event) if beam == nil then return false end if obj == nil then return false end local left = beam.contentBounds.xMin ~= obj.contentBounds.xMin and beam.contentBounds.xMax ~= obj.contentBounds.xMin local right = beam.contentBounds.xMin ~= obj.contentBounds.xMin and beam.contentBounds.xMin ~= obj.contentBounds.xMax local up = beam.contentBounds.yMin ~= obj.contentBounds.yMin and beam.contentBounds.yMax ~= obj.contentBounds.yMin local down = beam.contentBounds.yMin ~= obj.contentBounds.yMin and beam.contentBounds.yMin ~= obj.contentBounds.yMax return (left or right) and (up or down) end function onCollision(event) if hasCollided (beam,obj) then if beam.isVisible == true then print ("works") --an animation will play end end if endCollision (beam,obj) then if beam.isVisible == false then print ("evrika") -- the animation will stop end end end Runtime:addEventListener ("enterFrame",onCollision)

Thank you!

The loop runs 30 or 60 times per second.  Your function is probably testing true for the collision being over (i.e. they are no longer colliding)  and therefore it prints evricka endlessly.

Yes I know that,but does that affect game performance?

Well any thing adds to the performance.  But if you’re not doing too much it won’t impact it too much.  I would remove the print statement.

Rob

Okay,meanwhile I copied a tutorial and addapted to another scene. But how do I implement it in my code above?                                                      

local ball = display.newImageRect("ball.png",100,100) ball.x = 100 ball.x = 50 local ground = display.newImageRect ("Icon.png",100,100) ground.x = 100 ground.y = 50 function hasCollided (event) if ball == nil then return false end if ground == nil then return false end local left = ball.contentBounds.xMin \<= ground.contentBounds.xMin and ball.contentBounds.xMax \>= ground.contentBounds.xMin local right = ball.contentBounds.xMin \>= ground.contentBounds.xMin and ball.contentBounds.xMin \<= ground.contentBounds.xMax local up = ball.contentBounds.yMin \<= ground.contentBounds.yMin and ball.contentBounds.yMax \>= ground.contentBounds.yMin local down = ball.contentBounds.yMin \>= ground.contentBounds.yMin and ball.contentBounds.yMin \<= ground.contentBounds.yMax return (left or right) and (up or down) end function onCollision(event) if hasCollided (ball,ground) then print ("works") end end Runtime:addEventListener ("enterFrame",onCollision)

When you use physics, Corona SDK will generate an event, i.e. it will notify your app that the collision has happened.  When you see this code:

function onCollision( event ) &nbsp;&nbsp;&nbsp; if event.phase == "began" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- do stuff &nbsp;&nbsp;&nbsp; elseif event.phase == "ended" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("worked") &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; return true end Runtime:addEventListener ("touch",onCollision)

Then that’s code that works **with** physics.

Physics based collisions are the only thing built into Corona SDK.  However as you found the non-physics collisions, you can do box overlap detection with some simple math.  However you are responsible for checking your objects yourself.    There are two basic concepts and are based on how you are moving your objects.

If you are using touch-drag to move an object, you can check, during the “moved” phase in the touch handler if your event.target (the object you’re dragging) has touched and objects you care about.  The best way to do that is have those objects in an array and run a simple for loop:

local function handleTouch( event ) &nbsp;&nbsp;&nbsp;&nbsp; ... &nbsp;&nbsp;&nbsp;&nbsp; if event.phase == "moved" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i = 1, #objectsICareAbout do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if hasCollided( event.target, objectsICareAbout[i]) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- do what you want to do when they collide &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- do a break statement if you can only collide with one thing for performance reasons &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true end

You of course are responsible in this case of adding a touch handler to the object you are dragging and to get your objects you care about colliding with into a table/array that you can easily test against.

Now if you’re moving your object through code, like a transition.to() or an “enterFrame” event, then you should use an enterFrame event to watch for collisions:

local function checkCollisions()

     for i = 1, #objectsICareAbout do

           if hasCollieded( myObject, objectsICareAbout[i] then

               – do what you want to do when they collide

               – do a break statement if you can only collide with one thing for performance reasons

           end

     end

end

Runtime:addEventListener( “enterFrame”, checkCollisions )

Rob

Hey Rob,

  Manage to do it,everything works fine.But there’s a catch. The system prints evrika nonstop and when hasCollided function is called the system also prints woks a couple of times. I only need to print works and evrika once. How to do that?

Plus I need 2 hascollided functions and 2 ednCollision functions in my final game,will that affect the performance really hard? I also need to improove the performance.

Here’s the code.  I got 99 lines of code and a bug in one :)) j/k

local ufo = display.newImageRect("ufo2.png" ,100,90) ufo.x = 100 ufo.y = 100 local beam = display.newImageRect("Beam.png" ,90,200) beam.isVisible = false local obj = display.newImageRect ("Icon.png",70,70) obj.x = 100 obj.y = 300 local sheetData = {width = 100,height = 90,numFrames = 8,sheetContentWidth = 200,sheetContentHeight = 360} local mySheet = graphics.newImageSheet ("ufo.png",sheetData) local sequenceData = {name = "ufo1",start = 1,count = 8,time = 950,loopcount = 0,looDirection = "forward"} local ufo1 = display.newSprite (mySheet,sequenceData) ufo1.x = 150 ufo1.y = 200 ufo1.isVisible = false function beamOn (event) if event.phase == "began" then beam.isVisible = true beam.x = ufo.x beam.y = ufo.y + 110 if beam.x \< 50 then beam.isVisible = false end end end ufo:addEventListener ("touch",beamOn) function beamOff (event) if event.phase == "ended" then beam.isVisible = false end end ufo:addEventListener ("touch",beamOff) function roads (event) if obj.x \< - 10 then obj.x = 300 else obj.x = obj.x - 1 end end Runtime:addEventListener ("enterFrame",roads) function hasCollided (event) if beam == nil then return false end if obj == nil then return false end local left = beam.contentBounds.xMin \<= obj.contentBounds.xMin and beam.contentBounds.xMax \>= obj.contentBounds.xMin local right = beam.contentBounds.xMin \>= obj.contentBounds.xMin and beam.contentBounds.xMin \<= obj.contentBounds.xMax local up = beam.contentBounds.yMin \<= obj.contentBounds.yMin and beam.contentBounds.yMax \>= obj.contentBounds.yMin local down = beam.contentBounds.yMin \>= obj.contentBounds.yMin and beam.contentBounds.yMin \<= obj.contentBounds.yMax return (left or right) and (up or down) end function endCollision (event) if beam == nil then return false end if obj == nil then return false end local left = beam.contentBounds.xMin ~= obj.contentBounds.xMin and beam.contentBounds.xMax ~= obj.contentBounds.xMin local right = beam.contentBounds.xMin ~= obj.contentBounds.xMin and beam.contentBounds.xMin ~= obj.contentBounds.xMax local up = beam.contentBounds.yMin ~= obj.contentBounds.yMin and beam.contentBounds.yMax ~= obj.contentBounds.yMin local down = beam.contentBounds.yMin ~= obj.contentBounds.yMin and beam.contentBounds.yMin ~= obj.contentBounds.yMax return (left or right) and (up or down) end function onCollision(event) if hasCollided (beam,obj) then if beam.isVisible == true then print ("works") --an animation will play end end if endCollision (beam,obj) then if beam.isVisible == false then print ("evrika") -- the animation will stop end end end Runtime:addEventListener ("enterFrame",onCollision)

Thank you!

The loop runs 30 or 60 times per second.  Your function is probably testing true for the collision being over (i.e. they are no longer colliding)  and therefore it prints evricka endlessly.

Yes I know that,but does that affect game performance?

Well any thing adds to the performance.  But if you’re not doing too much it won’t impact it too much.  I would remove the print statement.

Rob