Esempio n. 1
0
        public long getProjectionRadius(Vector2d axis)
        {
            long pAxisX = Math.Abs(axis.Dot(m_AxisX));
            long pAxisY = Math.Abs(axis.Dot(m_AxisY));

            return(m_Half.x.Mul(pAxisX) + m_Half.y.Mul(pAxisY));
        }
Esempio n. 2
0
        private void ApplyCone(Vector3d center3d, Vector2d forward, long radius, long angle)
        {
            Vector2d center    = center3d.ToVector2d();
            long     fastRange = radius * radius;

            Scan(center, radius);
            for (int i = 0; i < ScanOutput.Count; i++)
            {
                LSAgent  agent      = ScanOutput[i];
                Vector2d agentPos   = agent.Body._position;
                Vector2d difference = agentPos - center;

                if (difference.FastMagnitude() > fastRange)
                {
                    continue;
                }
                if (forward.Dot(difference) < 0)
                {
                    continue;
                }
                difference.Normalize();

                long cross = forward.Cross(difference).Abs();
                if (cross > angle)
                {
                    continue;
                }
                HitAgent(agent);
            }
        }
Esempio n. 3
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 && CanCollisionStop)
                {
                    if (otherMover.MyMovementGroupID == MyMovementGroupID)
                    {
                        if (otherMover.IsMoving == false && otherMover.Arrived && otherMover.stopTime > MinimumOtherStopTime)
                        {
                            Arrive();
                        }
                        else if (hasPath && otherMover.hasPath && otherMover.pathIndex > 0 && otherMover.lastTargetPos.SqrDistance(targetPos.x, targetPos.y) < FixedMath.One)
                        {
                            if (movementDirection.Dot(targetDirection.x, targetDirection.y) < 0)
                            {
                                pathIndex++;
                            }
                        }
                    }
                }
            }
        }
        public static void PrepareAxisCheck(Vector2d p1, Vector2d p2, bool calculateIntersectionPoints = true)
        {
            cacheP1   = p1;
            cacheP2   = p2;
            cacheAxis = p2 - p1;
            cacheAxis.Normalize();
            cacheAxisNormal = cacheAxis.rotatedLeft;

            axisMin       = p1.Dot(cacheAxis.x, cacheAxis.y);
            axisMax       = p2.Dot(cacheAxis.x, cacheAxis.y);
            cacheProj     = cacheP1.Dot(cacheAxis.x, cacheAxis.y);
            cacheProjPerp = cacheP1.Dot(cacheAxisNormal.x, cacheAxisNormal.y);
            perpVector    = cacheAxisNormal * cacheProjPerp;

            calculateIntersections = calculateIntersectionPoints;
        }
        private void ApplyCone(Vector3d center3d, Vector2d forward, long radius, long angle, Action <LSAgent> apply, PlatformType targetPlatform)
        {
            Vector2d center    = center3d.ToVector2d();
            long     fastRange = radius * radius;

            foreach (LSAgent agent in Scan(center, radius))
            {
                LSProjectile.agentPos   = agent.Body._position;
                LSProjectile.difference = LSProjectile.agentPos - center;

                if (LSProjectile.difference.FastMagnitude() > fastRange)
                {
                    continue;
                }

                if (forward.Dot(difference) <= 0)
                {
                    continue;
                }

                LSProjectile.difference.Normalize();

                if (forward.Cross(difference).Abs() > angle)
                {
                    continue;
                }

                apply(agent);
            }
        }
Esempio n. 6
0
        public bool isCollision(FixedOBB2D obb)
        {
            Vector2d centerdis = m_Center - obb.m_Center;

            //4条检测轴
            Vector2d[] axes =
            {
                m_AxisX,
                m_AxisY,
                obb.m_AxisX,
                obb.m_AxisY,
            };
            long r1, r2, r3;

            for (int i = 0; i < axes.Length; ++i)
            {
                r1 = this.getProjectionRadius(axes[i]);
                r2 = obb.getProjectionRadius(axes[i]);
                r3 = Math.Abs(centerdis.Dot(axes[i]));
                if (r1 + r2 <= r3)
                {
                    //Debug.LogFormat("R1_{0:F}, R2_{1:F}, R:{2:F}, R:{3:F}", r1.ToFloat(), r2.ToFloat(), (r1 + r2).ToFloat(), r3.ToFloat());
                    return(false);
                }
            }

            return(true);
        }
 public static void PrepareAxisCheck(Vector2d p1, Vector2d p2)
 {
     cacheP1   = p1;
     cacheP2   = p2;
     cacheAxis = p2 - p1;
     cacheAxis.Normalize();
     axisMin       = p1.Dot(cacheAxis.x, cacheAxis.y);
     axisMax       = p2.Dot(cacheAxis.x, cacheAxis.y);
     cacheProjPerp = cacheP1.Cross(cacheAxis.x, cacheAxis.y);
 }
