Exemplo n.º 1
0
        public static bool TestPolygonVsPolygon(Polygon polygon1, Polygon polygon2, out ShapeCollision shapeCollision, bool flip = false)
        {
            if (!CheckPolygons(polygon1, polygon2, out ShapeCollision tmp1, flip) ||
                !CheckPolygons(polygon2, polygon1, out ShapeCollision tmp2, flip))
            {
                shapeCollision = new ShapeCollision();
                return(false);
            }

            ShapeCollision result;
            ShapeCollision other;

            if (System.Math.Abs(tmp1.Overlap) < System.Math.Abs(tmp2.Overlap))
            {
                result = tmp1;
                other  = tmp2;
            }
            else
            {
                result = tmp2;
                other  = tmp1;
            }

            result.OtherOverlap = other.Overlap;
            result.Separation   = other.Separation;
            result.Normal       = other.Normal;
            shapeCollision      = result;
            return(true);
        } //testPolygonVsPolygon
Exemplo n.º 2
0
        public override void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            if (SelectedGameObjects.Count > 0)
            {
                foreach (var selectedGameObject in SelectedGameObjects)
                {
                    if (SimulationGame.VisibleArea.Contains(selectedGameObject.Position))
                    {
                        var worldDrawPosition = Rectangle.Empty;

                        if (selectedGameObject is AmbientObject)
                        {
                            var gameObject = (AmbientObject)selectedGameObject;

                            worldDrawPosition = new Rectangle((int)(gameObject.Position.X - gameObject.GetObjectType().SpriteOrigin.X), (int)(gameObject.Position.Y - gameObject.GetObjectType().SpriteOrigin.Y), gameObject.GetObjectType().SpriteBounds.X, gameObject.GetObjectType().SpriteBounds.Y);
                        }
                        else if (selectedGameObject is AmbientHitableObject)
                        {
                            var gameObject = (AmbientHitableObject)selectedGameObject;

                            worldDrawPosition = new Rectangle((int)(gameObject.Position.X - gameObject.GetObjectType().SpriteOrigin.X), (int)(gameObject.Position.Y - gameObject.GetObjectType().SpriteOrigin.Y), gameObject.GetObjectType().SpriteBounds.X, gameObject.GetObjectType().SpriteBounds.Y);
                        }
                        else if (selectedGameObject is LivingEntity)
                        {
                            var gameObject = (LivingEntity)selectedGameObject;

                            worldDrawPosition = new Rectangle((int)(gameObject.Position.X - gameObject.GetObjectType().SpriteOrigin.X), (int)(gameObject.Position.Y - gameObject.GetObjectType().SpriteOrigin.Y), gameObject.GetObjectType().SpriteBounds.X, gameObject.GetObjectType().SpriteBounds.Y);
                        }

                        var uiPosition = SimulationGame.ConvertWorldPositionToUIPosition(worldDrawPosition.X, worldDrawPosition.Y);
                        SimulationGame.PrimitiveDrawer.Rectangle(new Rectangle((int)uiPosition.X, (int)uiPosition.Y, worldDrawPosition.Width, worldDrawPosition.Height), Color.Yellow);
                    }
                }
            }
            else if (SelectedBlockType != null)
            {
                var uiPosition = SimulationGame.ConvertWorldPositionToUIPosition(SelectedBlockPosition.X * WorldGrid.BlockSize.X, SelectedBlockPosition.Y * WorldGrid.BlockSize.Y);

                SimulationGame.PrimitiveDrawer.Rectangle(new Rectangle((int)uiPosition.X, (int)uiPosition.Y, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y), Color.Blue);
            }
            else if (SelectedWorldLink != null)
            {
                var uiPosition = SimulationGame.ConvertWorldPositionToUIPosition(SelectedWorldLink.FromBlock.X * WorldGrid.BlockSize.X, SelectedWorldLink.FromBlock.Y * WorldGrid.BlockSize.Y);

                SimulationGame.PrimitiveDrawer.Rectangle(new Rectangle((int)uiPosition.X, (int)uiPosition.Y, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y), Color.Orange);
            }

            if (startDragPosition != null)
            {
                var _startDragPosition  = startDragPosition ?? Point.Zero;
                var uiStartDragPosition = SimulationGame.ConvertWorldPositionToUIPosition(_startDragPosition.X, _startDragPosition.Y).ToPoint();
                var selectionRect       = ShapeCollision.ConvertLineToRect(uiStartDragPosition, SimulationGame.MouseState.Position);

                if (selectionRect.Width > 20 || selectionRect.Height > 20)
                {
                    SimulationGame.PrimitiveDrawer.Rectangle(selectionRect.ToXnaRectangle(), Color.White);
                }
            }
        }
        public ShapeCollision clone()
        {
            var clone = new ShapeCollision();

            clone.copy_from(this);

            return(clone);
        }
