Collision Filters "Helper Chart"

Hello all,

I'm posting the following explanation about Collision Filters as a help to the community in general, as a result of my own experiments. Some users, especially recent converts, have not yet used collision filters but it's an essential aspect to almost any game design. I created the attached "Collision Helper Chart" which I use for my own game designs... hopefully it can assist others too! The blank document can be downloaded from my website (link at the end of this post).

-----

So, what are Collision Filters? Simply put, they're a method to determine what objects combine with other objects, or perhaps more importantly, what objects do not collide with others in a game. The official documentation explains Corona's method of accomplishing this, which varies from other SDKs, but I created a chart to assist in the issue.

Here's a chart and list of steps following the classic "Asteroids" game example...

STEPS:

  1. Observe the "bits" (numbers) in the very top row. 1 to 512, in binary numbers. You can go as high as "32768" (16 places) but I stopped the chart at 512 which should be enough for most people. These "bits" are how Corona determines collision filters.
  2. Observe the first row. It has two sub-rows: "catg." and "cl.w/". These mean "category" and "collides with" respectively.
  3. For each object type in your game (i.e. "asteroid", pick one bit number. Place a circled X in that column. This bit number should be unique and not repeated for other objects under most circumstances! (There are probably advanced situations where you might duplicate category bits or even assign more than one to an object, but don't worry about it now)
  4. Next, ask yourself: "can this object collide with others of its type?" If yes, then place an X directly below in the "collides with" row. In the example, notice that asteroids can collide with other asteroids.
  5. Move down the rows of other objects in your game. For every object that "asteroids" can collide with, place an X in the "collides with" row for that object. Asteroids can collide with player_ship and alien_ship, so both of those get an X in their respective row/column. If it's not obvious already, keep the columns ordered: Asteroids have bit "2" as their category, so stay within that column for anything asteroids should collide with (I colored the chart entries to make it clearer).
  6. Move to the next game object and repeat. IMPORTANT! You must work back UP the chart, not just down! If two objects are intended to collide, both must be marked properly or the collision will not function! So, take the item pair of asteroid and player_ship, which should always collide: "asteroid: category" is marked in "player_ship: collide with" AND "player_ship: category" is marked in "asteroid: collide with". If you fail to mark both corresponding factors, the collision will not happen!
  7. When you've done all of your objects, simply add the bits across every row to determine sums.
  8. For each collision filter, you need these sums as follows, near the top of your main.lua file.

1
2
3
local asteroidCollisionFilter = { categoryBits = 2, maskBits = 7 }
local playerCollisionFilter = { categoryBits = 1, maskBits = 6 }
local alienCollisionFilter = { categoryBits = 4, maskBits = 7 }

Hi that was a very helpful document, thanks for posting it. I am sure a lot of new developers will appreciate it.

This has always confused me like no other, and this chart you created (as well as the explanation of how to use it) is nothing short of AMAZING.

Thanks Brent, I'm definitely going to link to this from my blog once I test it out in my current project.

UPDATE: I posted a link from my blog. I know I ran into this late, but thanks again Brent, it worked for me the first time around :-)

Jonathan Beebe
http://jonbeebe.tumblr.com/
http://beebegamesonline.appspot.com/

Thanks Jon!

Nice to hear that it worked perfectly the first time around. I hope others will link to it from your blog. I think Ansca's implementation of collision filters is incredible (much better than Torque2D's filters in my humble opinion), but Ansca hasn't really documented or explained it very well... so ideally, others can follow my chart method and use it for their games.

Brent

I been out of the forums for a few days due to my travels and I just came across this.

Wow. Fantastic.

Thanks @ignisdesign for documenting it !

We should get our **s together and make our docs much better. I know we lack in that dept.

Thanks again !

Carlos

As a start, I added a link to this post in the collision filter docs here: http://developer.anscamobile.com/content/game-edition-collision-detection#Collision_categories_masking_and_groups

Thanks, @IgnisDesign!

Nice work. I usually make a right mess of my collision filter, so thanks.

This has been very helpful, thank you very much!

Is there any way to temporarily suspend all collisions for a physical object without destroying and recreating it as nonphysical? I was trying to suppress collision detection on an object being dragged, but when not being dragged would collide as normal. Changing the collision filter before and after the drag doesn't seem to work.

@hoplite: Try this...

For disabling physics on a specific object:

myObject.isBodyActive = false

