The old way!
If you're using the Chipmunk bindings, the correct way to handle collisions between shapes is to register 4 (FOUR!) handlers for the different steps: begin, preSolve, postSolve and separate. Your collision handling logic is then spread in 4 different functions. All of that for the same collision.bool Begin (Arbiter arb)
{
Console.WriteLine ("began");
return true;
}
bool PreSolve (Arbiter arb)
{
Console.WriteLine ("presolved");
return true;
}
void PostSolve (Arbiter arb)
{
Console.WriteLine ("postsolved");
}
void Separate (Arbiter arb)
{
Console.WriteLine ("separated");
}
It would be great, for the sake of simplicity, if we could group the logic altogether.
await to the rescue
C# 5 (in .NET 4.5) allows just that. Procedural code in the form of:await began;
Console.WriteLine ("BEGAN");
await presolved;
Console.WriteLine ("PRESOLVE");
await postsolved;
Console.WriteLine ("POSTSOLVE");
await separated;
Console.WriteLine ("SEPARATED");
All this, ran into an infinite loop:
async void WaitForCollisions ()
{
using (var waiter = new AsyncCollisionWaiter (space, WALL, CHARACTER)) {
for(;;) {
var began = waiter.GetBeginAsync ();
var presolved = waiter.GetPreSolveAsync ();
var postsolved = waiter.GetPostSolveAsync ();
var separated = waiter.GetSeparateAsync ();
await began;
Console.WriteLine ("BEGAN");
await presolved;
Console.WriteLine ("PRESOLVE");
await postsolved;
Console.WriteLine ("POSTSOLVE");
await separated;
Console.WriteLine ("SEPARATED");
}
}
}
The magic lies in the AsyncCollisionWaiter. Here's a quick implementation for itCaveats
There's a 5-10 ms delay between the moment the result for the Task is set and the moment the awaiting function is resumed. That means nothing in most cases, but means A LOT when you're simulating physics. That means the separated event happens before the process resumes after the await began. That's why we have to Get*Async() all the events we're interested into before waiting for the first one.
Due to that delay as well, we loose the ability to decide in a timely manner if we want this collision to happen or not. That's why I unconditionally return true from Begin and PreSolve in the AsyncCollisionWaiter.
So what ?
Frank got me excited with his series of post. I wanted to apply the same process to my own stuffs. Although the code looks nicer, you're paying a high price for that beauty, and all the value of having 4 events is kinda ruined by the delay. In this case, a single collisionHappened would have been enough.
Have fun experimenting with await in your own mobile application too.
Have fun experimenting with await in your own mobile application too.

No comments:
Post a Comment