Collision Event System

Discuss topics related to BEPUphysics or physics engine development.
Post Reply
User avatar
Zukarakox
Not a Site Admin
Posts: 426
Joined: Mon Jul 10, 2006 4:28 am
Contact:

Collision Event System

Post by Zukarakox » Wed Apr 16, 2008 11:48 pm

Legal Notice: This code is in the public domain and may be used by anyone for any purpose without my consent.

This is just a collision event system I made for my game, all you have to do it invoke the method 'AddCollisionHook' and give it the entities you want it to monitor for collisions and your delegate method to answer the event.

Its 'fairly' quick and will only fire off the method that is watching the entities that collide and supports a single delegate watching multiple collisions. I have not tested the 'RemoveCollisionHook(OnCollision Delegate, Entity A, Entity B)' method yet, but it should work fine or only require a small tweak to fix, just post here if you have a problem.

This code will probably need an update with v0.5.0 and will no longer be required for v0.6.0.

The delegate, put it outside a class, near the using statements is usually where you put it.

Code: Select all

public delegate void OnCollision(Controller ContactInfomration, EventArgs e);
Put this code where you want the methods to be stored.

Code: Select all

        private static Hashtable Entities = new Hashtable();
        private static Hashtable DelegateParams = new Hashtable();
        public static void AddCollisionHook(Entity A, Entity B, OnCollision Delegate)
        {
            if (!(DelegateParams.ContainsKey(Delegate)))
            {
                List<DoubleEnt> EntList = new List<DoubleEnt>();
                EntList.Add(new DoubleEnt(A, B));
                DelegateParams.Add(Delegate, EntList);
            }
            else
            {
                ((List<DoubleEnt>)DelegateParams[Delegate]).Add(new DoubleEnt(A, B));
            }
            if (Entities.ContainsKey(A))
            {
                ((List<Entity>)Entities[A]).Add(B);
            }
            else if (Entities.ContainsKey(B))
            {
                ((List<Entity>)Entities[B]).Add(A);
            }
            else
            {
                List<Entity> HashList = new List<Entity>();
                HashList.Add(B);
                Entities.Add(A, HashList);
            }
        }
        public static void RemoveCollisionHook(OnCollision Delegate)
        {
            foreach (DoubleEnt DEnt in ((List<DoubleEnt>)DelegateParams[Delegate]))
            {
                Entity A = DEnt.a;
                Entity B = DEnt.b;
                if (Entities.ContainsKey(A) && !(Entities.ContainsKey(B)))
                { //Entities contains A but not B
                    ((List<Entity>)Entities[A]).Remove(B);
                    if (((List<Entity>)Entities[A]).Count == 0)
                    {
                        Entities.Remove(A);
                    }
                }
                else if (Entities.ContainsKey(B) && !(Entities.ContainsKey(A)))
                { //Entities contains B but not A
                    ((List<Entity>)Entities[B]).Remove(A);
                    if (((List<Entity>)Entities[B]).Count == 0)
                    {
                        Entities.Remove(B);
                    }
                }
                else
                { //Entities contains A and B
                    if (((List<Entity>)Entities[A]).Contains(B))
                    {//Entities[A] Contains B
                        ((List<Entity>)Entities[A]).Remove(B);
                        if (((List<Entity>)Entities[A]).Count == 0)
                        {
                            Entities.Remove(A);
                        }
                    }
                    else
                    {//Entities[B] Contains A
                        ((List<Entity>)Entities[B]).Remove(A);
                        if (((List<Entity>)Entities[B]).Count == 0)
                        {
                            Entities.Remove(B);
                        }
                    }
                }
            }
            DelegateParams.Remove(Delegate);
        }
        public static void RemoveCollisionHook(OnCollision Delegate, Entity A, Entity B)
        {//Removes a single entity pair from the Delegate

            foreach (DoubleEnt DEnt in ((List<DoubleEnt>)DelegateParams[Delegate]))
            {
                if ((DEnt.a == A && DEnt.b == B) || (DEnt.a == B && DEnt.b == A))
                {
                    ((List<DoubleEnt>)DelegateParams[Delegate]).Remove(DEnt);
                }
            }
            if (Entities.ContainsKey(A) && !(Entities.ContainsKey(B)))
            { //Entities contains A but not B
                ((List<Entity>)Entities[A]).Remove(B);
                if (((List<Entity>)Entities[A]).Count == 0)
                {
                    Entities.Remove(A);
                }
            }
            else if (Entities.ContainsKey(B) && !(Entities.ContainsKey(A)))
            { //Entities contains B but not A
                ((List<Entity>)Entities[B]).Remove(A);
                if (((List<Entity>)Entities[B]).Count == 0)
                {
                    Entities.Remove(B);
                }
            }
            else
            { //Entities contains A and B
                if (((List<Entity>)Entities[A]).Contains(B))
                {//Entities[A] Contains B
                    ((List<Entity>)Entities[A]).Remove(B);
                    if (((List<Entity>)Entities[A]).Count == 0)
                    {
                        Entities.Remove(A);
                    }
                }
                else
                {//Entities[B] Contains A
                    ((List<Entity>)Entities[B]).Remove(A);
                    if (((List<Entity>)Entities[B]).Count == 0)
                    {
                        Entities.Remove(B);
                    }
                }
            }
        }
        public static bool IsHooked(OnCollision Delegate)
        {
            return DelegateParams.ContainsKey(Delegate);
        }
        private static void OnCollision(Controller ContactInformation, EventArgs e)
        {
            List<OnCollision> DelegatesToInvoke = new List<OnCollision>();
            foreach (OnCollision Delegate in DelegateParams.Keys)
            {
                foreach (DoubleEnt DEnt in ((List<DoubleEnt>)DelegateParams[Delegate]))
                {
                    Entity A = DEnt.a;
                    Entity B = DEnt.b;
                    if ((A == ContactInformation.colliderA ||
                        A == ContactInformation.colliderB) &&
                        (B == ContactInformation.colliderA ||
                        B == ContactInformation.colliderB))
                    {
                        DelegatesToInvoke.Add(Delegate);
                    }
                }
            }
            foreach (OnCollision Delegate in DelegatesToInvoke)
            {
                Delegate.Invoke(ContactInformation, e);
            }
        }