Exemplo n.º 4
0
        private void handleOnMouseMove(MouseMoveEvent mouseMoveEvent)
        {
            if (mouseMoveEvent.LeftButtonDown && startDragPosition == null)
            {
                startDragPosition = SimulationGame.RealWorldMousePosition.ToPoint();
            }

            if (mouseMoveEvent.LeftButtonDown == false && startDragPosition != null)
            {
                selectGameObjects(ShapeCollision.ConvertLineToRect(startDragPosition ?? Point.Zero, SimulationGame.RealWorldMousePosition.ToPoint()));
                startDragPosition = null;
            }
        }
 public void copy_from(ShapeCollision other)
 {
     overlap          = other.overlap;
     separationX      = other.separationX;
     separationY      = other.separationY;
     unitVectorX      = other.unitVectorX;
     unitVectorY      = other.unitVectorY;
     otherOverlap     = other.otherOverlap;
     otherSeparationX = other.otherSeparationX;
     otherSeparationY = other.otherSeparationY;
     otherUnitVectorX = other.otherUnitVectorX;
     otherUnitVectorY = other.otherUnitVectorY;
     shape1           = other.shape1;
     shape2           = other.shape2;
 }
    ////////////////private static bool Intersect(Vector2[] polygon1, Vector2[] polygon2)
    ////////////////{

    ////////////////    var pointsA = polygon1;
    ////////////////    var edgesA = BuildEdges(pointsA);
    ////////////////    int edgeCountA = edgesA.Length;
    ////////////////    var pointsB = polygon2;
    ////////////////    var edgesB = BuildEdges(pointsB);
    ////////////////    int edgeCountB = edgesB.Length;

    ////////////////    Vector2 edge;

    ////////////////    // Loop through all the edges of both polygons
    ////////////////    for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
    ////////////////    {
    ////////////////        if (edgeIndex < edgeCountA)
    ////////////////        {
    ////////////////            edge = edgesA[edgeIndex];
    ////////////////        }
    ////////////////        else
    ////////////////        {
    ////////////////            edge = edgesB[edgeIndex - edgeCountA];
    ////////////////        }

    ////////////////        // ===== 1. Find if the polygons are currently intersecting =====

    ////////////////        // Find the axis perpendicular to the current edge
    ////////////////        Vector2 axis = new Vector2(-edge.y, edge.x);
    ////////////////        axis.Normalize();


    ////////////////        // Find the projection of the polygon on the current axis
    ////////////////        float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
    ////////////////        ProjectPolygon(axis, pointsA, ref minA, ref maxA);
    ////////////////        ProjectPolygon(axis, pointsB, ref minB, ref maxB);

    ////////////////        // Check if the polygon projections are currentlty intersecting
    ////////////////        //if (IntervalDistance(minA, maxA, minB, maxB) <= 0.000001) return true;
    ////////////////        if (Intersects(minA, maxA, minB, maxB, true))
    ////////////////            return true;

    ////////////////    }
    ////////////////    return false;
    ////////////////}

    ////////////////private static Vector2[] BuildEdges(Vector2[] points/*,Vector2 offset*/)
    ////////////////{
    ////////////////    Vector2 p1;
    ////////////////    Vector2 p2;
    ////////////////    List<Vector2> edges = new List<Vector2>(points.Length - 1);
    ////////////////    for (int i = 0; i < points.Length; i++)
    ////////////////    {
    ////////////////        p1 = points[i];
    ////////////////        if (i + 1 >= points.Length)
    ////////////////        {
    ////////////////            p2 = points[0];
    ////////////////        }
    ////////////////        else
    ////////////////        {
    ////////////////            p2 = points[i + 1];
    ////////////////        }
    ////////////////        //edges.Add(offset+p2 - p1);
    ////////////////        edges.Add(p2 - p1);

    ////////////////    }

    ////////////////    return edges.ToArray();
    ////////////////}

    ////////////////// Calculate the distance between [minA, maxA] and [minB, maxB]
    ////////////////// The distance will be negative if the intervals overlap
    ////////////////private static float IntervalDistance(float minA, float maxA, float minB, float maxB)
    ////////////////{
    ////////////////    if (minA < minB)
    ////////////////    {
    ////////////////        return minB - maxA;
    ////////////////    }
    ////////////////    else
    ////////////////    {
    ////////////////        return minA - maxB;
    ////////////////    }
    ////////////////}

    ////////////////public static bool Intersects(float min1, float max1, float min2, float max2, bool strict, bool correctMinMax = true)
    ////////////////{
    ////////////////    if (correctMinMax)
    ////////////////    {
    ////////////////        float tmp1 = min1, tmp2 = max1;
    ////////////////        min1 = Math.Min(tmp1, tmp2);
    ////////////////        max1 = Math.Max(tmp1, tmp2);

    ////////////////        tmp1 = min2;
    ////////////////        tmp2 = max2;
    ////////////////        min2 = Math.Min(tmp1, tmp2);
    ////////////////        max2 = Math.Max(tmp1, tmp2);

    ////////////////    }

    ////////////////    if (strict)
    ////////////////        return (min1 <= min2 && max1 > min2) || (min2 <= min1 && max2 > min1);
    ////////////////    else
    ////////////////        return (min1 <= min2 && max1 >= min2) || (min2 <= min1 && max2 >= min1);
    ////////////////}

    ////////////////// Calculate the projection of a polygon on an axis and returns it as a [min, max] interval
    ////////////////private static void ProjectPolygon(Vector2 axis, Vector2[] polygon, ref float min, ref float max)
    ////////////////{
    ////////////////    // To project a point on an axis use the dot product
    ////////////////    //float d = Vector2.Dot(axis, polygon[0]);

    ////////////////    float d = DotProduct(axis, polygon[0]);
    ////////////////    min = d;
    ////////////////    max = d;
    ////////////////    for (int i = 0; i < polygon.Length; i++)
    ////////////////    {
    ////////////////        d = DotProduct(polygon[i], axis);
    ////////////////        if (d < min)
    ////////////////        {
    ////////////////            min = d;
    ////////////////        }
    ////////////////        else
    ////////////////        {
    ////////////////            if (d > max)
    ////////////////            {
    ////////////////                max = d;
    ////////////////            }
    ////////////////        }
    ////////////////    }
    ////////////////}

    ////////////////public static float DotProduct(Vector2 vectorA, Vector2 vectorB)
    ////////////////{
    ////////////////    return vectorA.x * vectorB.x + vectorA.y * vectorB.y;
    ////////////////}

    private static bool Intersect(Vector2[] polygon1, Vector2[] polygon2)
    {
        var into = new ShapeCollision();
        var flip = false;

        var tmp1 = checkPolygons(polygon1, polygon2, flip);
        var tmp2 = checkPolygons(polygon2, polygon1, !flip);

        if (tmp1 == null)
        {
            return(false);
        }

        if (tmp2 == null)
        {
            return(false);
        }

        ShapeCollision result = null;
        ShapeCollision other  = null;

        if (System.Math.Abs(tmp1.overlap) < System.Math.Abs(tmp2.overlap))
        {
            result = tmp1;
            other  = tmp2;
        }
        else
        {
            result = tmp2;
            other  = tmp1;
        }

        result.otherOverlap     = other.overlap;
        result.otherSeparationX = other.separationX;
        result.otherSeparationY = other.separationY;
        result.otherUnitVectorX = other.unitVectorX;
        result.otherUnitVectorY = other.unitVectorY;

        into.copy_from(result);
        result = other = null;
        //return Math.Abs(into.otherOverlap) > 0.00001;
        return(true);
    }
