/// <summary> /// Used for weightlessness to determine if we are near a wall. /// </summary> /// <param name="broadPhaseSystem"></param> /// <param name="transform"></param> /// <param name="mover"></param> /// <param name="collider"></param> /// <returns></returns> public static bool IsAroundCollider(SharedBroadphaseSystem broadPhaseSystem, ITransformComponent transform, IMobMoverComponent mover, IPhysBody collider) { var enlargedAABB = collider.GetWorldAABB().Enlarged(mover.GrabRange); foreach (var otherCollider in broadPhaseSystem.GetCollidingEntities(transform.MapID, enlargedAABB)) { if (otherCollider == collider) { continue; // Don't try to push off of yourself! } // Only allow pushing off of anchored things that have collision. if (otherCollider.BodyType != BodyType.Static || !otherCollider.CanCollide || ((collider.CollisionMask & otherCollider.CollisionLayer) == 0 && (otherCollider.CollisionMask & collider.CollisionLayer) == 0) || (otherCollider.Owner.TryGetComponent(out SharedPullableComponent? pullable) && pullable.BeingPulled)) { continue; } return(true); } return(false); }
public float CalculatePenetration(IPhysBody target, IPhysBody source) { var manifold = target.GetWorldAABB().Intersect(source.GetWorldAABB()); if (manifold.IsEmpty()) { return(0.0f); } return(manifold.Height > manifold.Width ? manifold.Width : manifold.Height); }
/// <summary> /// Calculates the normal vector for two colliding bodies /// </summary> /// <param name="target"></param> /// <param name="source"></param> /// <returns></returns> public static Vector2 CalculateNormal(IPhysBody target, IPhysBody source) { var manifold = target.GetWorldAABB().Intersect(source.GetWorldAABB()); if (manifold.IsEmpty()) { return(Vector2.Zero); } if (manifold.Height > manifold.Width) { // X is the axis of seperation var leftDist = source.GetWorldAABB().Right - target.GetWorldAABB().Left; var rightDist = target.GetWorldAABB().Right - source.GetWorldAABB().Left; return(new Vector2(leftDist > rightDist ? 1 : -1, 0)); } else { // Y is the axis of seperation var bottomDist = source.GetWorldAABB().Top - target.GetWorldAABB().Bottom; var topDist = target.GetWorldAABB().Top - source.GetWorldAABB().Bottom; return(new Vector2(0, bottomDist > topDist ? 1 : -1)); } }
private bool TrySlip(SlipperyComponent component, IPhysBody ourBody, IPhysBody otherBody) { if (!component.Slippery || component.Owner.IsInContainer() || component.Slipped.Contains(otherBody.Owner.Uid) || !otherBody.Owner.TryGetComponent(out SharedStunnableComponent? stun)) { return(false); } if (otherBody.LinearVelocity.Length < component.RequiredSlipSpeed || stun.KnockedDown) { return(false); } var percentage = otherBody.GetWorldAABB().IntersectPercentage(ourBody.GetWorldAABB()); if (percentage < component.IntersectPercentage) { return(false); } if (!EffectBlockerSystem.CanSlip(otherBody.Owner)) { return(false); } otherBody.LinearVelocity *= component.LaunchForwardsMultiplier; stun.Paralyze(5); component.Slipped.Add(otherBody.Owner.Uid); component.Dirty(); PlaySound(component); return(true); }