Obviously, change myObject to the object you want to stop registering collisions, etc.

Alternatively, you can use:

myObject.isSensor = true

The above will still register collisions, but will not "bounce" off of anything (things will pass through it, but you can still handle collision events).

Hope that helps! I use both of the above A LOT so I can't imagine what it would be like not knowing about them.

Worked like a charm, @jonbeebe! Much appreciated.

Hi,

Is it possible to alter the collision mask at runtime?

Based on the object's game state, i'd like it to collide with different categories.

Paul

edit:
Found the answer
http://developer.anscamobile.com/forum/2010/11/08/changing-collision-filters-after-physics-object-created

So I may have too much time on my hands but I loved this detailed explanation of filters so much I turned the pdf file into a full Google spreadsheet

Heres the link:
https://spreadsheets.google.com/ccc?key=0AgbP7GCzild1dDVVdy1HTlViY1RHeFNnYWM5eHpWRVE&hl=en&authkey=CKeQqN4F

You can't edit this copy, but if you're signed into your Google account you can click File > Make a Copy

There is an example sheet along with a template sheet. I hope someone else can enjoy this spreadsheet.

@IgnisDesign Thanks for the post

CSteh this is awesome! Thanks for enhancing the chart, especially with higher bit numbers than I provided on the PDF (useful for those people designing intensive games with tons of collision rules).

I'm glad this document is helpful for so many game developers. :)

Brent Sorrentino
Ignis Design

Just incredibly useful. Thanks Ignis for chart and explanation, and thanks CSteh for the handy google doc.

Hey great post, found it damn simple and easy to use the collision filters. Had just one query and that is is it possible to animate these objects as well.
I tried doing so but either,
1) the collision filter works in which case the objects do not get animated or
2) the frame animation code works in which case the objects pass through each other without collision

I need the object to collide (using collision filters) and at the same time keep moving(using frame animation) until an object is tapped on, in which case that object becomes stationary.

Firstly is this possible.

If yes how can I do it. I am new to corona so would really appreciate the help.

Please help me. I have my jury in a few days and I really need this game to work.

Good to hear that the Collision Chart helped!

About your issue: it's definitely possible. :) I have animated objects (using sprite sheets) moving about my game and using collision filters too.

I don't think it makes a difference, but in my game (for the main character) I configured the animation parameters first, then I declared the physics body and collision filter after this.

Can you post some sample code so others can see what might be happening?

Brent Sorrentino
Ignis Design

Yes, surely

Hey Guys I am making a game using corona sdk and so needed help with the lus code. In this program there are bubbles floating across the screen and colliding with each either as well as with the walls of the screen.

I am using 'Collision Filter' for the collisions and the masking operation and it is working well. But in this game I want a bubble to continuously move unless and until it is tapped upon. I thought of using the frame animation to animate each bubble and then add a separate function that will make it stationary when tapped.

But the problem is that at a time only 1 program seems to wrok fine. So,
1) either the bubbles collide, fall down, bounce against wall and eventually rest down.
2) The bubbles continuously keep moving across the screen, without colliding against each other, and instead pass through the other bubbles

What should I do to animate and inanimate(on tapping that bubble) a colliding bubble.

My code is below,

borderCollisionFilter = { categoryBits = 1, maskBits = 2 } -- collides with (4 & 2) only
local borderBodyElement = { bounce=1.0, filter=borderCollisionFilter }

local borderTop = display.newRect( 0, 0, 480, 1 )
borderTop:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderTop, "static", borderBodyElement )

local borderBottom = display.newRect( 0, 318, 480, 1 )
borderBottom:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderBottom, "static", borderBodyElement )

local borderLeft = display.newRect( 0, 0, 1, 320 )
borderLeft:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderLeft, "static", borderBodyElement )

local borderRight = display.newRect( 480, 1, 1, 320 )
borderRight:setFillColor( 0, 0, 0, 0) -- make invisible
physics.addBody( borderRight, "static", borderBodyElement )

--BUBBLES

--local r1=30
--local r2=30

--local xdir1 = math.random(-3,5)
--local ydir1= math.random(-1,3)

--local xs1 = 2
--local ys1 = 3.5

--local x1 = 50
--local y1 = 350

local bubbleCollisionFilter = { categoryBits = 2, maskBits = 7 }
local bubble = {bounce=0.94, radius=18,filter = bubbleCollisionFilter }