Exemplo n.º 7
0
        /** Internal api - test a circle against a circle */
        public static ShapeCollision testCircleVsCircle(Circle circleA, Circle circleB, bool flip = false)
        {
            var result  = new ShapeCollision();
            var circle1 = flip ? circleB : circleA;
            var circle2 = flip ? circleA : circleB;

            //add both radii together to get the colliding distance
            var totalRadius = circle1.transformedRadius + circle2.transformedRadius;
            //find the distance between the two circles using Pythagorean theorem. No square roots for optimization
            var distancesq = Util.vec_lengthsq(circle1.x - circle2.x, circle1.y - circle2.y);

            //if your distance is less than the totalRadius square(because distance is squared)
            if (distancesq < totalRadius * totalRadius)
            {
                //find the difference. Square roots are needed here.
                float difference = (float)(totalRadius - System.Math.Sqrt(distancesq));

                result.shape1 = circle1;
                result.shape2 = circle2;

                var unitVecX   = circle1.x - circle2.x;
                var unitVecY   = circle1.y - circle2.y;
                var unitVecLen = Util.vec_length(unitVecX, unitVecY);

                unitVecX = Util.vec_normalize(unitVecLen, unitVecX);
                unitVecY = Util.vec_normalize(unitVecLen, unitVecY);

                result.unitVectorX = unitVecX;
                result.unitVectorY = unitVecY;

                //find the movement needed to separate the circles
                result.separationX = result.unitVectorX * difference;
                result.separationY = result.unitVectorY * difference;

                //the magnitude of the overlap
                result.overlap = Util.vec_length(result.separationX, result.separationY);

                return(result);
            } //if distancesq < r^2

            return(null);
        }
