コード例 #1
0
 private static bool IsIncluded(HitDetectionOptions options, IRectangularF obj)
 {
     if (options.Exclusions == null)
     {
         return(true);
     }
     else
     {
         return(options.Exclusions.Contains(obj) == false);
     }
 }
コード例 #2
0
        public static HitPrediction PredictHit(HitDetectionOptions options)
        {
            HitPrediction prediction = new HitPrediction();

            var left         = Math.Min(options.MovingObject.Left, options.MovingObject.Left + options.Dx);
            var top          = Math.Min(options.MovingObject.Top, options.MovingObject.Top + options.Dy);
            var right        = Math.Max(options.MovingObject.Left + options.MovingObject.Width, options.MovingObject.Left + options.MovingObject.Width + options.Dx);
            var bottom       = Math.Max(options.MovingObject.Top + options.MovingObject.Height, options.MovingObject.Top + options.MovingObject.Height + options.Dy);
            var relevantArea = RectangularF.Create(left, top, right - left, bottom - top);

            var effectiveObstacles = options.Obstacles.Where(o => o.Touches(relevantArea)).ToList();

            if (options.Dx == 0 && options.Dy == 0)
            {
                prediction.Direction = Direction.None;
                prediction.Type      = HitType.None;
                return(prediction);
            }

            var endPoint = RectangularF.Create(options.MovingObject.Left + options.Dx, options.MovingObject.Top + options.Dy, options.MovingObject.Width, options.MovingObject.Height);
            var angle    = options.MovingObject.CalculateAngleTo(endPoint);
            var d        = endPoint.CalculateDistanceTo(options.MovingObject);

            for (var dPrime = options.Precision; dPrime < d; dPrime += options.Precision)
            {
                var testLocation = options.MovingObject.Center().MoveTowards(angle, dPrime);
                var testArea     = RectangularF.Create(testLocation.Left - options.MovingObject.Width / 2, testLocation.Top - options.MovingObject.Height / 2, options.MovingObject.Width, options.MovingObject.Height);
                var obstacleHit  = effectiveObstacles.Where(o => IsIncluded(options, o) && o.Touches(testArea) == true).FirstOrDefault();

                if (obstacleHit != null)
                {
                    return(new HitPrediction()
                    {
                        Type = HitType.Obstacle,
                        ObstacleHit = obstacleHit
                    });
                }
            }

            var obstacleHitFinal = effectiveObstacles.Where(o => IsIncluded(options, o) && o.Touches(endPoint) == true).FirstOrDefault();

            if (obstacleHitFinal != null)
            {
                return(new HitPrediction()
                {
                    Type = HitType.Obstacle,
                    ObstacleHit = obstacleHitFinal
                });
            }

            prediction.Type = HitType.None;
            return(prediction);
        }
コード例 #3
0
        public static ICollider GetLineOfSightObstruction(this ICollider from, ICollider to, IEnumerable <ICollider> obstacles, CastingMode castingMode = CastingMode.Rough)
        {
            var options = new HitDetectionOptions(from, obstacles.Union(new[] { to }));

            options.Mode       = castingMode;
            options.Angle      = options.MovingObject.CalculateAngleTo(to.Bounds);
            options.Visibility = 3 * options.MovingObject.CalculateDistanceTo(to.Bounds);

            var prediction = PredictHit(options);

            if (prediction.Type == HitType.None)
            {
                return(null);
            }
            else
            {
                var obstacleHit = prediction.ColliderHit;
                return(obstacleHit == to ? null : obstacleHit);
            }
        }
コード例 #4
0
 public static HitPrediction PredictHit(HitDetectionOptions options)
 {
     return(PredictHit(options.MovingObject, options.Obstacles.ToArray(), options.Angle, options.Colliders, options.Visibility, options.Mode, options.EdgesHitOutput, options.ObstacleBufferLength));
 }
