예제 #1
0
        public static Route CalculateLineOfSight(this IRectangular from, IRectangular to, float increment)
        {
            Route        ret             = new Route();
            IRectangular current         = from;
            var          currentDistance = current.CalculateDistanceTo(to);
            var          firstDistance   = currentDistance;

            while (currentDistance > increment)
            {
#if DEBUG
                if (currentDistance > firstDistance)
                {
                    throw new Exception("Bug, we got farther away");
                }
#endif

                current = Rectangular.Create(MoveTowards(current.Center(), to.Center(), increment), from);
                current = Rectangular.Create(current.Left - from.Width / 2, current.Top - from.Height / 2, from.Width, from.Height);
                ret.Steps.Add(current);

                var obstacles = SpaceTime.CurrentSpaceTime.Elements
                                .Where(el => el != from && el != to && el.NumberOfPixelsThatOverlap(current) > 0);

                foreach (var obstacle in obstacles)
                {
                    if (ret.Obstacles.Contains(obstacle) == false)
                    {
                        ret.Obstacles.Add(obstacle);
                    }
                }

                currentDistance = current.CalculateDistanceTo(to);
            }

            return(ret);
        }
예제 #2
0
        public static Route CalculateLineOfSight(IRectangular from, ILocation to, float increment)
        {
            Route        ret     = new Route();
            IRectangular current = from;

            while (from.Center().CalculateDistanceTo(to) > increment)
            {
                current = Rectangular.Create(MoveTowards(current.Center(), to, increment), from);
                ret.Steps.Add(current.Center());

                var obstacles = SpaceTime.CurrentSpaceTime.Elements
                                .Where(el => el.NumberOfPixelsThatOverlap(current) > 0);

                foreach (var obstacle in obstacles)
                {
                    if (ret.Obstacles.Contains(obstacle) == false)
                    {
                        ret.Obstacles.Add(obstacle);
                    }
                }
            }

            return(ret);
        }
예제 #3
0
        public override void Evaluate()
        {
            float dt = (float)Governor.Rate.TotalSeconds;

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

            float dx = SpeedX * dt;
            float dy = SpeedY * dt;

            if (dx == 0 && dy == 0)
            {
                return;
            }

            var hitPrediction = HitDetection.PredictHit(SpaceTime.CurrentSpaceTime, Element, HitDetectionTypes, dx, dy);

            if (hitPrediction.Type != HitType.None)
            {
                float angle;

                if (hitPrediction.ElementHit != null)
                {
                    angle = Element.Center().CalculateAngleTo(hitPrediction.ElementHit.Center());
                }
                else if (hitPrediction.Direction == Direction.Left)
                {
                    angle = 180;
                }
                else if (hitPrediction.Direction == Direction.Right)
                {
                    angle = 0;
                }
                else if (hitPrediction.Direction == Direction.Up)
                {
                    angle = 270;
                }
                else if (hitPrediction.Direction == Direction.Down)
                {
                    angle = 90;
                }
                else
                {
                    throw new NotSupportedException($"Unsupported direction: {hitPrediction.Direction}");
                }

                if (ImpactOccurred != null && haveMovedSinceLastHitDetection)
                {
                    ImpactOccurred.Fire(new Impact()
                    {
                        Angle      = angle,
                        Bounds     = hitPrediction.BoundsOfItemBeingHit,
                        ElementHit = hitPrediction.ElementHit
                    });
                }
                haveMovedSinceLastHitDetection = false;
                var testArea = Rectangular.Create(Element.Left + dx, Element.Top + dy, Element.Width, Element.Height);

                if (hitPrediction.Direction == Direction.Down || hitPrediction.Direction == Direction.Up)
                {
                    SpeedY = -SpeedY * Bounciness;
                    SpeedX = SpeedX * ImpactFriction;
                }
                else if (hitPrediction.Direction == Direction.Left || hitPrediction.Direction == Direction.Right)
                {
                    SpeedX = -SpeedX * Bounciness;
                    SpeedY = SpeedY * ImpactFriction;
                }
                else
                {
                    SpeedX = -SpeedX * Bounciness;
                    SpeedY = -SpeedY * Bounciness;
                }
            }
            else
            {
                var oldLocation = Element.CopyBounds();
                Element.MoveBy(dx, dy);

                this.Angle = oldLocation.Center().CalculateAngleTo(Element.Center());
                haveMovedSinceLastHitDetection = true;
            }
        }
예제 #4
0
        public static HitPrediction PredictHit(SpaceTime r, SpacialElement Target, List <Type> hitDetectionTypes, float dx, float dy)
        {
            HitPrediction prediction = new HitPrediction();

            if (dx == 0 && dy == 0)
            {
                prediction.Direction = Direction.None;
                prediction.Type      = HitType.None;
                return(prediction);
            }

            if (dy > 0 && Target.Bottom() + dy >= r.Height)
            {
                prediction.Direction            = Direction.Down;
                prediction.Type                 = HitType.Boundary;
                prediction.BoundsOfItemBeingHit = Rectangular.Create(Target.Left + dx, r.Bounds.Height + dy, 1, 1);
                return(prediction);
            }
            else if (dx < 0 && Target.Left + dx <= 0)
            {
                prediction.Direction            = Direction.Left;
                prediction.Type                 = HitType.Boundary;
                prediction.BoundsOfItemBeingHit = Rectangular.Create(-dx, Target.Top + dy, 1, 1);
                return(prediction);
            }
            else if (dy < 0 && Target.Top + dy <= 0)
            {
                prediction.Direction            = Direction.Up;
                prediction.Type                 = HitType.Boundary;
                prediction.BoundsOfItemBeingHit = Rectangular.Create(Target.Left + dx, -dy, 1, 1);
                return(prediction);
            }
            else if (dx > 0 && Target.Right() + dx >= r.Width)
            {
                prediction.Direction            = Direction.Right;
                prediction.Type                 = HitType.Boundary;
                prediction.BoundsOfItemBeingHit = Rectangular.Create(r.Width + dx, Target.Top + dy, 1, 1);
                return(prediction);
            }

            var testArea = Rectangular.Create(Target.Left + dx, Target.Top + dy, Target.Width, Target.Height);

            var match = (from t in r.Elements
                         where
                         t.IsOneOfThese(hitDetectionTypes) &&
                         Target != t &&
                         testArea.NumberOfPixelsThatOverlap(t) > 0
                         select t).OrderBy(t => t.Center().CalculateDistanceTo(Target.Center()));


            if (match.Count() == 0)
            {
                prediction.Direction = Direction.None;
                prediction.Type      = HitType.None;
            }
            else
            {
                prediction.ElementHit           = match.First();
                prediction.Type                 = HitType.Element;
                prediction.Direction            = testArea.GetHitDirection(match.First().Bounds);
                prediction.BoundsOfItemBeingHit = prediction.ElementHit.Bounds;
            }

            return(prediction);
        }
예제 #5
0
 public static IRectangular CopyBounds(this IRectangular rectangular) => Rectangular.Create(rectangular.Left, rectangular.Top, rectangular.Width, rectangular.Height);