How can I detect object collision without physics?

All I have in my game is a player, which is this:

local player = display.newRect(30, centerY - 20, 20, 20) player:setFillColor(0.5)

Movement buttons, which are these:

local upArrow = display.newImage("arrows/up.png", 50, centerY + 30) local downArrow = display.newImage("arrows/down.png", 50, centerY + 130) local rightArrow = display.newImage("arrows/right.png", 100, centerY + 80) local leftArrow = display.newImage("arrows/left.png", 0, centerY + 80)

They work like this:

function moveUp( event ) player.y = player.y - 5 end upArrow:addEventListener("tap", moveUp)

And I have objects that I named blocks(which are these white “walls”):

local block1 = display.newRect(centerX, centerY - 50, 100, 220) local block2 = display.newRect(centerX + 125, centerY + 135, 350, 80) local block3 = display.newRect(centerX + 188, centerY + 45, 200, 100) local block4 = display.newRect(centerX + 100, centerY - 100, 100, 125) local block5 = display.newRect(centerX + 240, centerY - 50, 100, 100) local block6 = display.newRect(centerX + 230, centerY - 160, 160, 50)

How could I detect the player hitting one of these blocks?

You could write an enterframe function that compares the player’s coordinates to those blocks. This kind of comparison would be easiest done if those blocks were in a table.

At its simplest, you know that the player is touching a block if the player’s coordinates are located within a block. However, since your player is not 1 pixel by 1 pixel in size, you need to take its dimensions into account as well.

If you create an enterframe function that loops through each block, all you’d need to do is check if the player’s x coordinates +/- half of its width are within a block’s coordinates +/- half of the block’s width, and same for the y values and the objects’ heights.

You can (and should) add checks to the enterframe function to reduce the number of necessary calculations. For instance, first check to see only if a player is within the x bounds of a block. If it isn’t, then the y bounds don’t matter, etc. Depending on how you implement this system, there are numerous other means of improving its performance.

you’ll need an overlap test.  here’s one:

--- pass me two rects and i'll return boolean true/false if they overlap function overlap(a,b) a, b = a.contentBounds, b.contentBounds return (a.xMin \<= b.xMax) and (a.xMax \>= b.xMin) and (a.yMin \<= b.yMax) and (a.yMax \>= b.yMin) end

but i’d also suggest you restructure some other things too.  you can consider it optional, but it’ll make your life easier going forward.

first, let’s give the player a “move” method.  insert this code after creating player:

player.move = function(self,dx,dy) self.x = self.x + dx self.y = self.y + dy -- self:collide() -- haven't written this yet, but this is where it'll go end &nbsp;

then for your arrow taps, reword them to each use that move method:

leftArrow:addEventListener("tap", function() player:move(-5,0) end) rightArrow:addEventListener("tap", function() player:move(5,0) end) upArrow:addEventListener("tap", function() player:move(0,-5) end) downArrow:addEventListener("tap", function() player:move(0,5) end) &nbsp;

then, create an array to hold all your blocks so it’ll be easier to loop through them:

local blocks = {} function addBlock(x,y,w,h) blocks[#blocks+1] = display.newRect(x,y,w,h) end addBlock(centerX, centerY - 50, 100, 220) -- etc, add all the other blocks similarly

… now, finally!, you’re set up to write the collide function for the player, fe:

player.collide = function(self) for \_,block in pairs(blocks) do if (overlap(self,block)) then block:setFillColor(1,0,0) -- do "something" in response to the collision, up to you end end end

then uncomment that call to collide inside move() and you should be good!

NOTE:  the code above is just to give you all the ideas, it’s still up to you to implement them properly.  fe, if you just copy/paste the code here as is, rather than thinking about it how it all should fit together, then you may have scope issues (for example the player methods might not know what the “blocks” array is if it’s defined later), so make sure you put things in a logical order. 

We have a tutorial for that: http://docs.coronalabs.com/tutorial/games/nonPhysicalCollision/index.html

Rob

Thank you all for your help, davebollinger’s answer worked for me.

I’m just wondering how isn’t there a function or something to check for collision in Corona, it seems like a such a simple thing, but I guess it’s not.

Corona has collision detection support, but it’s part of the physics engine. 

Rob

as Rob said, if you want full collision  (contact detection and dynamics response) then physics lib, easy

but if you just want overlap testing, then DIY.  still easy, no big deal – axis-aligned-rect-vs-rect overlap algorithm has been around since at least early 70’s “Pong” and hasn’t changed a bit since (SAT as proof that 4 tests suffice), so just grab the “one-liner” above and done. :slight_smile:

Collision detection for all simple convex and concave polygons is also easily doable without physics.

You could write an enterframe function that compares the player’s coordinates to those blocks. This kind of comparison would be easiest done if those blocks were in a table.

At its simplest, you know that the player is touching a block if the player’s coordinates are located within a block. However, since your player is not 1 pixel by 1 pixel in size, you need to take its dimensions into account as well.

If you create an enterframe function that loops through each block, all you’d need to do is check if the player’s x coordinates +/- half of its width are within a block’s coordinates +/- half of the block’s width, and same for the y values and the objects’ heights.

You can (and should) add checks to the enterframe function to reduce the number of necessary calculations. For instance, first check to see only if a player is within the x bounds of a block. If it isn’t, then the y bounds don’t matter, etc. Depending on how you implement this system, there are numerous other means of improving its performance.

you’ll need an overlap test.  here’s one:

--- pass me two rects and i'll return boolean true/false if they overlap function overlap(a,b) a, b = a.contentBounds, b.contentBounds return (a.xMin \<= b.xMax) and (a.xMax \>= b.xMin) and (a.yMin \<= b.yMax) and (a.yMax \>= b.yMin) end

but i’d also suggest you restructure some other things too.  you can consider it optional, but it’ll make your life easier going forward.

first, let’s give the player a “move” method.  insert this code after creating player:

player.move = function(self,dx,dy) self.x = self.x + dx self.y = self.y + dy -- self:collide() -- haven't written this yet, but this is where it'll go end &nbsp;

then for your arrow taps, reword them to each use that move method:

leftArrow:addEventListener("tap", function() player:move(-5,0) end) rightArrow:addEventListener("tap", function() player:move(5,0) end) upArrow:addEventListener("tap", function() player:move(0,-5) end) downArrow:addEventListener("tap", function() player:move(0,5) end) &nbsp;

then, create an array to hold all your blocks so it’ll be easier to loop through them:

local blocks = {} function addBlock(x,y,w,h) blocks[#blocks+1] = display.newRect(x,y,w,h) end addBlock(centerX, centerY - 50, 100, 220) -- etc, add all the other blocks similarly

… now, finally!, you’re set up to write the collide function for the player, fe:

player.collide = function(self) for \_,block in pairs(blocks) do if (overlap(self,block)) then block:setFillColor(1,0,0) -- do "something" in response to the collision, up to you end end end

then uncomment that call to collide inside move() and you should be good!

NOTE:  the code above is just to give you all the ideas, it’s still up to you to implement them properly.  fe, if you just copy/paste the code here as is, rather than thinking about it how it all should fit together, then you may have scope issues (for example the player methods might not know what the “blocks” array is if it’s defined later), so make sure you put things in a logical order. 

We have a tutorial for that: http://docs.coronalabs.com/tutorial/games/nonPhysicalCollision/index.html

Rob

Thank you all for your help, davebollinger’s answer worked for me.

I’m just wondering how isn’t there a function or something to check for collision in Corona, it seems like a such a simple thing, but I guess it’s not.

Corona has collision detection support, but it’s part of the physics engine. 

Rob

as Rob said, if you want full collision  (contact detection and dynamics response) then physics lib, easy

but if you just want overlap testing, then DIY.  still easy, no big deal – axis-aligned-rect-vs-rect overlap algorithm has been around since at least early 70’s “Pong” and hasn’t changed a bit since (SAT as proof that 4 tests suffice), so just grab the “one-liner” above and done. :slight_smile:

Collision detection for all simple convex and concave polygons is also easily doable without physics.