Exemplo n.º 8
0
        public static ShapeCollision testPolygonVsPolygon(Polygon polygon1, Polygon polygon2, bool flip = false)
        {
            var output = new ShapeCollision();

            if ((tmp1 = checkPolygons(polygon1, polygon2, flip)) == null)
            {
                return(null);
            }
            //i dont need collision data

            /*
             *  if ( (tmp2 = checkPolygons(polygon2, polygon1, !flip)) == null) {
             *                  return null;
             *  }
             *
             *  ShapeCollision result = null;
             *          ShapeCollision other = null;
             *
             *  if (System.Math.Abs(tmp1.overlap) < System.Math.Abs(tmp2.overlap)) {
             *      result = tmp1;
             *      other = tmp2;
             *  } else {
             *      result = tmp2;
             *      other = tmp1;
             *  }
             *
             *  result.otherOverlap = other.overlap;
             *  result.otherSeparationX = other.separationX;
             *  result.otherSeparationY = other.separationY;
             *  result.otherUnitVectorX = other.unitVectorX;
             *  result.otherUnitVectorY = other.unitVectorY;
             *
             *          output.copy_from(result);
             *  result = other = null;
             */
            ShapeCollision result = tmp1;

            return(result);
        } //testPolygonVsPolygon
Exemplo n.º 9
0
        public static ShapeCollision testPolygonVsPolygon(Polygon polygon1, Polygon polygon2, bool flip = false)
        {
            var output = new ShapeCollision();

            if ((tmp1 = checkPolygons(polygon1, polygon2, flip)) == null)
            {
                return(null);
            }

            if ((tmp2 = checkPolygons(polygon2, polygon1, !flip)) == null)
            {
                return(null);
            }

            ShapeCollision result = null;
            ShapeCollision other  = null;

            if (System.Math.Abs(tmp1.overlap) < System.Math.Abs(tmp2.overlap))
            {
                result = tmp1;
                other  = tmp2;
            }
            else
            {
                result = tmp2;
                other  = tmp1;
            }

            result.otherOverlap     = other.overlap;
            result.otherSeparationX = other.separationX;
            result.otherSeparationY = other.separationY;
            result.otherUnitVectorX = other.unitVectorX;
            result.otherUnitVectorY = other.unitVectorY;

            output.copy_from(result);
            result = other = null;

            return(result);
        }     //testPolygonVsPolygon
