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 it
Caveats
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