Collision Handling the OO Way with C# Multiple Dispatch

Update: The code in this post has been updated due to an error in the first publication.
Collision handling has always been a tricky thing with OO languages. Historically, most strongly-typed (and therefore performant) OO languages have not been multiple-dispatch languages. Read the linked article for details, but the upshot of this is that the exact method overload to be called in most OO languages is determined at compile-time. This is an issue for tasks like collision handling, where we want to use abstract implementations of our types, rather than concrete types, yet we still need to handle collisions differently depending on the colliding types.

Typically this problem is solved by using type switches, enums or similar non-OO techniques. But no more! In C# 4.0 we were introduced to the dynamic keyword. dynamic allows us to tell the compiler, “hey, compiler, get your sticky hands off my method calls and let the runtime decide how to handle this”. Method calls are dynamically dispatched at runtime. So what’s the big deal? Well in terms of collision handling it allows us to write much more elegant and robust code. We no longer have need for type switches, and each class is responsible for handling how it responds to collisions with each other class, or ignore collision altogether.

Here’s a little sample program I put together to demonstrate how I handle this. Note how concrete classes are able to handle the collisions they are interested in, and ignore the ones they don’t want to handle (these are delegated to the default implementation). This is my first crack at OO collision handling, so if you have any critique or a better technique, pleae leave a comment.

using System;

namespace TestGame
{
    class Program
    {
        static void Main(string[] args)
        {
            Entity w = new Wall();
            Entity s = new Snake();

            ((dynamic)w).Collide((dynamic)s);
            ((dynamic)s).Collide((dynamic)s);
            ((dynamic)s).Collide((dynamic)w);
            ((dynamic)w).Collide((dynamic)w);
            Console.ReadLine();
        }
    }

    abstract class Entity
    {
        public virtual void Collide(Entity other)
        {
            // Do nothing in default implementation
        }
    }

    class Snake : Entity
    {
        public void Collide(Snake s)
        {
            Console.WriteLine("Snake collide with snake");
        }
        public void Collide(Wall wall)
        {
            Console.WriteLine("Snake collide with wall");
        }
    }

    class Wall : Entity
    {
        public void Collide(Snake snake)
        {
            Console.WriteLine("Wall collide with snake");
        }
    }
}

And the output from this program

This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

Leave a reply

*