Exemplo n.º 10
0
        /** Internal api - test a circle against a circle */
        public static bool TestCircleVsCircle(Circle circleA, Circle circleB, out ShapeCollision shapeCollision, bool flip = false)
        {
            shapeCollision = new ShapeCollision();
            Circle circle1 = flip ? circleB : circleA;
            Circle circle2 = flip ? circleA : circleB;

            //add both radii together to get the colliding distance
            float totalRadius = circle1.TransformedRadius + circle2.TransformedRadius;
            //find the distance between the two circles using Pythagorean theorem. No square roots for optimization
            float distancesq = (circle1.Position - circle2.Position).LengthSquared();

            //if your distance is less than the totalRadius square(because distance is squared)
            if (distancesq < totalRadius * totalRadius)
            {
                //find the difference. Square roots are needed here.
                float difference = (float)(totalRadius - System.Math.Sqrt(distancesq));

                shapeCollision.Shape1 = circle1;
                shapeCollision.Shape2 = circle2;

                Vector2 normal = circle1.Position - circle2.Position;
                normal.Normalize();

                shapeCollision.Normal = normal;

                //find the movement needed to separate the circles
                shapeCollision.Separation *= difference;

                //the magnitude of the overlap
                shapeCollision.Overlap = shapeCollision.Separation.Length();

                return(true);
            } //if distancesq < r^2

            return(false);
        }
Exemplo n.º 11
0
 public override bool CollidesWithCircle(Circle circle, out ShapeCollision shapeCollision, bool flip = false)
 => Sat2D.TestCircleVsCircle(this, circle, out shapeCollision, flip);
Exemplo n.º 12
0
        /** Internal api - test a circle against a polygon */
        public static bool TestCircleVsPolygon(Circle circle, Polygon polygon, out ShapeCollision shapeCollision, bool flip = false)
        {
            shapeCollision = new ShapeCollision();
            var verts = polygon.TransformedVertices;

            float   testDistance = float.MaxValue;
            Vector2 closest      = Vector2.Zero;

            for (int i = 0; i < verts.Count; i++)
            {
                float distance = (circle.Position - verts[i]).LengthSquared();

                if (distance < testDistance)
                {
                    testDistance = distance;
                    closest      = verts[i];
                }
            }

            Vector2 normalAxis = closest - circle.Position;

            normalAxis.Normalize();

            //project all its points, 0 outside the loop
            float test = 0.0f;
            float min1 = Vector2.Dot(normalAxis, verts[0]);
            float max1 = min1;

            for (int j = 1; j < verts.Count; j++)
            {
                test = Vector2.Dot(normalAxis, verts[j]);
                if (test < min1)
                {
                    min1 = test;
                }
                if (test > max1)
                {
                    max1 = test;
                }
            }

            // project the circle
            float max2   = circle.TransformedRadius;
            float min2   = -circle.TransformedRadius;
            float offset = Vector2.Dot(normalAxis, -circle.Position);

            min1 += offset;
            max1 += offset;

            float test1 = min1 - max2;
            float test2 = min2 - max1;

            //if either test is greater than 0, there is a gap, we can give up now.
            if (test1 > 0 || test2 > 0)
            {
                return(false);
            }

            // circle distance check
            float distMin = -(max2 - min1);

            if (flip)
            {
                distMin *= -1;
            }

            shapeCollision.Overlap = distMin;
            shapeCollision.Normal  = normalAxis;
            float closestDist = System.Math.Abs(distMin);

            // find the normal axis for each point and project
            for (int i = 0; i < verts.Count; i++)
            {
                normalAxis = FindNormalAxis(verts, i);
                normalAxis.Normalize();

                // project the polygon(again? yes, circles vs. polygon require more testing...)
                min1 = Vector2.Dot(normalAxis, verts[0]);
                max1 = min1; //set max and min

                //project all the other points(see, cirlces v. polygons use lots of this...)
                for (int j = 1; j < verts.Count; j++)
                {
                    test = Vector2.Dot(normalAxis, verts[j]);
                    if (test < min1)
                    {
                        min1 = test;
                    }
                    if (test > max1)
                    {
                        max1 = test;
                    }
                }

                // project the circle(again)
                max2 = circle.TransformedRadius;  //max is radius
                min2 = -circle.TransformedRadius; //min is negative radius

                //offset points
                offset = Vector2.Dot(normalAxis, -circle.Position);
                min1  += offset;
                max1  += offset;

                // do the test, again
                test1 = min1 - max2;
                test2 = min2 - max1;

                //failed.. quit now
                if (test1 > 0 || test2 > 0)
                {
                    return(false);
                }

                distMin = -(max2 - min1);
                if (flip)
                {
                    distMin *= -1;
                }

                if (System.Math.Abs(distMin) < closestDist)
                {
                    shapeCollision.Normal  = normalAxis;
                    shapeCollision.Overlap = distMin;
                    closestDist            = System.Math.Abs(distMin);
                }
            } //for

            //if you made it here, there is a collision!!!!!

            if (flip)
            {
                shapeCollision.Shape1 = polygon;
                shapeCollision.Shape2 = circle;
            }
            else
            {
                shapeCollision.Shape1 = circle;
                shapeCollision.Shape2 = polygon;
            }

            shapeCollision.Separation *= shapeCollision.Overlap;

            if (!flip)
            {
                shapeCollision.Normal = -shapeCollision.Normal;
            }

            return(true);
        }