--BUBBLE ANIMATE

--bubble.x = x1
--bubble.y = y1

--local sT = display.screenOriginY
--local sB = display.viewableContentHeight + display.screenOriginY
--local sL = display.screenOriginX
--local sR = display.viewableContentWidth + display.screenOriginX

--local function an1(event)

--x1 = x1 + ( xs1 * xdir1 );
--y1 = y1 + ( ys1 * ydir1 );

--if ( x1 > sR - r1 or x1 < sL + r1 ) then
-- xdir1 = xdir1 * -1;
--end

--if ( y1 > sB - r1 or y1 < sT + r1) then
--ydir1 = ydir1 * -1;
--end

--bubble:translate( x1 - bubble.x, y1 - bubble.y)

--bubble.angularVelocity = 100
--bubble:applyForce( 185, 0, bubble10.x, bubble10.y )

--end

--Runtime:addEventListener( "enterFrame", an1 );

--
--BUBBLES CREAES USING BUBBLE CONSTRUCT
--

local bubble1 = display.newImage( "bubble.png", 50, 50 )
physics.addBody( bubble1, bubble )

local bubble2 = display.newImage( "bubble.png", 100, 230 )
physics.addBody( bubble2, bubble )

local bubble3 = display.newImage( "bubble.png", 180, 200 )
physics.addBody( bubble3, bubble )

local bubble4 = display.newImage( "bubble.png", 90, 30 )
physics.addBody( bubble4, bubble )

--MINIONS

minionCollisionFilter = { categoryBits = 4, maskBits = 2 }
minionBodyElement = { bounce=0.8, filter=minionCollisionFilter }

local c1 = display.newImage("str-minion-small.png")
c1.isVisible=false
physics.addBody( c1, "static", minionBodyElement )

local c2 = display.newImage("str-minion-mid.png")
c2.isVisible=false
physics.addBody( c2, "static", minionBodyElement )

local c3 = display.newImage("str-minion-big.png")
c3.isVisible=false
physics.addBody( c3, "static", minionBodyElement )

--SPAWNING

local function spawnDisk( event )
local phase = event.phase
local volumeBar = display.newLine( 0, 0, 1, 0 )
volumeBar.y = 400
volumeBar.x = 20
local v = 20*math.log(r:getTunerVolume())
local MINTHRESH = 30
local LEFTMARGIN = 20
local v2 = MINTHRESH + math.max (v, -MINTHRESH)

v2 = (display.contentWidth - 1 * LEFTMARGIN ) * v2 / MINTHRESH
volumeBar.xScale = math.max ( 20, v2 )

local l = volumeBar.xScale
local cnt1 = 0
local cnt2 = 0
local cnt3 = 0
local ONE =1
local val = event.numTaps

if "ended" == phase then
if l > 50 and l <=150 then
c1.x=math.random( 10, 450 )
c1.y=math.random( 10, 300 )
physics.addBody( c1, { density=1, radius=10.0 } )
c1.isVisible=true
cnt1= cnt1+ ONE
return c1

elseif l > 100 and l <=250 then
c2.x=math.random( 10, 450 )
c2.y=math.random( 10, 300 )
physics.addBody( c2, { density=2, radius=30.0 } )
c2.isVisible=true
cnt2= cnt2+ ONE
return c2

elseif l >=250 then
c3.x=math.random( 40, 450 )
c3.y=math.random( 40, 300 )
physics.addBody( c3, { density=2, radius=50.0 , bounce=0.0 } )
c3.isVisible=true
cnt3= cnt3+ ONE
return c3
end
end
end

buzzR:addEventListener( "touch", spawnDisk ) -- touch the Button to create minions

--END

In this code the bubbles need to collide with,
1) the walls (c=1)
2) each other (c=2)
3) minions (c=4)

Also these bubbles need to move continuously(at a slow pace) across the screen without coming to a rest, until that bubble is tapped.

In the above code the filters works perfectly the animation does not. I have commented those codes. Tried using the frame animation function for the bubble construct.

Also need a way by which when I tap a bubble that bubble becomes stationary.

Really appreciate the help.

Thanks Brent :).

This helps clarify what's going on, somewhat. :)

Without dissecting your actual code, I just have a few suggestions on how you might tackle some of the tasks mentioned...

