objects phasing in and out

Mar 17, 2010 at 9:27 PM

In a game I am working on, there are doors that toggle between being passable and not.

The way I handle this is via the ContactFilter. It returns false to collide when checking for my player and the door if the door is open, true otherwise.


However, if the player is pressed against the door when it opens, the ContactFilter is not queried, and the player cannot pass through. I have to back up and lose contact in order for it to ask the ContactFilter again. This makes sense, since I get a notification for the beginning of a collision and the end. Internally, I can pass a message around saying that the door is now open, but I don't see how to allow the player to pass through without breaking contact first.


Is there a way to tell Box2D to allow this?


- John

Mar 17, 2010 at 10:24 PM

I haven't tried this, but I think you just need to call FlagForFiltering() on any persisted contact points.  Since you get begin/end notification you should be able to keep a list of the "active" contacts, and when a special condition that whould change contact filtering occurs (like the door "opening") you should run through this list and call Contact::FlagForFiltering().

Mar 18, 2010 at 2:45 AM

Excellent, yes that fixed the problem.

Thank you for the prompt and useful reply!

- John

Mar 18, 2010 at 3:01 AM

Actually...this *almost* fixes it.

If the player is very near, but not touching the door, and the door opens, then the contact has been detected inside Box2D but not reported to the client, since there is no actual overlap. As a result, I have no reference to the Contact information to call FlagForFiltering() on. The player has to back up and re-approach, or be leaning against the door from the beginning.

Any way around this one? A way to get a list of all the Contacts associated with a particular fixture? I don't see anything obvious in the API...

- John

Mar 18, 2010 at 3:18 AM

Makes sense, I forgot about the contact list (which might include non-touching contacts).

You should be able to instead call FlagForFiltering() on every single contact by getting the contact list from the world.

/// Get the world contact list. With the returned contact, use Contact.GetNext to get
	    /// the next contact in the world list. A null contact indicates the end of the list.
	    /// @return the head of the world contact list.
        public Contact GetContactList()
            return _contactManager._contactList;


Mar 18, 2010 at 3:31 AM

Excellent, once again.