Beispiel #1
0
        public void Move(List <IPolygon> polygons, Vector2 velocity)
        {
            Vector2 translation = velocity;

            foreach (Polygon polygon in polygons)
            {
                CollisionResult result = Simulate(polygon, velocity);

                if (result.WillIntersect && this.IsTangible && polygon.IsTangible)
                {
                    translation += result.MinimumTranslation;
                    //break;
                }

                if (result.AreIntersecting)
                {
                    this.OnCollide?.Invoke(this, polygon);

                    polygon.OnCollide?.Invoke(polygon, this);
                }
            }

            Position += translation;
        }
Beispiel #2
0
        /// <summary>
        /// Simulate collision between this polygon and another <paramref name="polygon"/> with <paramref name="velocity"/>
        /// </summary>
        /// <param name="polygon"></param>
        /// <param name="velocity"></param>
        /// <returns></returns>
        public CollisionResult Simulate(IPolygon polygon, Vector2 velocity)
        {
            CollisionResult result = new CollisionResult();

            result.AreIntersecting = true;
            result.WillIntersect   = true;

            int   edgeCountA      = this.Edges.Count;
            int   edgeCountB      = polygon.Edges.Count;
            float minimumInterval = float.PositiveInfinity;

            Vector2 translationAxis = Vector2.Zero;
            Vector2 edge            = Vector2.Zero;

            // loop through edges of both polygons
            for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
            {
                if (edgeIndex < edgeCountA)
                {
                    edge = this.Edges[edgeIndex];
                }
                else
                {
                    edge = polygon.Edges[edgeIndex - edgeCountA];
                }

                // find if the polygons are intersecting.
                // find the axis perpendicular to the current edge
                Vector2 axis = new Vector2(-edge.Y, edge.X);
                axis.Normalize();

                // find the projection of the axis
                float minA = 0, minB = 0, maxA = 0, maxB = 0;
                projectPolygon(axis, this, ref minA, ref maxA);
                projectPolygon(axis, polygon, ref minB, ref maxB);

                // check if projections are intersecting
                if (intervalDistance(minA, maxA, minB, maxB) > 0)
                {
                    result.AreIntersecting = false;
                }

                // find if polygons _will_ intersect
                float velocityProjection = Vector2.Dot(axis, velocity);

                // get the projection of this poly during movement
                if (velocityProjection < 0)
                {
                    minA += velocityProjection;
                }
                else
                {
                    maxA += velocityProjection;
                }

                // same test for new projection
                float interval           = intervalDistance(minA, maxA, minB, maxB);
                if (interval > 0)
                {
                    result.WillIntersect = false;
                }

                if (!result.AreIntersecting && !result.WillIntersect)
                {
                    break;
                }

                // check if the current interval is the minimum one
                interval = Math.Abs(interval);
                if (interval < minimumInterval)
                {
                    minimumInterval = interval;
                    translationAxis = axis;

                    Vector2 d = this.Center - polygon.Center;
                    if (Vector2.Dot(d, translationAxis) < 0)
                    {
                        translationAxis = -translationAxis;
                    }
                }
            }

            if (result.WillIntersect)
            {
                result.MinimumTranslation = translationAxis * minimumInterval;
            }

            return(result);
        }