/// <summary> /// Calculates the first occuring collision event on this object's track using the collisionrules. /// </summary> internal void CalculateClosestCollision() { ClosestCollisionSpeedFraction = float.PositiveInfinity; //no (more) collision checking this step please if (SpeedLeft == 0f || Speed == Point.Zero) { SpeedLeft = 0f; return; } float touchingSpeedLeftFraction = float.PositiveInfinity; Point intersectionAxis; //decide which target of the rules is closest and within collision range foreach (CollisionRule cRule in CollisionRules) { //skip if this rule doesn't have to be checked anyway if (!cRule.Active) { continue; } //get collision candidates once if they will be checked (JIT) if (CollisionCandidates == null && (cRule.Type == CollisionRuleType.Object || cRule.Type == CollisionRuleType.ObjectType || cRule.Type == CollisionRuleType.Objectmap)) { CollisionCandidates = Game.QuadTree.GetCollisionCandidates(this); } switch (cRule.Type) { case CollisionRuleType.Shape: if (Bounds.IntersectsWith((Shape)cRule.Target, Speed, out touchingSpeedLeftFraction, out intersectionAxis) && touchingSpeedLeftFraction > 0f && touchingSpeedLeftFraction <= SpeedLeft && touchingSpeedLeftFraction < ClosestCollisionSpeedFraction) { ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; ClosestCollisionTouchingAxis = intersectionAxis; ClosestCollisionRule = cRule; ClosestCollisionMethodArg = cRule.Target; ClosestCollisionRelativeSpeed = Speed; } break; case CollisionRuleType.Object: if (CollisionCandidates.Contains((PhysicalObject)cRule.Target) && Bounds.IntersectsWith(((PhysicalObject)cRule.Target).Bounds, Speed - ((PhysicalObject)cRule.Target).Speed, out touchingSpeedLeftFraction, out intersectionAxis) && touchingSpeedLeftFraction > 0f && touchingSpeedLeftFraction <= SpeedLeft && (touchingSpeedLeftFraction <= ((PhysicalObject)cRule.Target).SpeedLeft || ((PhysicalObject)cRule.Target).Speed == Point.Zero) && touchingSpeedLeftFraction < ClosestCollisionSpeedFraction) { ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; ClosestCollisionTouchingAxis = intersectionAxis; ClosestCollisionRule = cRule; ClosestCollisionMethodArg = cRule.Target; ClosestCollisionRelativeSpeed = Speed - ((PhysicalObject)cRule.Target).Speed; } break; case CollisionRuleType.ObjectType: foreach (PhysicalObject obj in Resources.PhysicalObjectsByType[(Type)cRule.Target]) { if (CollisionCandidates.Contains(obj) && Bounds.IntersectsWith(obj.Bounds, Speed - obj.Speed, out touchingSpeedLeftFraction, out intersectionAxis) && touchingSpeedLeftFraction > 0f && touchingSpeedLeftFraction <= SpeedLeft && (touchingSpeedLeftFraction <= obj.SpeedLeft || obj.Speed == Point.Zero) && touchingSpeedLeftFraction < ClosestCollisionSpeedFraction) { ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; ClosestCollisionTouchingAxis = intersectionAxis; ClosestCollisionRule = cRule; ClosestCollisionMethodArg = obj; ClosestCollisionRelativeSpeed = Speed - obj.Speed; } } break; case CollisionRuleType.Objectmap: foreach (PhysicalObject obj in ((Objectmap)cRule.Target).ActivePhysicalObjects) { //whether the object should be checked if the filter is enabled if (!cRule.FilterEnabled || cRule.ObjectmapFilter.Contains(obj.GetType())) //account for inheritance { if (CollisionCandidates.Contains(obj) && Bounds.IntersectsWith(obj.Bounds, Speed - obj.Speed, out touchingSpeedLeftFraction, out intersectionAxis) && touchingSpeedLeftFraction > 0f && touchingSpeedLeftFraction <= SpeedLeft && (touchingSpeedLeftFraction <= obj.SpeedLeft || obj.Speed == Point.Zero) && touchingSpeedLeftFraction < ClosestCollisionSpeedFraction) { ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; ClosestCollisionTouchingAxis = intersectionAxis; ClosestCollisionRule = cRule; ClosestCollisionMethodArg = obj; ClosestCollisionRelativeSpeed = Speed - obj.Speed; } } } break; case CollisionRuleType.Spritemap: foreach (ManagedSprite sprite in ((Spritemap)cRule.Target).ManagedSprites) { //whether the object should be checked if the filter is enabled if (!cRule.FilterEnabled || cRule.SpritemapFilter.Contains(sprite.TargetSprite)) //account for inheritance { if (Bounds.IntersectsWith(sprite, Speed, out touchingSpeedLeftFraction, out intersectionAxis) && touchingSpeedLeftFraction > 0f && touchingSpeedLeftFraction <= SpeedLeft && touchingSpeedLeftFraction < ClosestCollisionSpeedFraction) { ClosestCollisionSpeedFraction = touchingSpeedLeftFraction; ClosestCollisionTouchingAxis = intersectionAxis; ClosestCollisionRule = cRule; ClosestCollisionMethodArg = sprite; ClosestCollisionRelativeSpeed = Speed; } } } break; } } }
/// <summary> /// Calculates the first occuring collision event on this object's track using the collisionrules. /// </summary> internal void CalculateClosestCollision() { ClosestCollisionSpeedFraction = float.PositiveInfinity; //no (more) collision checking this step please if (SpeedLeft == 0f || Speed == Point.Zero) { SpeedLeft = 0f; return; } //decide which target of the rules is closest and within collision range foreach(CollisionRule cRule in CollisionRules) { //skip if this rule doesn't have to be checked anyway if (!cRule.Active) continue; //get collision candidates once if they will be checked (JIT) if (CollisionCandidates == null && (cRule.Type == CollisionRuleType.Object || cRule.Type == CollisionRuleType.ObjectType || cRule.Type == CollisionRuleType.Objectmap)) CollisionCandidates = Game.QuadTree.GetCollisionCandidates(this); float touchingSpeedLeftFraction; Point intersectionAxis; switch (cRule.Type) { case CollisionRuleType.Shape: if (Bounds.IntersectsWith((Shape)cRule.Target, Speed, out touchingSpeedLeftFraction, out intersectionAxis) && touchingSpeedLeftFraction > 0f && touchingSpeedLeftFraction <= SpeedLeft && touchingSpeedLeftFraction < ClosestCollisionSpeedFraction) { ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; _closestCollisionTouchingAxis = intersectionAxis; _closestCollisionRule = cRule; _closestCollisionMethodArg = cRule.Target; _closestCollisionRelativeSpeed = Speed; } break; case CollisionRuleType.Object: if (CollisionCandidates.Contains((PhysicalObject)cRule.Target) && Bounds.IntersectsWith(((PhysicalObject)cRule.Target).Bounds, Speed - ((PhysicalObject)cRule.Target).Speed, out touchingSpeedLeftFraction, out intersectionAxis) && touchingSpeedLeftFraction > 0f && touchingSpeedLeftFraction <= SpeedLeft && (touchingSpeedLeftFraction <= ((PhysicalObject)cRule.Target).SpeedLeft || ((PhysicalObject)cRule.Target).Speed == Point.Zero) && touchingSpeedLeftFraction < ClosestCollisionSpeedFraction) { ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; _closestCollisionTouchingAxis = intersectionAxis; _closestCollisionRule = cRule; _closestCollisionMethodArg = cRule.Target; _closestCollisionRelativeSpeed = Speed - ((PhysicalObject)cRule.Target).Speed; } break; case CollisionRuleType.ObjectType: foreach (PhysicalObject obj in Resources.PhysicalObjectsByType[(Type)cRule.Target]) { if (!CollisionCandidates.Contains(obj) || !Bounds.IntersectsWith(obj.Bounds, Speed - obj.Speed, out touchingSpeedLeftFraction, out intersectionAxis) || !(touchingSpeedLeftFraction > 0f) || !(touchingSpeedLeftFraction <= SpeedLeft) || (!(touchingSpeedLeftFraction <= obj.SpeedLeft) && obj.Speed != Point.Zero) || !(touchingSpeedLeftFraction < ClosestCollisionSpeedFraction)) continue; ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; _closestCollisionTouchingAxis = intersectionAxis; _closestCollisionRule = cRule; _closestCollisionMethodArg = obj; _closestCollisionRelativeSpeed = Speed - obj.Speed; } break; case CollisionRuleType.Objectmap: foreach (PhysicalObject obj in ((GameObjectCollection)cRule.Target).ActivePhysicalObjects) { //whether the object should be checked if the filter is enabled if (!cRule.FilterEnabled || cRule.ObjectmapFilter.Contains(obj.GetType())) //account for inheritance { if (!CollisionCandidates.Contains(obj) || !Bounds.IntersectsWith(obj.Bounds, Speed - obj.Speed, out touchingSpeedLeftFraction, out intersectionAxis) || !(touchingSpeedLeftFraction > 0f) || !(touchingSpeedLeftFraction <= SpeedLeft) || (!(touchingSpeedLeftFraction <= obj.SpeedLeft) && obj.Speed != Point.Zero) || !(touchingSpeedLeftFraction < ClosestCollisionSpeedFraction)) continue; ClosestCollisionSpeedFraction = touchingSpeedLeftFraction * SpeedLeft; _closestCollisionTouchingAxis = intersectionAxis; _closestCollisionRule = cRule; _closestCollisionMethodArg = obj; _closestCollisionRelativeSpeed = Speed - obj.Speed; } } break; } } }