Page 1 of 1

Understanding callbacks

Posted: Wed Feb 17, 2010 12:29 am
by Skah T
I have a simple app with balls falling down the screen and landing in buckets. The buckets are simply rectangular areas with three static shapes for the two sides and bottom. I also have a sensor shape (rectangle) that fills the inside of the bucket.

I attached callback functions to handle collisions between balls and the sensor. The balls start out purple. The Begin callback causes them to turn yellow (ball enters bucket) and the Separate callback turns them back to purple (ball bounces out of bucket). I would expect all balls in the bucket to be yellow at the end. This is mostly true, but I will occasionally get one or two balls that end up purple inside the bucket.

To find out what's going on, in the Separate event I changed the collision_type of the ball to some other value. That way I can track what happens to it next. I would expect that the next callback to get invoked for that particular ball to be a Begin event, yet I am seeing the PreSolve event is actually called, meaning the ball is actually still inside the bucket. This is likely why the ball is staying purple.

I'm somewhat new to Chipmunk so this might just be me not understanding how things work. I suspect what is happening is the solver is predicting that the ball and bucket will separate, and thus call the Separate callback, while instead other collisions cause the ball to actually remain in the bucket.

I hope I've explained all that sufficiently. Since I mostly understand what is happening (if not why) I think I can work around it, but it would still be nice to know whether or not this is expected behavior.

Re: Understanding callbacks

Posted: Wed Feb 17, 2010 1:46 am
by Skah T
Forgot to mention I am using the version of Chipmunk that comes with Cocos2d (0.99-rc).

Also, I added a call to cpArbiterIsFirstContact() from within my preSolve callback. After the Separate event and the preSolve is called that function returns 1. So even though the Begin event didn't trigger it seems to still recognize that the collision just started (again).

Re: Understanding callbacks

Posted: Wed Feb 17, 2010 10:35 am
by slembcke
The collision handler is assigned to a collision pair (cpArbiter) when the collision is first found. If you change the collision type after the begin() callback is called, it won't change anything. There isn't really a way to reset an arbiter. Do you think there should be?

I'll make sure this is documented under the collision handlers stuff.

Re: Understanding callbacks

Posted: Wed Feb 17, 2010 5:23 pm
by Skah T
Perhaps my mention of playing with the collision type distracted from my main question.

Is it possible for an arbiter to remain alive after the Separate callback is invoked?

Re: Understanding callbacks

Posted: Wed Feb 17, 2010 5:39 pm
by slembcke
It shouldn't be. The arbiter struct itself might to save the collision solution for a few frames, but it gets marked as old.

Re: Understanding callbacks

Posted: Wed Feb 17, 2010 6:10 pm
by Skah T
I just found my problem. I had two buckets next to each other. The ball was hitting the wall that separates them. In the process it was coming in contact with the sensor shapes of both buckets. That caused it to turn yellow. Once the ball fell one way or the other it separated from one of the sensors, turning it back to purple as it fell in the other bucket.

I lowered the height of my sensor shape so that it is slightly below the edge of the bucket instead of flush with it. Now things work as expected.

So, user error. And the user is now (slightly) more educated :)

Re: Understanding callbacks

Posted: Wed Feb 17, 2010 6:40 pm
by slembcke
Ah. Actually I've had similar problems when doing things like determining contact. The simple solution is to keep a count instead of a plain boolean. Increment on a begin() and decrement on a separate(). If the count is 0, then it is touching no objects. Works like a charm. \o/