Quick Links: Gideros Home | Download Gideros | Developer Guide
Simple Collision Detection - Gideros Forum
Simple Collision Detection
  • 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
  • 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
  • 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 : Want to participate to the Beta? -> Art, Samurai and a story
  • chipster123chipster123 +1 -1 (+1 / -0 )
    MikeHart said:


    if (yoursprite1:collision(yoursprite2) = true) then
    -- a collision has happened, do something
    end


    Shouldn't it be "== true" ?

    Loves: evs

  • Actually you can simplify it to
     
    if yoursprite1:collision(yoursprite2) then
    -- a collision has happened, do something
    end


    cheers

    evs
  • I prefer "collideWith" to "collision" :p
    Fun games for the whole family http://www.guava7.com
  • 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
  • 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
  • Thanks ar2!
  • ruxpin said:


    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?

  • 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
  • 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 +1 -1 (+1 / -0 )
    ... 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

    Loves: sunnyguy

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

    Loves: sunnyguy

  • 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
  • @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 )
  • @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

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Login with Facebook Sign In with Google Sign In with OpenID

In this Discussion

Top Posters