Exemplo n.º 13
0
        /** Internal api - implementation details for testPolygonVsPolygon */
        public static ShapeCollision checkPolygons(Polygon polygon1, Polygon polygon2, bool flip = false)
        {
            var result = new ShapeCollision();

            // TODO: This is unused, check original source
            var test1   = 0.0f;
            var test2   = 0.0f;
            var testNum = 0.0f;
            var min1    = 0.0f;
            var max1    = 0.0f;
            var min2    = 0.0f;
            var max2    = 0.0f;
            var closest = float.MaxValue;

            var axisX  = 0.0f;
            var axisY  = 0.0f;
            var verts1 = polygon1.transformedVertices;
            var verts2 = polygon2.transformedVertices;

            var count1 = verts1.Length;
            var count2 = verts2.Length;

            // loop to begin projection
            for (var i = 0; i < count1; i++)
            {
                axisX = findNormalAxisX(verts1, i);
                axisY = findNormalAxisY(verts1, i);
                var aLen = Util.vec_length(axisX, axisY);
                axisX = Util.vec_normalize(aLen, axisX);
                axisY = Util.vec_normalize(aLen, axisY);

                // project polygon1
                min1 = Util.vec_dot(axisX, axisY, verts1[0].x, verts1[0].y);
                max1 = min1;

                for (var j = 1; j < count1; j++)
                {
                    testNum = Util.vec_dot(axisX, axisY, verts1[j].x, verts1[j].y);
                    if (testNum < min1)
                    {
                        min1 = testNum;
                    }
                    if (testNum > max1)
                    {
                        max1 = testNum;
                    }
                }

                // project polygon2
                min2 = Util.vec_dot(axisX, axisY, verts2[0].x, verts2[0].y);
                max2 = min2;

                for (var j = 1; j < count2; j++)
                {
                    testNum = Util.vec_dot(axisX, axisY, verts2[j].x, verts2[j].y);
                    if (testNum < min2)
                    {
                        min2 = testNum;
                    }
                    if (testNum > max2)
                    {
                        max2 = testNum;
                    }
                }

                test1 = min1 - max2;
                test2 = min2 - max1;

                if (test1 > 0 || test2 > 0)
                {
                    return(null);
                }

                var distMin = -(max2 - min1);
                if (flip)
                {
                    distMin *= -1;
                }

                if (System.Math.Abs(distMin) < closest)
                {
                    result.unitVectorX = axisX;
                    result.unitVectorY = axisY;
                    result.overlap     = distMin;
                    closest            = System.Math.Abs(distMin);
                }
                break;
            }

            result.shape1      = flip ? polygon2 : polygon1;
            result.shape2      = flip ? polygon1 : polygon2;
            result.separationX = -result.unitVectorX * result.overlap;
            result.separationY = -result.unitVectorY * result.overlap;

            if (flip)
            {
                result.unitVectorX = -result.unitVectorX;
                result.unitVectorY = -result.unitVectorY;
            }

            return(result);
        }