コード例 #5
0
ファイル: HitDetection.cs プロジェクト: jiaw37/PowerArgs
        public static HitPrediction PredictHit(HitDetectionOptions options)
        {
            HitPrediction prediction = new HitPrediction();

            prediction.LKG = options.MovingObject.CopyBounds().TopLeft();
            prediction.MovingObjectPosition = options.MovingObject.CopyBounds();
            prediction.Visibility           = options.Visibility;
            if (options.Visibility == 0)
            {
                prediction.Direction = Direction.None;
                prediction.Type      = HitType.None;
                return(prediction);
            }


            var mov = options.MovingObject;

            List <Edge> rays;

            if (options.Mode == CastingMode.Precise)
            {
                rays = new List <Edge>()
                {
                    new Edge()
                    {
                        From = mov.TopLeft(), To = mov.TopLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.TopRight(), To = mov.TopRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomLeft(), To = mov.BottomLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomRight(), To = mov.BottomRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                };

                var granularity = .5f;

                for (var x = mov.Left + granularity; x < mov.Left + mov.Width; x += granularity)
                {
                    var top = LocationF.Create(x, mov.Top);
                    var bot = LocationF.Create(x, mov.Bottom());

                    rays.Add(new Edge()
                    {
                        From = top, To = top.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                    rays.Add(new Edge()
                    {
                        From = bot, To = bot.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                }

                for (var y = mov.Top + granularity; y < mov.Top + mov.Height; y += granularity)
                {
                    var left  = LocationF.Create(mov.Left, y);
                    var right = LocationF.Create(mov.Right(), y);

                    rays.Add(new Edge()
                    {
                        From = left, To = left.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                    rays.Add(new Edge()
                    {
                        From = right, To = right.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                }
            }
            else if (options.Mode == CastingMode.Rough)
            {
                var center = options.MovingObject.Center();
                rays = new List <Edge>()
                {
                    new Edge()
                    {
                        From = mov.TopLeft(), To = mov.TopLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.TopRight(), To = mov.TopRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomLeft(), To = mov.BottomLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomRight(), To = mov.BottomRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = center, To = center.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    }
                };
            }
            else if (options.Mode == CastingMode.SingleRay)
            {
                var center = options.MovingObject.Center();
                rays = new List <Edge>()
                {
                    new Edge()
                    {
                        From = center, To = center.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    }
                };
            }
            else
            {
                throw new NotSupportedException("Unknown mide: " + options.Mode);
            }

            var           closestIntersectionDistance = float.MaxValue;
            IRectangularF closestIntersectingElement  = null;
            var           closestEdgeIndex            = -1;
            var           effectiveObstacles          = options.Obstacles.ToArray();

            for (var i = 0; i < effectiveObstacles.Length; i++)
            {
                var obstacle = effectiveObstacles[i];
                for (var j = 0; j < obstacle.Edges.Length; j++)
                {
                    var edge = obstacle.Edges[j];
                    for (var k = 0; k < rays.Count; k++)
                    {
                        var ray          = rays[k];
                        var intersection = FindIntersectionPoint(ray, edge);
                        if (intersection != null)
                        {
                            var d = ray.From.CalculateDistanceTo(intersection);
                            if (d < closestIntersectionDistance && d <= options.Visibility)
                            {
                                closestIntersectionDistance = d;
                                closestIntersectingElement  = obstacle;
                                closestEdgeIndex            = j;
                            }
                        }
                    }
                }
            }

            if (closestIntersectingElement != null)
            {
                prediction.ObstacleHit = closestIntersectingElement;
                prediction.LKGD        = closestIntersectionDistance - .1f;
                prediction.LKG         = options.MovingObject.MoveTowards(options.Angle, prediction.LKGD, normalized: false).TopLeft();
                prediction.Type        = HitType.Obstacle;
                prediction.EdgeIndex   = closestEdgeIndex;
            }

            return(prediction);
        }
コード例 #6
0
ファイル: HitDetection.cs プロジェクト: BlackFrog1/PowerArgs
        public static HitPrediction PredictHit(HitDetectionOptions options)
        {
            HitPrediction prediction = new HitPrediction();

            prediction.MovingObjectPosition = options.MovingObject.CopyBounds();
            prediction.Visibility           = options.Visibility;
            if (options.Visibility == 0)
            {
                prediction.Direction = Direction.None;
                prediction.Type      = HitType.None;
                return(prediction);
            }


            var effectiveObstacles = options.Obstacles.Where(o => o.CalculateDistanceTo(options.MovingObject) <= options.Visibility + options.Precision).ToList();

            var        endPoint = options.MovingObject.MoveTowards(options.Angle, options.Visibility);
            ILocationF lkg      = null;

            for (var dPrime = options.Precision; dPrime < options.Visibility; dPrime += options.Precision)
            {
                var testArea = options.MovingObject.MoveTowards(options.Angle, dPrime);
                prediction.Path.Add(testArea);
                var obstacleHit = effectiveObstacles.Where(o =>
                {
                    var simpleTest = o.Touches(testArea) == true;
                    if (simpleTest == false)
                    {
                        return(false);
                    }

                    if (o.Touches(options.MovingObject))
                    {
                        var overlapBefore = options.MovingObject.NumberOfPixelsThatOverlap(o);
                        var overlapAfter  = testArea.NumberOfPixelsThatOverlap(o);

                        if (overlapAfter < overlapBefore)
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        return(true);
                    }
                }).FirstOrDefault();

                if (obstacleHit != null)
                {
                    prediction.Type        = HitType.Obstacle;
                    prediction.ObstacleHit = obstacleHit;
                    prediction.LKG         = lkg;
                    return(prediction);
                }
                else
                {
                    lkg = testArea.TopLeft();
                }
            }

            var obstacleHitFinal = effectiveObstacles.Where(o => o.Touches(endPoint) == true).FirstOrDefault();

            if (obstacleHitFinal != null)
            {
                prediction.Type        = HitType.Obstacle;
                prediction.ObstacleHit = obstacleHitFinal;
                prediction.LKG         = lkg;
                return(prediction);
            }

            prediction.Type = HitType.None;
            return(prediction);
        }