2D Collision Response - Multiple Dispatch

Started by
12 comments, last by NotAYakk 17 years, 7 months ago
NotAYakk: I like that (effectively a double-keyed matrix of function pointers). That's a very neat solution to the double-virtual problem.
Advertisement
Very interesting solution NotAYakk. This is very similar to Andrei Alexandrescu's "constant-time" multiple dispatch solution in that you can get constant-time execution by inserting function pointers into a map and looking it up based on an ID (or essence, in your case).

I agree that your solution is a lot more flexible and powerful. I'm a bit weary of injecting my classes with different essences. Mostly because I'm worried about managing these different classes and the code to do so overcomplicating or overshadowing my initial problem. But it's certainly something I'll keep in mind if I need this multiple-dispatch problem anywhere else other than collision (since the system would facilitate that nicely).

It was these kinds of responses I was looking for, and I greatly appreciate the thoroughness and effort put into your solution.
I havn't taken the time to read all the posts, but double dispatch is pretty easy. You just call a virtual function on one of the objects, which calls an overloaded virtual function on the other, passing itself as a parameter. Like this:
class Box;class Sphere;class Collider{   virtual bool CheckCollision(Collider* other) = 0;   virtual bool Collide(Box* other) = 0;   virtual bool Collide(Sphere* other) = 0;};class Box{   virtual bool CheckCollision(Collider* other)   {      return other->Collide(this);   }   virtual bool Collide(Box* other)   {      //Box box collision.   }   virtual bool Collide(Sphere* other)   {      //Box sphere collision.   }};


There. Done. Saves you pretty much nothing, you end up just calling free functions in the Collide() things to save implementing everything twice.
___________________________________________________David OlsenIf I've helped you, please vote for PigeonGrape!
Razor, you would also want to add default implemantation, instead of pure virtualization:

// Collider.h:class Box;class Sphere;class Collider{   virtual bool CheckCollision(Collider* other) = 0;   virtual bool Collide(Collider* other) = 0;   virtual bool Collide(Box* other);   virtual bool Collide(Sphere* other);};// In Collider.cpp:#include <Box.h>#include <Sphere.h>//...bool Collider::Collide(Box* other_) {  Collider* other = other_;  return Collider(other);}bool Collider::Collide(Sphere* other_) {  Collider* other = other_;  return Collider(other);}// Box.h:class Box: public Collider{   virtual bool CheckCollision(Collider* other)   {      return other->Collide(this);   }   virtual bool Collide(Collider* other)   {      // default implementation   }   virtual bool Collide(Box* other)   {      //Box box collision.   }   // Boxes and spheres collide using the default code://   virtual bool Collide(Sphere* other)};


The above adds in inheritance semantics to your code -- if a new class is added to the heiarchy with a known parent, classes that don't override the method will act as if the object is colliding with the parent.

However, you will note that whenever you add a new class, you have to add boilerplate code in lots and lots of seperate places -- you have to add O(n) glue code.

And symmetric double-dispatch functions have to be done manually, and are fragile.

Lastly, N-ary dispatch (two objects collide on a particular level, for an example of 3-ary dispatch) gets hellishly complicated I think under your model.

This topic is closed to new replies.

Advertisement