Exemplo n.º 14
0
        /** Internal api - test a circle against a polygon */
        public static ShapeCollision testCircleVsPolygon(Circle circle, Polygon polygon, bool flip = false)
        {
            var result = new ShapeCollision();
            var verts  = polygon.transformedVertices;

            var circleX = circle.x;
            var circleY = circle.y;

            float testDistance = float.MaxValue;
            var   distance     = 0.0f;
            var   closestX     = 0.0f;
            var   closestY     = 0.0f;

            for (var i = 0; i < verts.Length; i++)
            {
                distance = Util.vec_lengthsq(circleX - verts[i].x, circleY - verts[i].y);

                if (distance < testDistance)
                {
                    testDistance = distance;
                    closestX     = verts[i].x;
                    closestY     = verts[i].y;
                }
            }

            var normalAxisX = closestX - circleX;
            var normalAxisY = closestY - circleY;
            var normAxisLen = Util.vec_length(normalAxisX, normalAxisY);

            normalAxisX = Util.vec_normalize(normAxisLen, normalAxisX);
            normalAxisY = Util.vec_normalize(normAxisLen, normalAxisY);

            //project all its points, 0 outside the loop
            var test = 0.0f;
            var min1 = Util.vec_dot(normalAxisX, normalAxisY, verts[0].x, verts[0].y);
            var max1 = min1;

            for (var j = 1; j < verts.Length; j++)
            {
                test = Util.vec_dot(normalAxisX, normalAxisY, verts[j].x, verts[j].y);
                if (test < min1)
                {
                    min1 = test;
                }
                if (test > max1)
                {
                    max1 = test;
                }
            }

            // project the circle
            var max2   = circle.transformedRadius;
            var min2   = -circle.transformedRadius;
            var offset = Util.vec_dot(normalAxisX, normalAxisY, -circleX, -circleY);

            min1 += offset;
            max1 += offset;

            var test1 = min1 - max2;
            var test2 = min2 - max1;

            //if either test is greater than 0, there is a gap, we can give up now.
            if (test1 > 0 || test2 > 0)
            {
                return(null);
            }

            // circle distance check
            var distMin = -(max2 - min1);

            if (flip)
            {
                distMin *= -1;
            }

            result.overlap     = distMin;
            result.unitVectorX = normalAxisX;
            result.unitVectorY = normalAxisY;
            var closest = System.Math.Abs(distMin);

            // find the normal axis for each point and project
            for (var i = 0; i < verts.Length; i++)
            {
                normalAxisX = findNormalAxisX(verts, i);
                normalAxisY = findNormalAxisY(verts, i);
                var aLen = Util.vec_length(normalAxisX, normalAxisY);
                normalAxisX = Util.vec_normalize(aLen, normalAxisX);
                normalAxisY = Util.vec_normalize(aLen, normalAxisY);

                // project the polygon(again? yes, circles vs. polygon require more testing...)
                min1 = Util.vec_dot(normalAxisX, normalAxisY, verts[0].x, verts[0].y);
                max1 = min1; //set max and min

                //project all the other points(see, cirlces v. polygons use lots of this...)
                for (var j = 1; j < verts.Length; j++)
                {
                    test = Util.vec_dot(normalAxisX, normalAxisY, verts[j].x, verts[j].y);
                    if (test < min1)
                    {
                        min1 = test;
                    }
                    if (test > max1)
                    {
                        max1 = test;
                    }
                }

                // project the circle(again)
                max2 = circle.transformedRadius;  //max is radius
                min2 = -circle.transformedRadius; //min is negative radius

                //offset points
                offset = Util.vec_dot(normalAxisX, normalAxisY, -circleX, -circleY);
                min1  += offset;
                max1  += offset;

                // do the test, again
                test1 = min1 - max2;
                test2 = min2 - max1;

                //failed.. quit now
                if (test1 > 0 || test2 > 0)
                {
                    return(null);
                }

                distMin = -(max2 - min1);
                if (flip)
                {
                    distMin *= -1;
                }

                if (System.Math.Abs(distMin) < closest)
                {
                    result.unitVectorX = normalAxisX;
                    result.unitVectorY = normalAxisY;
                    result.overlap     = distMin;
                    closest            = System.Math.Abs(distMin);
                }
            } //for

            //if you made it here, there is a collision!!!!!

            if (flip)
            {
                result.shape1 = polygon;
                result.shape2 = circle;
            }
            else
            {
                result.shape1 = circle;
                result.shape2 = polygon;
            }

            result.separationX = result.unitVectorX * result.overlap;
            result.separationY = result.unitVectorY * result.overlap;

            if (!flip)
            {
                result.unitVectorX = -result.unitVectorX;
                result.unitVectorY = -result.unitVectorY;
            }

            return(result);
        }