1) For the bubbles, I would suggest you use Sprite Sheets for their animation (they are animating in some way, correct?). I assume all of the bubbles will use the same basic animation, so you can create one sprite sheet in the beginning and every bubble can reference it. If you have multiple bubble types (different colors, for example), you just configure different sprite definitions within that sprite sheet. Sprite sheets might seem complicated at first but they're very memory-efficient and Corona documents their usage nicely.

2) Each bubble is a physical object, of course. For each one, I would store/link its velocity and direction directly to the bubble, as in "thisBubble.xVel = 10" (xVel could be whatever name you want: xVeloc, xVelocity, xV, basically anything that doesn't conflict with another variable name or Corona API name).

The reason for storing these values is to stop/resume the bubbles on tap. When the bubble is tapped, you just set the velocities to 0. Then on "resume" you read those stored values and send the bubble moving on the same path/speed it was on before.

By using sprite sheets (above) you can simply pause the animation to make the bubble look "stopped" and then resume its animation when needed.

Does this help somewhat? As with most programming SDKs, there are usually multiple ways to accomplish a certain task. This is how I would program your scenario, personally. :)

Brent

Hi,

im having trouble with using the [displayGroup] funtion. i tired using it in my game but i can't output onscreen the image.

1
2
local asteroid = display.newImageRect( [displayGroup], "asteroid.png", 32, 32 )
physics.addBody( asteroid, { density=2.9, friction=0.5, bounce=0.3, radius=16, filter=asteroidCollisionFilter } )

Scroll down about halfway and look for the "Groups" heading:

http://developer.anscamobile.com/content/display-objects

Display groups are 100% essential to development. They act as "layers" to correctly position images behind or in front of other images. They also act as ways to group and manage a whole series of images and perform an action on the entire set with one command, like move 15 related items across the screen.

Any place you see "[displayGroup]" in the API reference, it's talking about the group to insert this object into (a group you've defined already). Otherwise it will be put onto the "stage" which is a master display group in itself, but you'll need more control than just this one stage layer.

If you're just starting with Corona, follow through some of the basic tutorials thoroughly. It takes some time and it's a little tedious at points, but it's worth every second.

Hi Brent,
firstly thanks for the help so far. But the problem is that I am still kind of stuck.

The reason for this is that I am not sure if configuring a sprite sheet uniquely for each bubble would give me the effect I need.

You must have seen the fishies example,
http://developer.anscamobile.com/sample-code/fishies

I need the bubbles to move across the screen exactly in the way the fishes do. And on clicking a bubble it gets stationary and it change color similar to that in the fishies example.

In fact I initially thought of using that code and modifying it but, the issue is that physics does not work on group objects(it appears as though on a separate layer). So the bubbles do not collide with each other or with the minions ( spwaning objects)

I've seen the Fishies example. The "problem" with this example, in my opinion, is that it uses constant Runtime tracking of every fish's X and Y position, and then when a fish reaches the edge of the screen, it does something to that fish (changes its direction). This is not necessarily bad coding, but if you're using physics bodies on your bubbles already, it's better to take advantage of the physics system and all its powers. :)

Stopping and re-starting the bubbles could be done as I outlined in my post above (store X and Y velocity, set them to 0,0 on first tap, resume to stored value on next tap).

The bubbles can still be sprites, based on just ONE sprite sheet, not multiple sheets. You define the sheet once at the start and all bubbles can access it. This is the beauty of sprite sheets. You could even have 3 colors of bubbles in 3 frames within the sheet. Frame 1 is "normal" (aqua?), frame 2 is "green", frame 3 is "red", or whatever. On clicking a bubble, you just declare its frame and it appears as the color bubble you need.

You could even make animating bubbles in this fashion. Let's say the bubble has 3 frames of animation. Your sprite sheet could be set up like this (in numbered frame order):

AQUA1, AQUA2, AQUA3, GREEN1, GREEN2, GREEN3, RED1, RED2, RED3

"Normal" animation would be cycling constantly between frames 1 and 3. You define this as an individual sprite (sprite.add) within the sprite sheet/set. "Green" animation would cycle between frames 4-6, "Red" between 7-9. This is all very simple to set up and change during runtime, and you can control speed and looping too (cycle, back-and-forth, number of loops, etc.)

Hmm ok, well will definitely try the approach you have suggested :) .

But since am new to corona I am not very clear with the syntax. Nonetheless I want to try and will post with the same. If I have some issue will let you know. And you could tell me what in my code is not working. Would really appreciate all the help since I have none as of now.