Esempio n. 8
0
        public bool IsPositionCovered(Vector2d position)
        {
            //Checks if this body covers a position

            //Different techniques for different shapes
            switch (this.Shape)
            {
            case ColliderType.Circle:
                long maxDistance = this.Radius + FixedMath.Half;
                maxDistance *= maxDistance;
                if ((this._position - position).FastMagnitude() > maxDistance)
                {
                    return(false);
                }
                goto case ColliderType.AABox;

            case ColliderType.AABox:
                return(position.x + FixedMath.Half >= this.XMin && position.x - FixedMath.Half <= this.XMax &&
                       position.y + FixedMath.Half >= this.YMin && position.y - FixedMath.Half <= this.YMax);

                break;

            case ColliderType.Polygon:
                for (int i = this.EdgeNorms.Length - 1; i >= 0; i--)
                {
                    Vector2d norm = this.EdgeNorms [i];
                    long     posProj = norm.Dot(position);
                    long     polyMin, polyMax;
                    CollisionPair.ProjectPolygon(norm.x, norm.y, this, out polyMin, out polyMax);
                    if (posProj >= polyMin && posProj <= polyMax)
                    {
                    }
                    else
                    {
                        return(false);
                    }
                }
                return(true);

                break;
            }


            return(false);
        }
Esempio n. 9
0
        private bool InternalRaycast(Vector2d From, Vector2d To, int ExceptionID)
        {
            _Version++;

            MadeContact = false;
            Hits.FastClear();


            const int StepSize = 1 << Partition.ShiftSize;

            x0 = From.x;
            y0 = From.y;
            x1 = To.x;
            y1 = To.y;
            if (y1 > y0)
            {
                compare1 = y1 - y0;
            }
            else
            {
                compare1 = y0 - y1;
            }
            if (x1 > x0)
            {
                compare2 = x1 - x0;
            }
            else
            {
                compare2 = x0 - x1;
            }
            steep = compare1 > compare2;
            if (steep)
            {
                t  = x0;                // swap x0 and y0
                x0 = y0;
                y0 = t;
                t  = x1;                // swap x1 and y1
                x1 = y1;
                y1 = t;
            }
            if (x0 > x1)
            {
                t  = x0;                // swap x0 and x1
                x0 = x1;
                x1 = t;
                t  = y0;                // swap y0 and y1
                y0 = y1;
                y1 = t;
            }
            dx = x1 - x0;

            dy = (y1 - y0);
            if (dy < 0)
            {
                dy = -dy;
            }

            error = dx / 2;
            ystep = (y0 < y1) ? StepSize : -StepSize;
            y     = y0;

            AxisX = From.x - To.x;
            AxisY = From.y - To.y;
            Mag   = FixedMath.Sqrt((AxisX * AxisX + AxisY * AxisY) >> FixedMath.SHIFT_AMOUNT);
            if (Mag == 0)
            {
                return(false);
            }
            AxisX   = FixedMath.Div(AxisX, Mag);
            AxisY   = FixedMath.Div(AxisY, Mag);
            AxisMin = Vector2d.Dot(AxisX, AxisY, From.x, From.y);
            AxisMax = Vector2d.Dot(AxisX, AxisY, To.x, To.y);
            if (AxisMin > AxisMax)
            {
                SwapValue = AxisMin;
                AxisMin   = AxisMax;
                AxisMax   = SwapValue;
            }
            PerpProj = Vector2d.Dot(-AxisY, AxisX, From.x, From.y);

            XMin = From.x;
            XMax = To.x;
            if (XMin > XMax)
            {
                SwapValue = XMin;
                XMin      = XMax;
                XMax      = SwapValue;
            }
            YMin = From.y;
            YMax = To.y;
            if (YMin > YMax)
            {
                SwapValue = YMin;
                YMin      = YMax;
                YMax      = SwapValue;
            }
            x = x0;
            while (true)
            {
                if (steep)
                {
                    retX = (y - Partition.OffsetX) / StepSize;
                    retY = (x - Partition.OffsetY) / StepSize;
                }
                else
                {
                    retX = (x - Partition.OffsetX) / StepSize;
                    retY = (y - Partition.OffsetY) / StepSize;
                }

                PartitionNode node = Partition.Nodes [retX * Partition.Count + retY];
                if (node.Count > 0)
                {
                    for (i = 0; i < node.Count; i++)
                    {
                        DidHit = false;

                        LSBody body = PhysicsManager.SimObjects [node [i]];
                        if (body.RaycastVersion != _Version && body.ID != ExceptionID)
                        {
                            body.RaycastVersion = _Version;
                            switch (body.Shape)
                            {
                            case ColliderType.Circle:
                                Projection = Vector2d.Dot(AxisX, AxisY, body.Position.x, body.Position.y);
                                TestMin    = Projection - body.Radius;
                                TestMax    = Projection + body.Radius;
                                if (TestMin < AxisMax)
                                {
                                    if (TestMax > AxisMin)
                                    {
                                        Projection = Vector2d.Dot(-AxisY, AxisX, body.Position.x, body.Position.y);
                                        TestMin    = Projection - body.Radius;
                                        TestMax    = Projection + body.Radius;
                                        if (PerpProj < TestMax && PerpProj > TestMin)
                                        {
                                            DidHit = true;
                                        }
                                    }
                                }
                                break;

                            case ColliderType.AABox:
                                if (AxisMin < body.XMax)
                                {
                                    if (AxisMax > body.XMin)
                                    {
                                        if (PerpProj < body.YMax)
                                        {
                                            if (PerpProj > body.YMin)
                                            {
                                                DidHit = true;
                                            }
                                        }
                                    }
                                }
                                break;
                            }
                            if (DidHit)
                            {
                                Hits.Add(body);
                                MadeContact = true;
                                break;
                            }
                        }
                    }
                }

                error = error - dy;
                if (error < 0)
                {
                    y     += ystep;
                    error += dx;
                }

                if (x >= x1)
                {
                    break;
                }
                x += StepSize;
            }
            return(MadeContact);
        }
