Collision Detection Without Physics.

Hello everyone,

I want to detect when two images hit each other on the screen. I’ve used Rob Miracles code but I am facing few problems while detection.

      http://omnigeek.robmiracle.com/2011/12/14/collision-detection-without-physics/

I have a Ball and few obstacles which are being generated randomly on the screen. I just want to destroy the ball when it collides with an obstacle.

There is uncertainty in detection code. Sometimes it work and sometimes it doesn’t.

Explaining my problem further more:

When the ball hits first few obstacles, it shows detection properly but after that it stops working for few seconds and works again and then so on.

Here is my code:

--BALL local myCircle = display.newCircle( \_W\*0.5, \_H - 100, 30 ) myCircle:setFillColor( 0.5 ) myCircle.strokeWidth = 5 myCircle:setStrokeColor( 1, 0, 0 ) --COLLISION DETECTION local function hasCollided(obj1, obj2) if obj1 == nil then &nbsp;return false end if obj2 == nil then &nbsp;return false end local left = obj1.contentBounds.xMin \<= obj2.contentBounds.xMin and obj1.contentBounds.xMax \>= obj2.contentBounds.xMin local right = obj1.contentBounds.xMin \>= obj2.contentBounds.xMin and obj1.contentBounds.xMin \<= obj2.contentBounds.xMax&nbsp; local up = obj1.contentBounds.yMin \<= obj2.contentBounds.yMin and obj1.contentBounds.yMax \>= obj2.contentBounds.yMin local down = obj1.contentBounds.yMin \>= obj2.contentBounds.yMin and obj1.contentBounds.yMin \<= obj2.contentBounds.yMax return (left or right) and (up or down) end --RANDOMLY ADDING OBSTACLES local function addBlock() block = display.newImage("images/objects/"..objectName..".png") block.x, block.y = 1 + math.random(450), -0 block.shape = objectShape blocksGroup:insert(block) block.type = "block" blocks[#blocks+1] = block end --OBSTACLE COLLISION local function blockCollisions() for i = 1, #blocks do if hasCollided(blocks[i], myCircle) then &nbsp; remove\_block(i) end end end myCircle:addEventListener( "touch", xDrag ) blocksTimer = timer.performWithDelay( obstaclesGenerationTime, &nbsp;addBlock, -1 ) Runtime:addEventListener("enterFrame", blockCollisions)

Any help would be highly appreciated.

Thanks,

When looping lists of objects and removing them you need to do it backwards

for i = #objects, 1, -1 do --check for collision and remove object end

I tried to do it backwards as well but it failed again.

I use a similar method in a game and I have hundreds of objects all colliding nicely so I know it works. 

What is in the function remove_block(i**)**?

local function remove\_block(num) blocks[num]:removeSelf() blocks[num] = nil end

There are some problems like

  1. It doesn’t check for collision until it overlaps the image more than expected.

  2. If I decrease timer speed. Then collision fails.

THIS FAILS

blocksTimer = timer.performWithDelay(500, &nbsp;addBlock, -1 )

THIS WORKS

blocksTimer = timer.performWithDelay(800, &nbsp;addBlock, -1 )

Please help me out.

My guess is, it’s because of the way you remove your blocks when you detect a collision as you don’t fill the gap and as a result the length of the array won’t be correct anymore.

Try using table.remove instead.

[lua]

local function remove_block(num)

    blocks[num]:removeSelf()

    table.remove( blocks, num )

end

[/lua]

Thank you so much, you saved my day.

Tysssssssssssssmmmmmmmmmmmmmmmmmmmmmmm

I can’t express my amusement this time. So happy  :) Thank you

And thanks to SGS as well.

:))))))) CHEERS

contentBounds  checking is not the best for circular shapes.  As you will get collisions on the alpha part of images.

This will be much more accurate for circular objects

function isCollision(obj1, obj2) if obj1 and obj2 then local sqrt = math.sqrt local dx = obj1.x - obj1.x local dy = obj2.y - obj2.y local distance = sqrt(dx\*dx + dy\*dy) local objectSize = (obj1.contentWidth/2) + (obj2.contentWidth/2) return distance \< objectSize else return false end end

The official tutorial is here: https://docs.coronalabs.com/tutorial/games/nonPhysicalCollision/index.html

It covers both circular and square objects.

Rob

Thanks Rob.

When looping lists of objects and removing them you need to do it backwards

for i = #objects, 1, -1 do --check for collision and remove object end

I tried to do it backwards as well but it failed again.

I use a similar method in a game and I have hundreds of objects all colliding nicely so I know it works. 

What is in the function remove_block(i**)**?

local function remove\_block(num) blocks[num]:removeSelf() blocks[num] = nil end

There are some problems like

  1. It doesn’t check for collision until it overlaps the image more than expected.

  2. If I decrease timer speed. Then collision fails.

THIS FAILS

blocksTimer = timer.performWithDelay(500, &nbsp;addBlock, -1 )

THIS WORKS

blocksTimer = timer.performWithDelay(800, &nbsp;addBlock, -1 )

Please help me out.

My guess is, it’s because of the way you remove your blocks when you detect a collision as you don’t fill the gap and as a result the length of the array won’t be correct anymore.

Try using table.remove instead.

[lua]

local function remove_block(num)

    blocks[num]:removeSelf()

    table.remove( blocks, num )

end

[/lua]

Thank you so much, you saved my day.

Tysssssssssssssmmmmmmmmmmmmmmmmmmmmmmm

I can’t express my amusement this time. So happy  :) Thank you

And thanks to SGS as well.

:))))))) CHEERS

contentBounds  checking is not the best for circular shapes.  As you will get collisions on the alpha part of images.

This will be much more accurate for circular objects

function isCollision(obj1, obj2) if obj1 and obj2 then local sqrt = math.sqrt local dx = obj1.x - obj1.x local dy = obj2.y - obj2.y local distance = sqrt(dx\*dx + dy\*dy) local objectSize = (obj1.contentWidth/2) + (obj2.contentWidth/2) return distance \< objectSize else return false end end

The official tutorial is here: https://docs.coronalabs.com/tutorial/games/nonPhysicalCollision/index.html

It covers both circular and square objects.

Rob

Thanks Rob.