Пример #1
0
        /*public CollisionResult CollideCircleWithEdgeAtTime(Circle circle, Vector2 I, Vector2 J, out double t)
         * {
         *  t = -1;
         *
         *  // Circle moves along path MN
         *  Vector2 M = circle.Position;
         *  Vector2 N = circle.Position + circle.Velocity;
         *  Vector2 MN = circle.Velocity;
         *
         *  double timeOfIntersection = -1;
         *
         *  if (!PhysicsObject.TimeOfIntersection(M, N, I, J, out timeOfIntersection, out double uCA)) return CollisionResult.None;
         *
         *  // The first colliding edge, in vector form
         *  Vector2 IJ = J - I;
         *
         *  // Angle between MN and IJ
         *  double a = Math.Atan2((MN.X * IJ.Y - MN.Y * IJ.X), Vector2.Dot(MN, IJ));
         *
         *  // Distance between center of circle and point of intersection at time t
         *  double distCenterToIntersection = Math.Abs(circle.Radius / Math.Sin(a));
         *
         *  // Report the actual time of collision given the circle's radius
         *  t = timeOfIntersection - (distCenterToIntersection / MN.Length());
         *
         *  if (t >= 0 && t <= 1)
         *  {
         *      // First two parameters are zero since we don't need to report collision info for the triangle itself
         *      //TODO: new velocity for circle is more complex than just Vector2.Negate(MN)
         *      return new CollisionResult(Vector2.Zero, Vector2.Zero, M + (float)(t - 0.01) * MN, Vector2.Negate(MN));
         *  }
         *
         *
         *  return CollisionResult.None;
         * }*/

        public CollisionResult CollideCircleWithEdgeAtTime(float s, Circle circle, Vector2 I, Vector2 J, out double t)
        {
            t = -1; //arbitrary error case

            // Circle moves along path MN
            Vector2 M  = circle.Position;
            Vector2 N  = circle.Position + circle.Velocity * s;
            Vector2 MN = N - M;

            // Collide with IJ translated by the normal of the circle's radius in length
            Vector2 IJ     = J - I;
            Vector2 normIJ = new Vector2(IJ.Y, -IJ.X); //negate the Y value because the edge runs clockwise

            normIJ.Normalize();

            double timeOfEdgeIntersection = -1;

            if (Vector2.Dot(normIJ, MN) <= 0) // Only collide edge if we are moving toward it
            {
                Vector2 scaledNormIJ = normIJ * circle.Radius;
                Vector2 P            = I + scaledNormIJ;
                Vector2 Q            = J + scaledNormIJ;

                timeOfEdgeIntersection = -1;
                bool intersectsEdge = PhysicsObject.TimeOfIntersection(M, N, P, Q, out timeOfEdgeIntersection, out double u);
                if (!intersectsEdge || u < 0 || u > 1)
                {
                    timeOfEdgeIntersection = -1;                                    // Invalid intersections
                }
            }

            // Collide circle as point with a new circle with center I and the same radius as circle (corner circle)
            //TODO: we shouldn't create an object every time - create a struct circle representation or equivalent method
            Circle point = new Circle()
            {
                Position = circle.Position, Velocity = circle.Velocity
            };
            Circle corner = new Circle()
            {
                Position = I, Radius = circle.Radius
            };
            double          timeOfCornerIntersection = -1;
            CollisionResult cornerCollisionResult    = point.CollideCircleAtTime(s, corner, out timeOfCornerIntersection);

            // Earliest wins
            CircleEdgeCollision first = FirstCircleEdgeCollision(timeOfEdgeIntersection, timeOfCornerIntersection);

            if (first == CircleEdgeCollision.None)
            {
                return(CollisionResult.None);                                   // No valid times
            }
            Vector2 normMN    = Vector2.Normalize(MN);
            Vector2 negNormMN = Vector2.Negate(normMN);

            if (first == CircleEdgeCollision.Edge)
            {
                t = timeOfEdgeIntersection;
                Vector2 newCirclePos = M + (float)t * MN + normIJ * SEPARATION;
                Vector2 newCircleVel = (2 * Vector2.Dot(normIJ, negNormMN) * normIJ - negNormMN) * circle.Velocity.Length();
                return(new CollisionResult(Vector2.Zero, Vector2.Zero, newCirclePos, newCircleVel));
            }
            else
            {
                t = timeOfCornerIntersection;
                //Vector2 newCirclePos = M + (float)t * MN - 0 * normMN; //Separation of .5 unit
                //Vector2 newCircleVel = Vector2.Normalize(newCirclePos - I) * circle.Velocity.Length();

                Vector2 newCirclePos = cornerCollisionResult.PositionA;
                Vector2 newCircleVel = cornerCollisionResult.VelocityA;

                newCirclePos += Vector2.Normalize(newCirclePos - I) * SEPARATION;
                return(new CollisionResult(Vector2.Zero, Vector2.Zero, newCirclePos, newCircleVel));
            }
        }