Esempio n. 10
0
        public 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);
                if (PenetrationX > 0)
                {
                    PenetrationX = 0;
                }
            }
            else
            {
                PenetrationX = (circle.XMax - box.XMin);
                if (PenetrationX < 0)
                {
                    PenetrationX = 0;
                }
            }
            if (yMore)
            {
                PenetrationY = (circle.YMin - box.YMax);
                if (PenetrationY > 0)
                {
                    PenetrationY = 0;
                }
            }
            else
            {
                PenetrationY = (circle.YMax - box.YMin);
                if (PenetrationY < 0)
                {
                    PenetrationY = 0;
                }
            }


            xAbs = PenetrationX < 0 ? -PenetrationX : PenetrationX;
            yAbs = PenetrationY < 0 ? -PenetrationY : PenetrationY;
            if (xAbs > yAbs)
            {
                PenetrationX = 0;
            }
            else
            {
                PenetrationY = 0;
            }

            //Resolving
            if (Vector2d.Dot(PenetrationX, PenetrationY, circle.Velocity.x, circle.Velocity.y) < 0)
            {
                return;
            }

            circle.Position.x -= PenetrationX;            //(PenetrationX * Multiplier) >> FixedMath.SHIFT_AMOUNT;
            circle.Position.y -= PenetrationY;            //(PenetrationY * Multiplier) >> FixedMath.SHIFT_AMOUNT;

            if (LeCollisionType != CollisionType.Circle_AABox)
            {
                Mag          = FixedMath.Sqrt((PenetrationX * PenetrationX + PenetrationY * PenetrationY) >> FixedMath.SHIFT_AMOUNT);
                PenetrationX = (PenetrationX << FixedMath.SHIFT_AMOUNT) / Mag;
                PenetrationY = (PenetrationY << FixedMath.SHIFT_AMOUNT) / Mag;
            }
            else
            {
                if (PenetrationX != 0)
                {
                    PenetrationX = PenetrationX > 0 ? FixedMath.One : -FixedMath.One;
                }
                else if (PenetrationY != 0)
                {
                    PenetrationY = PenetrationY > 0 ? FixedMath.One : -FixedMath.One;
                }
            }

            circle.PositionChanged = true;
            circle.BuildBounds();
        }
        public bool Overlaps(FastList <Vector2d> outputIntersectionPoints)
        {
            outputIntersectionPoints.FastClear();
            //Checks if this object overlaps the line formed by p1 and p2
            switch (this.Shape)
            {
            case ColliderType.Circle:
            {
                bool overlaps = false;
                //Check if the circle completely fits between the line
                long projPos = this._position.Dot(cacheAxis.x, cacheAxis.y);
                //Circle withing bounds?
                if (projPos >= axisMin && projPos <= axisMax)
                {
                    long projPerp = this._position.Dot(cacheAxisNormal.x, cacheAxisNormal.y);
                    long perpDif  = (cacheProjPerp - projPerp);
                    long perpDist = perpDif.Abs();
                    if (perpDist <= _radius)
                    {
                        overlaps = true;
                    }
                    if (overlaps)
                    {
                        long sin = (perpDif);
                        long cos = FixedMath.Sqrt(_radius.Mul(_radius) - sin.Mul(sin));
                        if (cos == 0)
                        {
                            outputIntersectionPoints.Add((cacheAxis * projPos) + perpVector);
                        }
                        else
                        {
                            outputIntersectionPoints.Add(cacheAxis * (projPos - cos) + perpVector);
                            outputIntersectionPoints.Add(cacheAxis * (projPos + cos) + perpVector);
                        }
                    }
                }
                else
                {
                    //If not, check distances to points
                    long p1Dist = _position.FastDistance(cacheP1.x, cacheP2.y);
                    if (p1Dist <= this.FastRadius)
                    {
                        outputIntersectionPoints.Add(cacheP1);
                        overlaps = true;
                    }
                    long p2Dist = _position.FastDistance(cacheP2.x, cacheP2.y);
                    if (p2Dist <= this.FastRadius)
                    {
                        outputIntersectionPoints.Add(cacheP2);
                        overlaps = true;
                    }
                }
                return(overlaps);
            }
            break;

            case ColliderType.AABox:
            {
            }
            break;

            case ColliderType.Polygon:
            {
                bool intersected = false;


                for (int i = 0; i < this.Vertices.Length; i++)
                {
                    int      edgeIndex = i;
                    Vector2d pivot     = this.RealPoints [edgeIndex];
                    Vector2d edge      = this.Edges [edgeIndex];
                    long     proj1     = 0;
                    int      nextIndex = edgeIndex + 1 < this.RealPoints.Length ? edgeIndex + 1 : 0;
                    Vector2d nextPoint = RealPoints [nextIndex];
                    long     proj2     = (nextPoint - pivot).Dot(edge);

                    long min;
                    long max;
                    if (proj1 < proj2)
                    {
                        min = proj1;
                        max = proj2;
                    }
                    else
                    {
                        min = proj2;
                        max = proj1;
                    }

                    long lineProj1 = (cacheP1 - pivot).Dot(edge);
                    long lineProj2 = (cacheP2 - pivot).Dot(edge);

                    long lineMin;
                    long lineMax;
                    if (lineProj1 < lineProj2)
                    {
                        lineMin = lineProj1;
                        lineMax = lineProj2;
                    }
                    else
                    {
                        lineMin = lineProj2;
                        lineMax = lineProj1;
                    }
                    if (CollisionPair.CheckOverlap(min, max, lineMin, lineMax))
                    {
                        Vector2d edgeNorm      = this.EdgeNorms [edgeIndex];
                        long     normProj      = 0;
                        long     normLineProj1 = (cacheP1 - pivot).Dot(edgeNorm);
                        long     normLineProj2 = (cacheP2 - pivot).Dot(edgeNorm);

                        long normLineMin;
                        long normLineMax;

                        if (normLineProj1 < normLineProj2)
                        {
                            normLineMin = normLineProj1;
                            normLineMax = normLineProj2;
                        }
                        else
                        {
                            normLineMin = normLineProj2;
                            normLineMax = normLineProj1;
                        }

                        if (normProj >= normLineMin && normProj <= normLineMax)
                        {
                            long revProj1 = pivot.Dot(LSBody.cacheAxisNormal);
                            long revProj2 = nextPoint.Dot(cacheAxisNormal);

                            long revMin;
                            long revMax;
                            if (revProj1 < revProj2)
                            {
                                revMin = revProj1;
                                revMax = revProj2;
                            }
                            else
                            {
                                revMin = revProj2;
                                revMax = revProj1;
                            }

                            if (LSBody.cacheProjPerp >= revMin && LSBody.cacheProjPerp <= revMax)
                            {
                                intersected = true;
                                if (LSBody.calculateIntersections)
                                {
                                    long fraction         = normLineProj1.Abs().Div(normLineMax - normLineMin);
                                    long intersectionProj = FixedMath.Lerp(lineProj1, lineProj2, fraction);
                                    outputIntersectionPoints.Add(edge * intersectionProj + pivot);

                                    if (outputIntersectionPoints.Count == 2)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                return(intersected);
            }
            break;
            }
            return(false);
        }
Esempio n. 12
0
 public static long Dot(Vector2d a, Vector2d b)
 {
     return(a.Dot(b));
 }