Exemplo n.º 15
0
 public override bool CollidesWithPolygon(Polygon polygon, out ShapeCollision shapeCollision, bool flip = false)
 => Sat2D.TestCircleVsPolygon(this, polygon, out shapeCollision, flip);
Exemplo n.º 16
0
    private static ShapeCollision checkPolygons(Vector2[] polygon1, Vector2[] polygon2, bool flip = false)
    {
        var result = new ShapeCollision();

        // TODO: This is unused, check original source
        var offset  = 0.0f;
        var test1   = 0.0f;
        var test2   = 0.0f;
        var testNum = 0.0f;
        var min1    = 0.0f;
        var max1    = 0.0f;
        var min2    = 0.0f;
        var max2    = 0.0f;
        var closest = float.MaxValue;

        var axisX  = 0.0f;
        var axisY  = 0.0f;
        var verts1 = polygon1;
        var verts2 = polygon2;


        var founded = false;

        // loop to begin projection
        for (var i = 0; i < verts1.Length; i++)
        {
            axisX = findNormalAxisX(verts1, i);
            axisY = findNormalAxisY(verts1, i);
            var aLen = vec_length(axisX, axisY);
            axisX = vec_normalize(aLen, axisX);
            axisY = vec_normalize(aLen, axisY);

            // project polygon1
            min1 = vec_dot(axisX, axisY, verts1[0].x, verts1[0].y);
            max1 = min1;

            for (var j = 1; i < verts1.Length; i++)
            {
                testNum = vec_dot(axisX, axisY, verts1[j].x, verts1[j].y);
                if (testNum < min1)
                {
                    min1 = testNum;
                }
                if (testNum > max1)
                {
                    max1 = testNum;
                }
            }

            // project polygon2
            min2 = vec_dot(axisX, axisY, verts2[0].x, verts2[0].y);
            max2 = min2;

            for (var j = 1; i < verts2.Length; i++)
            {
                testNum = vec_dot(axisX, axisY, verts2[j].x, verts2[j].y);
                if (testNum < min2)
                {
                    min2 = testNum;
                }
                if (testNum > max2)
                {
                    max2 = testNum;
                }
            }

            test1 = min1 - max2;
            test2 = min2 - max1;

            if (test1 > 0 || test2 > 0)
            {
                return(null);
            }

            //if (test1 > 0 || test2 > 0) continue;
            //founded = true;
            var distMin = -(max2 - min1);
            if (flip)
            {
                distMin *= -1;
            }

            if (System.Math.Abs(distMin) < closest)
            {
                result.unitVectorX = axisX;
                result.unitVectorY = axisY;
                result.overlap     = distMin;
                closest            = System.Math.Abs(distMin);
            }
        }

        //if (!founded)
        //    return null;

        result.shape1      = flip ? polygon2 : polygon1;
        result.shape2      = flip ? polygon1 : polygon2;
        result.separationX = -result.unitVectorX * result.overlap;
        result.separationY = -result.unitVectorY * result.overlap;

        if (flip)
        {
            result.unitVectorX = -result.unitVectorX;
            result.unitVectorY = -result.unitVectorY;
        }

        return(result);
    }
Exemplo n.º 17
0
 public override bool CollidesWith(Shape shape, out ShapeCollision shapeCollision)
 => shape.CollidesWithCircle(this, out shapeCollision, true);
Exemplo n.º 18
0
 public override bool CollidesWithCircle(Circle circle, out ShapeCollision shapeCollision, bool flip = false)
 => Sat2D.TestCircleVsPolygon(circle, this, out shapeCollision, !flip);