Inside your update method.

Code: Select all

            List<Controller> CollisionsToReport = new List<Controller>();
            foreach (Entity ent in Entities.Keys)
            {
                if (ent is CompoundBody)
                {
                    List<Controller> controllers = new List<Controller>();
                    getControllers(ref controllers, ent);
                    if (controllers.Count > 0)
                    {
                        foreach (Entity entB in ((List<Entity>)Entities[ent]))
                        {
                            foreach (Controller controller in controllers)
                            {
                                if (controller.contacts.Count > 0)
                                {
                                    if (controller.colliderA == entB || controller.colliderB == entB)
                                    {
                                        if (controller.colliderA == entB)
                                            controller.colliderB = ent;
                                        else
                                            controller.colliderA = ent;
                                        CollisionsToReport.Add(controller);
                                    }
                                }
                            }
                        }
                    }
                }

                else if (ent.controllers.Count > 0)
                {
                    foreach (Entity entB in ((List<Entity>)Entities[ent]))
                    {
                        foreach (Controller controller in ent.controllers)
                        {
                            if (controller.contacts.Count > 0)
                            {
                                if (entB is CompoundBody)
                                {
                                    List<Entity> ents = new List<Entity>();
                                    getSubbodies(ref ents, entB);
                                    foreach (Entity entC in ents)
                                    {
                                        if (controller.colliderA == entC || controller.colliderB == entC)
                                        {
                                            if (controller.colliderA == entC)
                                                controller.colliderA = entB;
                                            else
                                                controller.colliderB = entB;
                                            CollisionsToReport.Add(controller);
                                        }
                                    }
                                }
                                else
                                {
                                    if (controller.colliderA == entB || controller.colliderB == entB)
                                    {
                                        CollisionsToReport.Add(controller);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (Controller control in CollisionsToReport)
            {
                OnCollision(control, EventArgs.Empty);
            }
Create a new class called 'DoubleEnt" and have it just hold two entities, a and b.

Code: Select all

using BEPUphysics;

namespace YOUR PROJECT NAME HERE
{
    public class DoubleEnt
    {
        public DoubleEnt(Entity A, Entity B)
        {
            a = A;
            b = B;
        }
        public Entity a;
        public Entity b;
    }
}
i has multiple toes

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest