コード例 #1
0
        /// <summary>
        /// Returns whether this instance collides against the argument Capsule2D.
        /// </summary>
        /// <param name="capsule">The Capsule2D to test collision against.</param>
        /// <returns>Whether collision has occurred.</returns>
        public bool CollideAgainst(Capsule2D capsule)
        {
            UpdateDependencies(TimeManager.CurrentTime);
            capsule.UpdateDependencies(TimeManager.CurrentTime);

            Circle circle = Capsule2D.CollisionCircle;

            circle.Position = capsule.Endpoint1Position;
            circle.Radius   = capsule.EndpointRadius;

            bool collision = circle.CollideAgainst(this);

            if (collision)
            {
                return(true);
            }

            circle.Position = capsule.Endpoint2Position;

            collision = circle.CollideAgainst(this);

            if (collision)
            {
                return(true);
            }

            Polygon polygon = Capsule2D.CollisionPolygon;

            float right = capsule.Scale - capsule.EndpointRadius;
            float top   = capsule.EndpointRadius;

            polygon.SetPoint(0, -right, top);
            polygon.SetPoint(1, right, top);
            polygon.SetPoint(2, right, -top);
            polygon.SetPoint(3, -right, -top);
            polygon.SetPoint(4, -right, top);

            polygon.Position       = capsule.Position;
            polygon.RotationMatrix = capsule.RotationMatrix;

            polygon.UpdateDependencies(TimeManager.CurrentTime);

            return(this.CollideAgainst(polygon));
        }
コード例 #2
0
        public bool CollideAgainstMove(Circle circle, float thisMass, float otherMass)
        {
#if DEBUG
            if (thisMass == 0 && otherMass == 0)
            {
                throw new ArgumentException("Both masses cannot be 0.  For equal masses pick a non-zero value");
            }
#endif
            if (circle.CollideAgainst(this))
            {
                Point circleCenter = new Point(circle.X, circle.Y);

                if (IsPointOnOrInside(ref circleCenter))
                {
                    double xDistanceToMoveCircle = 0;
                    double yDistanceToMoveCircle = 0;

                    float smallestDistance = float.PositiveInfinity;


                    if ((this.RepositionDirections & Geometry.RepositionDirections.Right) == Geometry.RepositionDirections.Right)
                    {
                        smallestDistance      = Right - circle.X;
                        xDistanceToMoveCircle = smallestDistance + circle.Radius;
                    }

                    if ((this.RepositionDirections & Geometry.RepositionDirections.Left) == Geometry.RepositionDirections.Left &&
                        circle.X - Left < smallestDistance)
                    {
                        smallestDistance      = circle.X - Left;
                        xDistanceToMoveCircle = -smallestDistance - circle.Radius;
                    }

                    if ((this.RepositionDirections & Geometry.RepositionDirections.Up) == Geometry.RepositionDirections.Up &&
                        Top - circle.Y < smallestDistance)
                    {
                        smallestDistance      = Top - circle.Y;
                        xDistanceToMoveCircle = 0;
                        yDistanceToMoveCircle = smallestDistance + circle.Radius;
                    }

                    if ((this.RepositionDirections & Geometry.RepositionDirections.Down) == Geometry.RepositionDirections.Down &&
                        circle.Y - Bottom < smallestDistance)
                    {
                        smallestDistance      = circle.Y - Bottom;
                        xDistanceToMoveCircle = 0;
                        yDistanceToMoveCircle = -smallestDistance - circle.Radius;
                    }

                    float amountToMoveThis = otherMass / (thisMass + otherMass);

                    mLastMoveCollisionReposition.X = (float)(-xDistanceToMoveCircle * amountToMoveThis);
                    mLastMoveCollisionReposition.Y = (float)(-yDistanceToMoveCircle * amountToMoveThis);

                    TopParent.X += mLastMoveCollisionReposition.X;
                    TopParent.Y += mLastMoveCollisionReposition.Y;

                    circle.LastMoveCollisionReposition.X = (float)(xDistanceToMoveCircle * (1 - amountToMoveThis));
                    circle.LastMoveCollisionReposition.Y = (float)(yDistanceToMoveCircle * (1 - amountToMoveThis));
                    circle.mLastCollisionTangent         = new Point(circle.LastMoveCollisionReposition.Y,
                                                                     -circle.LastMoveCollisionReposition.X);

                    circle.TopParent.Position.X += circle.LastMoveCollisionReposition.X;
                    circle.TopParent.Position.Y += circle.LastMoveCollisionReposition.Y;

                    ForceUpdateDependencies();
                    circle.ForceUpdateDependencies();

                    return(true);
                }
                else
                {
                    Segment collisionSegment = new Segment();
                    // top
                    Segment edge             = new Segment();
                    float   smallestDistance = float.PositiveInfinity;
#if FRB_MDX
                    Vector2 amountToMove = Vector2.Empty;
#else
                    Vector2 amountToMove = Vector2.Zero;
#endif
                    bool isAmountToMoveSet = false;

                    if ((this.RepositionDirections & Geometry.RepositionDirections.Up) == Geometry.RepositionDirections.Up)
                    {
                        bool shouldUseInfiniteSegment = (circleCenter.X < Position.X &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Left) != Geometry.RepositionDirections.Left) ||
                                                        (circleCenter.X > Position.X &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Right) != Geometry.RepositionDirections.Right);

                        if (shouldUseInfiniteSegment)
                        {
                            smallestDistance = Top + circle.Radius - circle.Position.Y;


                            isAmountToMoveSet = true;

                            amountToMove.X = 0;
                            amountToMove.Y = -smallestDistance;
                        }
                        else
                        {
                            // Maybe we can save by not calling "new"
                            edge = new Segment(
                                new Point(this.Left, this.Top),
                                new Point(this.Right, this.Top));
                            smallestDistance = edge.DistanceTo(circleCenter, out collisionSegment);
                        }
                    }

                    if ((this.RepositionDirections & Geometry.RepositionDirections.Down) == Geometry.RepositionDirections.Down)
                    {
                        bool shouldUseInfiniteSegment = (circleCenter.X < Position.X &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Left) != Geometry.RepositionDirections.Left) ||
                                                        (circleCenter.X > Position.X &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Right) != Geometry.RepositionDirections.Right);


                        if (shouldUseInfiniteSegment)
                        {
                            float candidate = Bottom - circle.Radius - circle.Position.Y;

                            if (System.Math.Abs(candidate) < System.Math.Abs(smallestDistance))
                            {
                                smallestDistance  = candidate;
                                isAmountToMoveSet = true;

                                amountToMove.X = 0;
                                amountToMove.Y = -smallestDistance;
                            }
                        }
                        else
                        {
                            // bottom
                            edge = new Segment(
                                new Point(Left, Bottom),
                                new Point(Right, Bottom));

                            if (edge.DistanceTo(circleCenter) < smallestDistance)
                            {
                                smallestDistance = (float)edge.DistanceTo(circleCenter, out collisionSegment);
                            }
                        }
                    }


                    if ((this.RepositionDirections & Geometry.RepositionDirections.Left) == Geometry.RepositionDirections.Left)
                    {
                        bool shouldUseInfiniteSegment = (circleCenter.Y < Position.Y &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Down) != Geometry.RepositionDirections.Down) ||
                                                        (circleCenter.Y > Position.Y &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Up) != Geometry.RepositionDirections.Up);

                        if (shouldUseInfiniteSegment)
                        {
                            float candidate = Left - circle.Radius - circle.Position.X;

                            if (System.Math.Abs(candidate) < System.Math.Abs(smallestDistance))
                            {
                                smallestDistance = candidate;

                                isAmountToMoveSet = true;
                                amountToMove.Y    = 0;
                                amountToMove.X    = -smallestDistance;
                            }
                        }
                        else
                        {
                            // left
                            edge = new Segment(
                                new Point(Left, Top),
                                new Point(Left, Bottom));
                            if (edge.DistanceTo(circleCenter) < smallestDistance)
                            {
                                smallestDistance = (float)edge.DistanceTo(circleCenter, out collisionSegment);
                            }
                        }
                    }

                    if ((this.RepositionDirections & Geometry.RepositionDirections.Right) == Geometry.RepositionDirections.Right)
                    {
                        bool shouldUseInfiniteSegment = (circleCenter.Y < Position.Y &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Down) != Geometry.RepositionDirections.Down) ||
                                                        (circleCenter.Y > Position.Y &&
                                                         (this.RepositionDirections & Geometry.RepositionDirections.Up) != Geometry.RepositionDirections.Up);

                        if (shouldUseInfiniteSegment)
                        {
                            float candidate = Right + circle.Radius - circle.Position.X;

                            if (System.Math.Abs(candidate) < System.Math.Abs(smallestDistance))
                            {
                                smallestDistance = candidate;

                                isAmountToMoveSet = true;
                                amountToMove.Y    = 0;
                                amountToMove.X    = -smallestDistance;
                            }
                        }
                        else
                        {
                            // right
                            edge = new Segment(
                                new Point(Right, Top),
                                new Point(Right, Bottom));
                            if (edge.DistanceTo(circleCenter) < smallestDistance)
                            {
                                smallestDistance = (float)edge.DistanceTo(circleCenter, out collisionSegment);
                                //				edgeClosestTo = "right";
                            }
                        }
                    }

                    if (smallestDistance <= circle.Radius)
                    {
                        float remainingDistance = (float)circle.Radius - smallestDistance;
                        if (!isAmountToMoveSet)
                        {
                            amountToMove = new Vector2((float)(collisionSegment.Point2.X - collisionSegment.Point1.X),
                                                       (float)(collisionSegment.Point2.Y - collisionSegment.Point1.Y));
                            amountToMove.Normalize();
                            amountToMove = amountToMove * remainingDistance;
                        }

                        float amountToMoveThis = otherMass / (thisMass + otherMass);

                        mLastMoveCollisionReposition.X = amountToMove.X * amountToMoveThis;
                        mLastMoveCollisionReposition.Y = amountToMove.Y * amountToMoveThis;

                        TopParent.X += mLastMoveCollisionReposition.X;
                        TopParent.Y += mLastMoveCollisionReposition.Y;

                        circle.LastMoveCollisionReposition.X = -amountToMove.X * (1 - amountToMoveThis);
                        circle.LastMoveCollisionReposition.Y = -amountToMove.Y * (1 - amountToMoveThis);

                        circle.TopParent.Position.X += circle.LastMoveCollisionReposition.X;
                        circle.TopParent.Position.Y += circle.LastMoveCollisionReposition.Y;

                        ForceUpdateDependencies();
                        circle.ForceUpdateDependencies();

                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            return(false);
        }
コード例 #3
0
 /// <summary>
 /// Returns whether this instance collides against the argument Circle.
 /// </summary>
 /// <param name="circle">The Circle to test collision against.</param>
 /// <returns>Whether collision has occurred.</returns>
 public bool CollideAgainst(Circle circle)
 {
     return(circle.CollideAgainst(this));
 }