Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Simple Collision Detection — Gideros Forum

Simple Collision Detection

ruxpinruxpin Member
edited November 2011 in Game & application design
I was looking for a way to check if two sprites had collided without getting into Box2d stuff. I came up with this solution after a little bit of searching/trial and error. It checks if the sprites' rectangles are overlapping. Maybe something like this can be implemented in the engine to speed up the checks?

Put this code in your init.lua file so all Sprites can use it.
--Input (sprite2): another sprite to check for collision detection
--Return: return true if the rectangles overlap otherwise return false
function Sprite:collision(sprite2)
 
	-- self bottom < other sprite top
	if self:getY() + self:getHeight() < sprite2:getY() then
		return false
	end
	-- self top > other sprite bottom
	if self:getY() > sprite2:getY() + sprite2:getHeight() then
		return false
	end
	-- self left > other sprite right
	if self:getX() > sprite2:getX() + sprite2:getWidth() then
		return false
	end
	-- self right < other sprite left
	if self:getX() + self:getWidth() < sprite2:getX() then
		return false
	end
 
	return true
end
Tagged:

Comments

  • atilimatilim Maintainer
    Thank you for the contribution :)

    Right now this way is the best way. We'll consider embedding collision detection or geometry engine into Gideros API.

  • Please, could you give an example of its use? I'm starting

    Thank!
  • take care of the anchor point for a bitmap.
  • if (yoursprite1:collision(yoursprite2) = true) then
        -- a collision has happened, do something
    end
  • MellsMells Guru
    edited May 2012
    take care of the anchor point for a bitmap.

    Talking about the anchor point, do people usually work with it set at top left for Sprites and center for Bitmaps (mix)? Or do you prefer to work with all anchors set at the same point and would it be top left or center?
    (Even though it's not possible for Sprites right now but I believe @atilim said that support is coming soon.)
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
  • if (yoursprite1:collision(yoursprite2) = true) then
        -- a collision has happened, do something
    end
    Shouldn't it be "== true" ?

    Likes: evs

    +1 -1 (+1 / -0 )Share on Facebook
  • evsevs Member
    Actually you can simplify it to
     
    if yoursprite1:collision(yoursprite2) then
        -- a collision has happened, do something
    end
    cheers

    evs
  • Where do you get all the method details from?

    I asked on another thread about certain methods for TileMap which I couldn't find in the reference manual and was told because TileMap descends from Sprite it inherits the methods. Thats fine but I dont see a class diagram anywhere so not sure how I discover all these goodies!

    Cheers

    Gary
  • ar2rsawseenar2rsawseen Maintainer
    If you look at documentation:
    http://www.giderosmobile.com/documentation/reference_manual.html

    You can notice things like:
    Sprite > EventDispatcher meaning Sprite inherits all EventDispatcher methods
    TileMap > Sprite meaning TileMap inherits all Sprite methods and EventDispatcher methods

  • Put this code in your init.lua file so all Sprites can use it.
    --Input (sprite2): another sprite to check for collision detection
    --Return: return true if the rectangles overlap otherwise return false
    function Sprite:collision(sprite2)
     
    	-- self bottom < other sprite top
    	if self:getY() + self:getHeight() < sprite2:getY() then
    		return false
    	end
    	-- self top > other sprite bottom
    	if self:getY() > sprite2:getY() + sprite2:getHeight() then
    		return false
    	end
    	-- self left > other sprite right
    	if self:getX() > sprite2:getX() + sprite2:getWidth() then
    		return false
    	end
    	-- self right < other sprite left
    	if self:getX() + self:getWidth() < sprite2:getX() then
    		return false
    	end
     
    	return true
    end
    Well i've been using this method and it's working fine
    BUT since i'm using it on a lots of objects, it's slowing my game down.
    Is there any better way? Or API implementation is anywhere close on the roadmap?

  • ar2rsawseenar2rsawseen Maintainer
    Well, now let's see if any lua optimization really increases the performance or not.

    Will something like this work better?
    --Input (sprite2): another sprite to check for collision detection
    --Return: return true if the rectangles overlap otherwise return false
    function Sprite:collision(sprite2)
     	local myX = self:getX()
     	local myY = self:getY()
     	local myWidth = self:getWidth()
     	local myHeight = self:getHeight()
     	local otherX = sprite2:getX()
     	local otherY = sprite2:getY()
     	local otherWidth = sprite2:getWidth()
     	local otherHeight = sprite2:getHeight()
    	-- self bottom < other sprite top
    	if myY + myHeight < otherY then
    		return false
    	end
    	-- self top > other sprite bottom
    	if myY > otherY + otherHeight then
    		return false
    	end
    	-- self left > other sprite right
    	if myX > otherX + otherWidth then
    		return false
    	end
    	-- self right < other sprite left
    	if myX  + myWidth < otherX then
    		return false
    	end
     
    	return true
    end
    Maybe combining in one "OR" statement will also work faster?
  • oh i did the variable thingy. it didn't help.
    but i don't know how to implement any "OR"s ?
  • I think @ar2rsawseen meant something like this when he mentioned using OR statements
    --Input (sprite2): another sprite to check for collision detection
    --Return: return true if the rectangles overlap otherwise return false
    function Sprite:collision(sprite2)
     	local myX = self:getX()
     	local myY = self:getY()
     	local myWidth = self:getWidth()
     	local myHeight = self:getHeight()
     	local otherX = sprite2:getX()
     	local otherY = sprite2:getY()
     	local otherWidth = sprite2:getWidth()
     	local otherHeight = sprite2:getHeight()
    	-- self bottom < other sprite top or self top > other sprite bottom
    	if myY + myHeight < otherY or myY > otherY + otherHeight then
    		return false
    	end
    	-- self left > other sprite right or self right < other sprite left
    	if myX > otherX + otherWidth or myX  + myWidth < otherX then
    		return false
    	end
     
    	return true
    end
  • ar2rsawseenar2rsawseen Maintainer
    Yeah, but I guess that also won't do any good.
    Sprite:getBounds maybe?\
    I wonder what is the slowest statement in this function
  • Thanks for the code. I found (as alexzheng mentioned) that you have to be take the anchor point on the Bitmap into consideration. Then I found the post below that uses Sprite:getBounds(). Using this function returns the correct bounds relative to the stage, solving the anchor point problem.

    This function should be added back to the class reference documentation.

    http://www.giderosmobile.com/forum/discussion/1279/how-do-i-get-the-bounds-of-a-sprite
    --[[
    	Input (sprite2): another sprite to check for collision detection
    	Return: return true if the rectangles overlap otherwise return false
    ]]
    function Sprite:collidesWith(sprite2)
     
    	local x,y,w,h = self:getBounds(stage)
    	local x2,y2,w2,h2 = sprite2:getBounds(stage)
     
    	-- self bottom < other sprite top
    	if y + h < y2 then
    		return false
    	end
    	-- self top > other sprite bottom
    	if y > y2 + h2 then
    		return false
    	end
    	-- self left > other sprite right
    	if x > x2 + w2 then
    		return false
    	end
    	-- self right < other sprite left
    	if x + w < x2 then
    		return false
    	end
     
    	print('self bounds:',x,y,w,h,' sprite2 bounds:',x,y,w,h)
     
    	return true
    end
    Wuji Touch Software
    http://wujitouch.com
  • ""Sprite:getBounds maybe?""

    why there is no such thing in api?
  • Thanks for the code. I found (as alexzheng mentioned) that you have to be take the anchor point on the Bitmap into consideration. Then I found the post below that uses Sprite:getBounds(). Using this function returns the correct bounds relative to the stage, solving the anchor point problem.

    This function should be added back to the class reference documentation.
    --[[
    	Input (sprite2): another sprite to check for collision detection
    	Return: return true if the rectangles overlap otherwise return false
    --]]
    function Sprite:collidesWith(sprite2)
     
    	local x,y,w,h = self:getBounds(stage)
    	local x2,y2,w2,h2 = sprite2:getBounds(stage)
     
    	-- self bottom < other sprite top
    	if y + h < y2 then
    		return false
    	end
    	-- self top > other sprite bottom
    	if y > y2 + h2 then
    		return false
    	end
    	-- self left > other sprite right
    	if x > x2 + w2 then
    		return false
    	end
    	-- self right < other sprite left
    	if x + w < x2 then
    		return false
    	end
     
    	print('self bounds:',x,y,w,h,' sprite2 bounds:',x,y,w,h)
     
    	return true
    end
    wow, that works clearly faster than the previous.
    everyone should use this code over the old one :)
    and ofc this should be added to documentation.
  • GregBUGGregBUG Guru
    edited July 2012
    ... and you can speed-up things even more (about 7%-10% faster) with this implementation (not mine; only converted):
    function Sprite:collidesWith(sprite2)
    	local x,y,w,h = self:getBounds(stage)
    	local x2,y2,w2,h2 = sprite2:getBounds(stage)
     
    	return not ((y+h < y2) or (y > y2+h2) or (x > x2+w2) or (x+w < x2))
    end
    :D

    Likes: sunnyguy, bali001

    TNT ENGiNE for Gideors Studio - Particle Engine, Virtual Pad, Animator Studio, Collision Engine - DOWNLOAD NOW !!! IT'S FREE!!! -
    www.tntengine.com
    +1 -1 (+2 / -0 )Share on Facebook
  • ar2rsawseenar2rsawseen Maintainer
    @GregBUG this should go straight into FAQ

    Likes: sunnyguy

    +1 -1 (+1 / -0 )Share on Facebook
  • Thanks GregBUG for posting the code.

    One question though - if I wanted to shrink the hitbox so that there was a padding of say 5 pixels around the outside, how would I do that?

    Thanks
  • GregBUGGregBUG Guru
    edited September 2012
    @Tom2012

    try this...

    taken from my upcoming collision lib (this is original prototype lua code... it's quite fast)

    my next lib will be C++ native and for this example/collision check is about 30% faster...

    anyway...
    local cHandle = { x = 0, y = 0 }
     
    -- set Anchor Point
    function setCollisionAnchorPoint(x, y)
        cHandle.x = x
        cHandle.y = y
    end
     
    -- get Anchor Point
    function getCollisionAnchorPoint()
        return cHandle.x, cHandle.y
    end
     
    function boxToBox(spriteAX, spriteAY, widthA, heightA, spriteBX, spriteBY, widthB, heightB)
        -- Check for vertical GAP
        local Ay1, By1 =  spriteAY - (heightA * cHandle.y ), spriteBY - (heightB * cHandle.y ) 
        if Ay1 + heightA < By1 then
            return false
        end
        if Ay1 > By1 + heightB then
            return false
        end
     
      -- Check for horizontal GAP
        local Ax1, Bx1  = spriteAX - (widthA * cHandle.x ), spriteBX - (widthB * cHandle.x ) 
        if Ax1 > Bx1 + widthB then
            return false
        end
        if Ax1 + widthA < Bx1 then
            return false
        end
        -- Boxes Collide...
        return true
    end

    you can set width and height and also set collision handle so...


    let me know...
    TNT ENGiNE for Gideors Studio - Particle Engine, Virtual Pad, Animator Studio, Collision Engine - DOWNLOAD NOW !!! IT'S FREE!!! -
    www.tntengine.com
  • The Bitmaps do not have a getBounds method, do they?
    twitter: @ozapps | http://www.oz-apps.com | http://howto.oz-apps.com | http://reviewme.oz-apps.com
    Author of Learn Lua for iOS Game Development from Apress ( http://www.apress.com/9781430246626 )
    Cool Vizify Profile at https://www.vizify.com/oz-apps
  • @OZApps Bitmap is extended from Sprite, and Sprite has getBounds method, so yeah, Bitmap also has it ;)
  • i have not used getBounds because in c plugin version i must to call
    form c code a "Gideros lua" function (getBounds) and get back result to c code
    ....but is it's very slow...

    but yes in this lua version you can use getBounds...

    TNT ENGiNE for Gideors Studio - Particle Engine, Virtual Pad, Animator Studio, Collision Engine - DOWNLOAD NOW !!! IT'S FREE!!! -
    www.tntengine.com
  • Hey GregBUG - nice script. Do you have an example on how to use the function?

    Thanks

    Tom
  • Is there a way to do this for odd shapes? Like a Star. or TRiangle?
    REAL programmers type copy con filename.exe
    ---------------------------------------
  • Is there a way to do this for odd shapes? Like a Star. or TRiangle?
    i don't think so unless you go with the physics

Sign In or Register to comment.