Anyways take care and thanks a lot Brent :).

Hey hi brent, tried working on your suggestion but frankly due to my lack of coding experience I was unable to do it. I don't know where to start or what syntax to follow. I tried searching for reference with regards to collision on sprites and how to configure sprites for each bubble, here again am lost. Tried going through the horse animation code. But unlike in that I need the bubbles to move across the screen I don't know(syntax) how to achieve that using the sprites logic. And my biggest challenge is how to link the sprites and collision filters :( . I hope I am not asking for a lot. I really want to learn corona, but right now just blank and am unable to write code that will work. My jury is in this week, scared I will get an F. Could I mail you with regards to my queries? Sorry for all the trouble :(.

It's tricky to learn this stuff, and sprite sheets are a more advanced topic. Since I (and most of us here) promote and truly enjoy Corona, we'd like you to stick around and keep using it. :) I'm too busy on my own projects to actually "write code" for you, but e-mail me and I can send you some snippets of code from my own projects which should help, specifically using sprite sheets.

E-mail: bjsorrentino@yahoo.com

IS there anyway possible where we can add the collision filter later in a function ??

Just a small hint -if you don't want to hardcode your collision flags in several places throughout your code and to avoid the hassle of calculating the sum of all those bits manually, you can use kind of "constants", like below. It's very clear and also allows to change the object categories and collision behaviour simply by editing those few lines at any time:

On top of your main.lua

1
2
3
4
5
6
7
8
9
10
11
-- DEFINE CATEGORIES (USE 1,2,4,8,16...)
TYPE_SHIP     = 1
TYPE_COMET    = 2
TYPE_UFO      = 4
TYPE_SHOT     = 8
 
-- WHO CAN COLLIDE WITH WHOM?
collisionFilter_Ship  = { categoryBits = TYPE_SHIP , maskBits = TYPE_COMET + TYPE_UFO }
collisionFilter_Comet = { categoryBits = TYPE_COMET, maskBits = TYPE_SHIP  + TYPE_SHOT + TYPE_COMET }
collisionFilter_UFO   = { categoryBits = TYPE_UFO  , maskBits = TYPE_SHIP  + TYPE_SHOT }
collisionFilter_Shot  = { categoryBits = TYPE_SHOT , maskBits = TYPE_COMET + TYPE_UFO  }

Here is my take on managing collision filter..

Download link : http://db.tt/UAV3Lm2

@chinmay.patil

awesome! thanks for sharing

Great Tutorial! Thank you so much!

Just wanted to add, that if you DON'T supply a collision filter, the object acts as if it has a category bit of 1, and collides with EVERYTHING ELSE. Or in other words, it acts as if it has filter = { categoryBits = 1, maskBits = 65535 }.

Hi all,

firstly thanks for this post, it is very helpful. Although i don't have a personal need for the filtering yet (my objects crash into everything) i am interested in the fact that isSensor should still register collisions.

Basically my issue is that i have an object that performs a function when collided with and it's working 100%, then i wanted this object to be moveable but if a user moves it over another object i don't want any action to occur. I accomplished this by using isSensor while the object is being dragged.

But that means that while it the object is a sensor there's no collision detection happening, and i need it to happen to stop the user from placing the object on top of another object (when he releases the object i don't want to allow him to put it directly on top of another object).

I hope that made sense, basically while the object is being dragged i make it a sensor, then when the phase ends i change it back, but i need a way to stop it from being placed on other objects.

Thanks for all the help!

Hi marioanam,

If I understand correctly: you have something like a stack of "bricks" which the user can move around. During the "drag" stage, the user can move a brick anywhere, and it won't collide with anything. But upon the "drop" (end phase) you want to ensure that the brick is not directly on top of another brick...

"But that means that while it the object is a sensor there's no collision detection happening"

Sensors still register hits. If your isSensor object isn't registering hits, then you might have configured your physics setup improperly. The TYPE of the object is VERY important in regards to this... "solid" objects react differently to "kinematic" objects, and it's even more fussy when you're dealing with sensors. I would suggest you experiment with each type to achieve the proper collisions.

For example, in my game, I think a "solid sensor" only reacts with another solid sensor, not a "kinematic sensor". It's weird and unfortunately I haven't determined how/what reacts with what in the sensor state, or why. Best of luck!

views:1723 update:2011/10/19 14:58:09
corona forums © 2003-2011