Search code examples
c#genericscollision-detectionxna-4.0game-physics

Using Generic Functions for collision detection in C# / XNA


I am making a physics engine in c# / XNA, I have three basic objects...

Sphere Cube Plane

that are all derived from

GameObject

I store all my objects in a list of GameObjects and I would like to loop through this list and be able to call a CheckCollision function that will go to the correct function for each pair of objects

eg

go is a Sphere,

go2 is a Sphere

if(CheckCollision(go, go2))
{
  //do stuff
}

bool CheckCollision(Sphere one, Sphere two)
{
  //Check Sphere to Sphere
}

bool CheckCollision(Sphere sphere, Plane plane)
{
  //Check Sphere to Plane
}

and I would like it to just go to the correct function withour having to use if checks.

Thank you.


Solution

  • You could use virtual dispatch:

    abstract class GameObject
    {
        abstract bool CheckCollision (GameObject other);
        abstract bool CheckCollision (Sphere other);
        abstract bool CheckCollision (Cube other);
        abstract bool CheckCollision (Plane other);
    }
    
    class Sphere : GameObject
    {
        override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
        override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
        override bool CheckCollision (Cube other) { /* ... implementation ... */ }
        override bool CheckCollision (Plane other) { /* ... implementation ... */ }
    }
    
    class Cube : GameObject
    {
        override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
        override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
        override bool CheckCollision (Cube other) { /* ... implementation ... */ }
        override bool CheckCollision (Plane other) { /* ... implementation ... */ }
    }
    
    class Plane : GameObject
    {
        override bool CheckCollision (GameObject other) { return other.CheckCollision(this); }
        override bool CheckCollision (Sphere other) { /* ... implementation ... */ }
        override bool CheckCollision (Cube other) { /* ... implementation ... */ }
        override bool CheckCollision (Plane other) { /* ... implementation ... */ }
    }
    

    EDIT

    Consider what happens when you have this:

    GameObject go1 = new Sphere();
    GameObject go2 = new Cube();
    bool collision = go1.CheckCollision(go2);
    
    • The call goes to the abstract GameObject.CheckCollision(GameObject) method on the sphere.
    • Virtual dispatch means that we go to Sphere.CheckCollision(GameObject)
    • Sphere.CheckCollision(GameObject) calls the abstract GameObject.CheckCollision(Sphere) method on the cube.
    • Virtual dispatch means that we go to Cube.CheckCollision(Sphere)!

    Therefore, no type-checking if statements are necessary.

    EDIT 2

    See Eric Lippert's answer at https://stackoverflow.com/a/2367981/385844; the first option -- the visitor pattern -- is essentially the approach outlined above. Eric's other answer at https://stackoverflow.com/a/9069976/385844 also discusses this issue.