private static bool CheckBox_Poly(LSBody box, LSBody poly) { bool Right = poly._position.x > box._position.x; bool Top = poly._position.y > box._position.y; bool xPassed = false; bool yPassed = false; int vertCount = poly.RealPoints.Length; for (int i = 0; i < vertCount; i++) { if (!xPassed) { if (Right) { if (poly.RealPoints [i].x <= box.XMax) { xPassed = true; } } else { if (poly.RealPoints [i].x >= box.XMin) { xPassed = true; } } } if (!yPassed) { if (Top) { if (poly.RealPoints [i].y <= box.YMax) { yPassed = true; } } else { if (poly.RealPoints [i].y >= box.YMin) { yPassed = true; } } } if (xPassed && yPassed) { return(true); } } return(false); }
private static CollisionPair CreatePair(LSBody body1, LSBody body2) { CollisionPair pair; if (CachedCollisionPairs.Count > 0) { pair = CachedCollisionPairs.Pop(); } else { pair = new CollisionPair(); } pair.Initialize(body1, body2); return(pair); }
private static bool CheckCircle_Poly(LSBody circle, LSBody poly) { int EdgeCount = poly.EdgeNorms.Length; ClosestDist = long.MaxValue; for (int i = 0; i < EdgeCount; i++) { Vector2d axis = poly.EdgeNorms [i]; long CircleProjection = circle._position.Dot(axis.x, axis.y); long CircleMin = CircleProjection - circle.Radius; long CircleMax = CircleProjection + circle.Radius; long PolyMin; long PolyMax; ProjectPolygon(axis.x, axis.y, poly, out PolyMin, out PolyMax); //TODO: Cache PolyMin and PolyMax? if (CheckOverlap(CircleMin, CircleMax, PolyMin, PolyMax)) { long dist1 = PolyMax - CircleMin; long dist2 = CircleMax - PolyMin; long localCloseDist = 0; if (dist1 <= dist2) { localCloseDist = dist1; } else { localCloseDist = -dist2; } if (localCloseDist.Abs() < ClosestDist.Abs()) { ClosestDist = localCloseDist; ClosestAxis = axis; ClosestAxisProjection = CircleProjection; } } else { return(false); } } return(true); }
internal static void Dessimilate(LSBody body) { int tid = body.ID; if (!SimObjects[tid].IsNotNull()) { Debug.LogWarning("Object with ID" + body.ID.ToString() + "cannot be dessimilated because it it not assimilated"); return; } SimObjects[tid] = null; CachedIDs.Add(tid); if (body.DynamicID >= 0) { DynamicSimObjects.RemoveAt(body.DynamicID); body.DynamicID = -1; } }
public static void Visualize() { LerpTime = Time.fixedDeltaTime; if (ResetAccumulation) { AccumulatedTime = 0; } AccumulatedTime += Time.deltaTime; ExpectedAccumulation = AccumulatedTime / LerpTime; for (int i = 0; i < DynamicSimObjects.PeakCount; i++) { LSBody b1 = DynamicSimObjects.innerArray[i]; if (b1.IsNotNull()) { b1.SetVisuals(); } } ResetAccumulation = false; }
private static void GetGridBounds(LSBody Body) { GridXMin = GetGridX(Body.XMin); GridXMax = GetGridX(Body.XMax); GridYMin = GetGridY(Body.YMin); GridYMax = GetGridY(Body.YMax); int iterationCount = 0; while (CheckSize(GridXMin, GridXMax, GridYMin, GridYMax)) { iterationCount++; if (iterationCount >= 5) { break; } GridXMin = GetGridX(Body.XMin); GridXMax = GetGridX(Body.XMax); GridYMin = GetGridY(Body.YMin); GridYMax = GetGridY(Body.YMax); } }
public static void ProjectPolygon(long AxisX, long AxisY, LSBody Poly, out long Min, out long Max) { Min = Poly.RealPoints [0].Dot(AxisX, AxisY); Max = Min; int PointCount = Poly.RealPoints.Length; long Projection; for (int i = 1; i < PointCount; i++) { Projection = Poly.RealPoints [i].Dot(AxisX, AxisY); if (Projection < Min) { Min = Projection; } else if (Projection > Max) { Max = Projection; } } }
void DistributeCircle_CirclePriority(LSBody higherPriority, LSBody lowerPriority) { if (true || higherPriority.Immovable || lowerPriority.ImmovableCollisionDirection.EqualsZero()) { DistributeCircle(lowerPriority); lowerPriority.ImmovableCollisionDirection = new Vector2d(DistX, DistY); } else { //TODO: Fix this behavior. It's supposed to prevent pass-through between i.e. buildings. //Only move if there isn't an immovable object in that direction if (lowerPriority.ImmovableCollisionDirection.x.Sign() != DistX.Sign()) { lowerPriority._position.x += DistX; } if (lowerPriority.ImmovableCollisionDirection.y.Sign() != DistY.Sign()) { lowerPriority._position.y += DistY; } } }
/// <summary> /// Call this to deactivate this body and remove from simulation. /// </summary> public void Deactivate() { //Don't double deactivate if (this.Active == false) { return; } Partition.UpdateObject(this, false); foreach (var collisionPair in CollisionPairs.Values) { collisionPair.Body2.CollisionPairHolders.Remove(ID); DeactivatePair(collisionPair); } CollisionPairs.Clear(); foreach (var id in CollisionPairHolders) { LSBody other = PhysicsManager.SimObjects[id]; if (other.IsNotNull()) { CollisionPair collisionPair; if (other.CollisionPairs.TryGetValue(ID, out collisionPair)) { other.CollisionPairs.Remove(this.ID); DeactivatePair(collisionPair); } else { Debug.Log("nope " + ID); } } } CollisionPairHolders.Clear(); PhysicsManager.Dessimilate(this); Active = false; }
public static void LateSimulate() { //TODO: Look into this int inactiveFrameThreshold = LockstepManager.FrameRate * 8; for (int i = 0; i < RanCollisionPairs.PeakCount; i++) { if (RanCollisionPairs.arrayAllocation[i]) { var instancePair = RanCollisionPairs[i]; var pair = RanCollisionPairs[i].Pair; if (instancePair.Version != instancePair.Pair._Version) { //pair is removed at Deactivate so no longer possible } else { if (pair._ranIndex >= 0) { RanCollisionPairs.RemoveAt(pair._ranIndex); pair._ranIndex = -1; InactiveCollisionPairs.Add(instancePair); } } } } //Clear the buffer of collision pairs to turn off and pool while (InactiveCollisionPairs.Count > 0) { var instancePair = InactiveCollisionPairs.Peek(); var pair = instancePair.Pair; if (pair.Active) { //It's active again! Get it out of inactives and move on to the next guy. InactiveCollisionPairs.Remove(); } var passedFrames = LockstepManager.FrameCount - pair.LastFrame; if (passedFrames >= inactiveFrameThreshold) { InactiveCollisionPairs.Remove(); FullDeactivateCollisionPair(pair); } else { break; } } for (int i = 0; i < DynamicSimObjects.PeakCount; i++) { LSBody b1 = DynamicSimObjects.innerArray[i]; if (b1.IsNotNull()) { b1.Simulate(); } } ResetAccumulation = true; }
private void HandleContact(LSBody other) { isColliding = true; }
public static bool CheckCircle_Box(LSBody box, LSBody circle) { Collided = false; xMore = circle._position.x > box._position.x; yMore = circle._position.y > box._position.y; if (!Collided) { Collided = false; if (xMore) { if (circle._position.x <= box.XMax) { Collided = true; } } else { if (circle._position.x >= box.XMin) { Collided = true; } } if (yMore) { if (circle._position.y <= box.YMax) { Collided = true; } } else { if (circle._position.y >= box.YMin) { Collided = true; } } if (!Collided) { if (xMore) { xDist = (circle._position.x) - (box.XMax); } else { xDist = (circle._position.x) - (box.XMin); } if (yMore) { yDist = (circle._position.y) - (box.YMax); } else { yDist = (circle._position.y) - (box.YMin); } if ((xDist * xDist + yDist * yDist) <= circle.Radius * circle.Radius) { Collided = true; } } } return(Collided); }
public static LSEffect CreateCollisionEffect(string effectCode, LSProjectile projectile, LSBody hitBody) { Vector3 collisionDirection = -(projectile.Forward.ToVector3()); Vector3 collisionPosition = collisionDirection * hitBody.Radius.ToFloat() + hitBody.PositionalTransform.position; return(CreateEffect(effectCode, collisionPosition, projectile.transform.rotation)); }
protected override void OnInitialize() { CachedBody = Agent.Body; UpdateCoordinates(); }
public void Initialize(LSBody b1, LSBody b2) { IsValid = true; if (!IsValid) { return; } if (b1.ID < b2.ID) { Body1 = b1; Body2 = b2; } else { Body1 = b2; Body2 = b1; } _ranIndex = -1; _isColliding = false; DistX = 0; DistY = 0; PenetrationX = 0; PenetrationY = 0; FastCollideDistance = b1.Radius + b2.Radius; FastCollideDistance *= FastCollideDistance; LeCollisionType = CollisionType.None; if (Body1.Shape == ColliderType.None || Body2.Shape == ColliderType.None) { } else if (Body1.Shape == ColliderType.Circle) { if (Body2.Shape == ColliderType.Circle) { LeCollisionType = CollisionType.Circle_Circle; } else if (Body2.Shape == ColliderType.AABox) { LeCollisionType = CollisionType.Circle_AABox; } else if (Body2.Shape == ColliderType.Polygon) { LeCollisionType = CollisionType.Circle_Polygon; } } else if (Body1.Shape == ColliderType.AABox) { if (Body2.Shape == ColliderType.Circle) { LeCollisionType = CollisionType.Circle_AABox; } else if (Body2.Shape == ColliderType.AABox) { LeCollisionType = CollisionType.AABox_AABox; } else if (Body2.Shape == ColliderType.Polygon) { LeCollisionType = CollisionType.AABox_Polygon; } } else if (Body1.Shape == ColliderType.Polygon) { if (Body2.Shape == ColliderType.Circle) { LeCollisionType = CollisionType.Circle_Polygon; } else if (Body2.Shape == ColliderType.AABox) { LeCollisionType = CollisionType.AABox_Polygon; } else if (Body2.Shape == ColliderType.Polygon) { LeCollisionType = CollisionType.Polygon_Polygon; } } DoPhysics = ((Body1.IsTrigger || Body2.IsTrigger) == false); if (DoPhysics) { } //TODO: Space out checks when culled //TODO: The time between collision checks might cause goofy behavior //Maybe use a distance or velocity heuristic for culling instead of time since last collision //It wouldn't be able to replace partitions because of raycasts and fast-moving objects //Let's see if this works well or if something better is needed. if (Body1.PreventCulling || Body2.PreventCulling) { //Never cull CullCounter = -1; } else { //Immediately check collision CullCounter = 0; //If collision distance is too large, don't cull based on distance PreventDistanceCull = FastCollideDistance > PhysicsManager.CullFastDistanceMax; LastCollidedFrame = LockstepManager.FrameCount; FastDistanceOffset = FixedMath.Sqrt(FastCollideDistance >> FixedMath.SHIFT_AMOUNT) + FixedMath.One * 2; FastDistanceOffset *= FastDistanceOffset; } Active = true; _Version++; }
private void HandleCollision(LSBody other) { if (!CanMove) { return; } if ((tempAgent = other.Agent) == null) { return; } Move otherMover = tempAgent.GetAbility <Move>(); if (ReferenceEquals(otherMover, null) == false) { if (IsMoving) { //If the other mover is moving to a similar point if (otherMover.MyMovementGroupID == MyMovementGroupID || otherMover.targetPos.FastDistance(this.targetPos) <= (closingDistance * closingDistance)) { if (otherMover.IsMoving == false) { if (otherMover.Arrived && otherMover.StoppedTime > MinimumOtherStopTime) { Arrive(); } } else { if (hasPath && otherMover.hasPath && otherMover.pathIndex > 0 && otherMover.lastTargetPos.SqrDistance(targetPos.x, targetPos.y) < closingDistance.Mul(closingDistance)) { if (this.distance < this.closingDistance) { this.pathIndex++; } } } } if (GetLookingForStopPause()) { //As soon as the original collision stop unit is released, units will start breaking out of pauses if (otherMover.GetCanCollisionStop() == false) { StopPauseLayer = -1; PauseAutoStop(); } else if (otherMover.GetCanAutoStop() == false) { if (otherMover.StopPauseLayer < StopPauseLayer) { StopPauseLayer = otherMover.StopPauseLayer + 1; PauseAutoStop(); } } } else { } } } }
private void RemoveChild(LSBody child) { Children.Remove(child); }
private bool CheckCollision(LSBody target) { return(target._position.FastDistance(Position.x, Position.y) <= target.FastRadius); }
private void DistributeCircle_Box(LSBody box, LSBody circle) { xMore = circle._position.x > box._position.x; yMore = circle._position.y > box._position.y; if (xMore) { PenetrationX = (circle.XMin - box.XMax); } else { PenetrationX = (circle.XMax - box.XMin); } if (yMore) { PenetrationY = (circle.YMin - box.YMax); } else { PenetrationY = (circle.YMax - box.YMin); } //PenetrationX = PenetrationX + circle.Velocity.x; //PenetrationY = PenetrationY + circle.Velocity.y; xAbs = PenetrationX < 0 ? -PenetrationX : PenetrationX; yAbs = PenetrationY < 0 ? -PenetrationY : PenetrationY; if ((xAbs <= circle.Radius && yAbs <= circle.Radius)) { Vector2d corner; corner.x = xMore ? box.Position.x + box.HalfWidth : box.Position.x - box.HalfWidth; corner.y = yMore ? box.Position.y + box.HalfLength : box.Position.y - box.HalfLength; Vector2d dir = circle.Position - corner; dir.Normalize(); circle.Position = corner + dir * circle.Radius; } else { if (xAbs > yAbs) { PenetrationX = 0; //if (yAbs < circle.Radius) PenetrationY = PenetrationY * yAbs / circle.Radius; if (PenetrationY > 0 == yMore) { PenetrationY = -PenetrationY; } } else { PenetrationY = 0; //if (xAbs < circle.Radius) PenetrationX = PenetrationX * xAbs / circle.Radius; if (PenetrationX > 0 == xMore) { PenetrationX = -PenetrationX; } } //Resolving circle._position.x -= PenetrationX; circle._position.y -= PenetrationY; } circle.PositionChanged = true; circle.BuildBounds(); }
protected override void OnSetup() { CachedBody = Agent.Body; UpdateCoordinates(); }