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); }
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); } }