Esempio n. 1
0
        public static IRectangularF GetLineOfSightObstruction(this IRectangularF from, IRectangularF to, IEnumerable <IRectangularF> obstacles)
        {
            var prediction = PredictHit(new HitDetectionOptions()
            {
                MovingObject = from,
                Angle        = from.Center().CalculateAngleTo(to.Center()),
                Obstacles    = obstacles.Union(new IRectangularF[] { to }),
                Visibility   = 3 * from.Center().CalculateDistanceTo(to.Center()),
                Mode         = CastingMode.Rough,
            });

            if (prediction.Type == HitType.None)
            {
                return(SpaceTime.CurrentSpaceTime?.Bounds);
            }
            else
            {
                if (to is IHaveMassBounds && prediction.ObstacleHit is SpacialElement && (to as IHaveMassBounds).IsPartOfMass(prediction.ObstacleHit as SpacialElement))
                {
                    return(null);
                }

                if (prediction.ObstacleHit is SpacialElement && (to is IHaveMassBounds) && (to as IHaveMassBounds).IsPartOfMass((SpacialElement)prediction.ObstacleHit))
                {
                    return(null);
                }
                else
                {
                    return(prediction.ObstacleHit == to ? null : prediction.ObstacleHit);
                }
            }
        }
Esempio n. 2
0
        private static List <IRectangularF> GetLineOfSight(this IRectangularF from, IRectangularF to, List <IRectangularF> obstacles, float increment = .5f)
        {
            IRectangularF current         = from;
            var           currentDistance = current.CalculateDistanceTo(to);
            var           a    = current.Center().CalculateAngleTo(to.Center());
            var           path = new List <IRectangularF>();

            while (currentDistance > increment)
            {
                current = RectangularF.Create(MoveTowards(current.Center(), a, increment), current);
                current = RectangularF.Create(current.Left - current.Width / 2, current.Top - current.Height / 2, current.Width, current.Height);

                foreach (var obstacle in obstacles)
                {
                    if (obstacle == to || obstacle == from)
                    {
                        continue;
                    }
                    else if (obstacle.OverlapPercentage(current) > 0)
                    {
                        return(null);
                    }
                }
                path.Add(current);
                currentDistance = current.CalculateDistanceTo(to);
            }

            return(path);
        }
Esempio n. 3
0
        public static IRectangularF Shrink(this IRectangularF rect, float percentage)
        {
            var center = rect.Center();
            var newW   = rect.Width * (1 - percentage);
            var newH   = rect.Height * (1 - percentage);

            return(RectangularF.Create(center.Left - newW / 2, center.Top - newH / 2, newW, newH));
        }
Esempio n. 4
0
        public static float LineOfSightVisibility(this IRectangularF from, float angle, IEnumerable <IRectangularF> obstacles, float range, float increment = .5f)
        {
            for (var d = increment; d < range; d += increment)
            {
                var testLocation = from.Center().MoveTowards(angle, d);
                var testRect     = RectangularF.Create(testLocation.Left - from.Width / 2, testLocation.Top - from.Height / 2, from.Width, from.Height);
                if (obstacles.Where(o => o.Touches(testRect)).Any() || SpaceTime.CurrentSpaceTime.Bounds.Contains(testRect) == false)
                {
                    return(d);
                }
            }

            return(range);
        }
Esempio n. 5
0
 public static float CalculateAngleTo(this IRectangularF from, IRectangularF to) => CalculateAngleTo(from.Center(), to.Center());
Esempio n. 6
0
        private async Task ExecuteAsync()
        {
            while (this.Lifetime.IsExpired == false)
            {
                await Time.CurrentTime.YieldAsync();

                if (this.Lifetime.IsExpired)
                {
                    return;
                }
                if (MovementTakeover != null)
                {
                    await MovementTakeover();

                    continue;
                }

                float dt = (float)Time.CurrentTime.Increment.TotalSeconds;
                if (dt == 0)
                {
                    dt = (float)Time.CurrentTime.Increment.TotalSeconds;
                }
                float d = Speed * dt;

                if (d == 0)
                {
                    OnVelocityEnforced?.Fire();
                    continue;
                }

                HitPrediction hitPrediction = null;
                IRectangularF bounds        = null;
                if (HitDetectionDisabled == false)
                {
                    var obstacles = GetObstacles();

                    bounds = BoundsTransform != null?BoundsTransform() : Element;

                    hitPrediction = HitDetection.PredictHit(new HitDetectionOptions()
                    {
                        MovingObject = bounds,
                        Obstacles    = obstacles,
                        Angle        = Angle,
                        Visibility   = d,
                        Mode         = CastingMode.Precise,
                    });
                    LastPrediction = hitPrediction;
                }


                if (hitPrediction != null && hitPrediction.Type != HitType.None)
                {
                    var dx = BoundsTransform != null ? bounds.Left - Element.Left : 0;
                    var dy = BoundsTransform != null ? bounds.Top - Element.Top : 0;

                    var proposedBounds = BoundsTransform != null?BoundsTransform() : Element;

                    var distanceToObstacleHit = proposedBounds.CalculateDistanceTo(hitPrediction.ObstacleHit);
                    if (distanceToObstacleHit > .5f)
                    {
                        proposedBounds = proposedBounds.MoveTowards(Angle, distanceToObstacleHit - .5f, false);
                        Element.MoveTo(proposedBounds.Left - dx, proposedBounds.Top - dy);
                        haveMovedSinceLastHitDetection = true;
                    }
                    float angle = bounds.Center().CalculateAngleTo(hitPrediction.ObstacleHit.Center());


                    if (haveMovedSinceLastHitDetection)
                    {
                        LastImpact = new Impact()
                        {
                            Angle        = angle,
                            MovingObject = Element,
                            ObstacleHit  = hitPrediction.ObstacleHit,
                            HitType      = hitPrediction.Type,
                        };

                        if (hitPrediction.ObstacleHit is SpacialElement)
                        {
                            Velocity.For(hitPrediction.ObstacleHit as SpacialElement)?.ImpactOccurred.Fire(new Impact()
                            {
                                Angle        = angle.GetOppositeAngle(),
                                MovingObject = hitPrediction.ObstacleHit as SpacialElement,
                                ObstacleHit  = Element,
                                HitType      = hitPrediction.Type,
                            });
                        }

                        ImpactOccurred?.Fire(LastImpact);
                        GlobalImpactOccurred.Fire(LastImpact);

                        haveMovedSinceLastHitDetection = false;
                        Element.SizeOrPositionChanged.Fire();
                    }

                    if (Bounce)
                    {
                        var side = Geometry.GetSideGivenEdgeIndex(hitPrediction.EdgeIndex);

                        if (side == Side.Top || side == Side.Bottom)
                        {
                            Angle = 0.AddToAngle(-Angle);
                        }
                        else
                        {
                            Angle = 180.AddToAngle(-Angle);
                        }
                    }
                    else
                    {
                        Stop();
                    }
                }
                else
                {
                    var newLocation = Element.MoveTowards(Angle, d);
                    Element.MoveTo(newLocation.Left, newLocation.Top);
                    haveMovedSinceLastHitDetection = true;
                }

                OnVelocityEnforced?.Fire();
            }
        }