Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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;
            }
        }
Пример #5
0
        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);
            }
        }
Пример #7
0
        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;
                }
            }
        }
Пример #8
0
 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;
         }
     }
 }
Пример #9
0
        /// <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;
        }
Пример #10
0
        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;
        }
Пример #11
0
 private void HandleContact(LSBody other)
 {
     isColliding = true;
 }
Пример #12
0
        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));
        }
Пример #14
0
 protected override void OnInitialize()
 {
     CachedBody = Agent.Body;
     UpdateCoordinates();
 }
Пример #15
0
        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++;
        }
Пример #16
0
        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
                    {
                    }
                }
            }
        }
Пример #17
0
 private void RemoveChild(LSBody child)
 {
     Children.Remove(child);
 }
 private bool CheckCollision(LSBody target)
 {
     return(target._position.FastDistance(Position.x, Position.y) <= target.FastRadius);
 }
Пример #19
0
        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();
 }