예제 #1
0
        bool OnContact(Contact contact)
        {
            bool collisionAllowed = AllowCollisionsBetweenGroups(((FarActor)contact.FixtureA.Body.UserData).CollisionGroup, ((FarActor)contact.FixtureB.Body.UserData).CollisionGroup);
            bool eitherEntity     = IsEntityGroup(((FarActor)contact.FixtureA.Body.UserData).CollisionGroup) || IsEntityGroup(((FarActor)contact.FixtureB.Body.UserData).CollisionGroup);

            if (!collisionAllowed && !eitherEntity)
            {
                return(false);
            }

            if (null != BeginContact)
            {
                Collision collision = new Collision();
                collision.actor1 = (contact.FixtureA.Body.UserData as JabActor);
                collision.actor2 = (contact.FixtureB.Body.UserData as JabActor);

                BeginContact.Invoke(collision);
            }


            CollisionEvent ev = new CollisionEvent();

            ev.contactType = CollisionEvent.ContactType.ONCONTACT;
            ev._Actor1     = (contact.FixtureA.Body.UserData as JabActor);
            ev._Actor2     = (contact.FixtureB.Body.UserData as JabActor);

            Jabber.Util.EventManager.Get.SendEvent(ev);

            collisionAllowed = AllowCollisionsBetweenGroups(((FarActor)contact.FixtureA.Body.UserData).CollisionGroup, ((FarActor)contact.FixtureB.Body.UserData).CollisionGroup);
            if (eitherEntity || !collisionAllowed)
            {
                return(false);
            }
            return(true);
        }
예제 #2
0
        public void OnBeginContact(BeginContact message)
        {
            // We only get one message for a collision pair, so we handle it for both parties.
            var contact = message.Contact;

            // Get the two involved entities. We only handle one collision between
            // two bodies per tick, to avoid damage being applied multiple times.
            var entityA = Math.Min(contact.FixtureA.Entity, contact.FixtureB.Entity);
            var entityB = Math.Max(contact.FixtureA.Entity, contact.FixtureB.Entity);

            // See if either one does some damage and/or should be removed.
            var damageA = (CollisionDamage)Manager.GetComponent(entityA, CollisionDamage.TypeId);
            var damageB = (CollisionDamage)Manager.GetComponent(entityB, CollisionDamage.TypeId);

            var healthA = (Health)Manager.GetComponent(entityA, Health.TypeId);
            var healthB = (Health)Manager.GetComponent(entityB, Health.TypeId);

            // See if the hit entity should be removed on collision.
            var persistent = true;

            if (damageA != null && damageA.RemoveOnCollision)
            {
                // Entity gets removed, so forget about handling the collision physically.
                ((DeathSystem)Manager.GetSystem(DeathSystem.TypeId)).MarkForRemoval(entityA);
                contact.Disable();
                persistent = false;
            }
            if (damageB != null && damageB.RemoveOnCollision)
            {
                // Entity gets removed, so forget about handling the collision physically.
                ((DeathSystem)Manager.GetSystem(DeathSystem.TypeId)).MarkForRemoval(entityB);
                contact.Disable();
                persistent = false;
            }

            // Ignore contacts where no damage is involved at all.
            if ((damageA == null || healthB == null) &&
                (damageB == null || healthA == null))
            {
                return;
            }

            // See if we already know something about this collision.
            var key = BitwiseMagic.Pack(entityA, entityB);
            NewCollisionInfo info;

            if (!_newCollisions.TryGetValue(key, out info))
            {
                info = new NewCollisionInfo();
                _newCollisions.Add(key, info);
            }

            // Track the number of persistent contacts. This is necessary for damage "fields",
            // such as radiation in a certain area.
            if (persistent)
            {
                ++info.Count;
            }

            // See if the shield was hit.
            var shielded = false;
            var shieldA  = Manager.GetComponent(entityA, ShieldEnergyStatusEffect.TypeId) as ShieldEnergyStatusEffect;

            if (shieldA != null && (contact.FixtureA.Id == shieldA.Fixture || contact.FixtureB.Id == shieldA.Fixture))
            {
                info.IsShieldA = true;
                shielded       = true;
            }
            var shieldB = Manager.GetComponent(entityB, ShieldEnergyStatusEffect.TypeId) as ShieldEnergyStatusEffect;

            if (shieldB != null && (contact.FixtureA.Id == shieldB.Fixture || contact.FixtureA.Id == shieldB.Fixture))
            {
                info.IsShieldB = true;
                shielded       = true;
            }

            // For at least one of the involved entities a shield was hit, so get the normal.
            // Note that this can potentially lead to 'wrong' results, if an entity is hit by
            // multiple fixtures in the same frame. This is a problematic case, logically speaking:
            // what to do if this happens?
            if (shielded)
            {
                IList <FarPosition> points;
                contact.ComputeWorldManifold(out info.Normal, out points);
            }
        }