Esempio n. 1
0
        private static void _rayCast(IPortalable placeable, IEnumerable<IPortal> portals, double movementLeft, IPortal portalPrevious, Action<EnterCallbackData, double> portalEnter, Settings settings, int count)
        {
            Transform2 begin = placeable.GetTransform();
            Transform2 velocity = placeable.GetVelocity().Multiply(settings.TimeScale);
            if (settings.MaxIterations <= count)
            {
                //If we run out of iterations before running out of movement, call _rayEnd with 0 movementLeft just to make sure the AdjustEnpoint setting is handled.
                _rayEnd(placeable, portals, 0, portalPrevious, settings, begin, velocity);
                return;
            }
            if (!placeable.IsPortalable)
            {
                _rayEnd(placeable, portals, movementLeft, portalPrevious, settings, begin, velocity);
                return;
            }
            double distanceMin = movementLeft;
            IPortal portalNearest = null;
            IntersectCoord intersectNearest = new IntersectCoord();
            LineF ray = new LineF(begin.Position, begin.Position + velocity.Position);
            foreach (IPortal p in portals)
            {
                if (!Portal.IsValid(p) || portalPrevious == p)
                {
                    continue;
                }

                LineF portalLine = new LineF(Portal.GetWorldVerts(p));
                IntersectCoord intersect = MathExt.LineLineIntersect(portalLine, ray, true);
                double distance = ((Vector2d)begin.Position - intersect.Position).Length;
                if (intersect.Exists && distance < distanceMin)
                {
                    distanceMin = distance;
                    portalNearest = p;
                    intersectNearest = intersect;
                }
            }
            if (portalNearest != null)
            {
                movementLeft -= distanceMin;

                double t = (velocity.Position.Length - movementLeft) / velocity.Position.Length;

                begin.Position = (Vector2)intersectNearest.Position;
                placeable.SetTransform(begin);
                Portal.Enter(portalNearest, placeable, (float)intersectNearest.TFirst, true);

                portalEnter?.Invoke(new EnterCallbackData(portalNearest, placeable, intersectNearest.TFirst), t);

                movementLeft *= Math.Abs(placeable.GetTransform().Size / begin.Size);
                _rayCast(placeable, portals, movementLeft, portalNearest.Linked, portalEnter, settings, count + 1);
            }
            else
            {
                _rayEnd(placeable, portals, movementLeft, portalPrevious, settings, begin, velocity);
            }
        }
Esempio n. 2
0
 private static void _rayEnd(IPortalable placeable, IEnumerable<IPortal> portals, double movementLeft, IPortal portalPrevious, Settings settings, Transform2 begin, Transform2 velocity)
 {
     begin.Position += velocity.Position.Normalized() * (float)movementLeft;
     if (settings.AdjustEndpoint)
     {
         /*After the end position of the ray has been determined, adjust it's position so that it isn't too close to
          * any portal.  Otherwise there is a risk of ambiguity as to which side of a portal the end point is on.*/
         begin = AddMargin(portals, portalPrevious, begin, velocity);
     }
     placeable.SetTransform(begin);
 }