Beispiel #1
0
        public static async Task AnimateAsync(this IRectangularF rectangular, RectangularAnimationOptions options)
        {
            var startX = rectangular.Left;
            var startY = rectangular.Top;
            var startW = rectangular.Width;
            var startH = rectangular.Height;

            await Animator.AnimateAsync(new FloatAnimatorOptions()
            {
                Duration         = options.Duration,
                AutoReverse      = options.AutoReverse,
                AutoReverseDelay = options.AutoReverseDelay,
                DelayProvider    = options.DelayProvider,
                Loop             = options.Loop,
                EasingFunction   = options.EasingFunction,
                From             = 0,
                To          = 1,
                IsCancelled = options.IsCancelled,
                Setter      = v =>
                {
                    var dest   = options.Destination();
                    var xDelta = dest.Left - startX;
                    var yDelta = dest.Top - startY;
                    var wDelta = dest.Width - startW;
                    var hDelta = dest.Height - startH;

                    var frameX      = startX + (v *xDelta);
                    var frameY      = startY + (v *yDelta);
                    var frameW      = startW + (v *wDelta);
                    var frameH      = startH + (v *hDelta);
                    var frameBounds = RectangularF.Create(frameX, frameY, frameW, frameH);
                    options.Setter(rectangular, frameBounds);
                }
            });
        }
Beispiel #2
0
 public override void Setter(IRectangularF target, IRectangularF bounds)
 {
     (target as ConsoleControl).X      = (int)Math.Round(bounds.Left);
     (target as ConsoleControl).Y      = (int)Math.Round(bounds.Top);
     (target as ConsoleControl).Width  = (int)Math.Round(bounds.Width);
     (target as ConsoleControl).Height = (int)Math.Round(bounds.Height);
 }
Beispiel #3
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);
                }
            }
        }
Beispiel #4
0
        public Projectile(Weapon w, float speed, float angle) : base(w)
        {
            this.ResizeTo(StandardWidth, StandardHeight);
            if (w?.Holder != null)
            {
                this.MoveTo(w.Holder.CenterX() - StandardWidth / 2, w.Holder.CenterY() - StandardHeight / 2, w.Holder.ZIndex);
            }

            Time.CurrentTime.QueueAction("Snap bounds", () => startLocation = this.Bounds);

            this.Tags.Add(Weapon.WeaponTag);
            Velocity = new Velocity(this);
            Velocity.Governor.Rate = TimeSpan.FromSeconds(0);
            Velocity.ImpactOccurred.SubscribeForLifetime(Speed_ImpactOccurred, this.Lifetime);
            this.Velocity.HitDetectionExclusionTypes.Add(typeof(Projectile));
            if (w?.Holder != null)
            {
                this.Velocity.HitDetectionExclusions.Add(w.Holder);
            }
            Velocity.Speed = speed;
            Velocity.Angle = angle;

            this.SizeOrPositionChanged.SubscribeForLifetime(() =>
            {
                if (startLocation != null && Range > 0 && this.CalculateDistanceTo(startLocation) > Range)
                {
                    this.Lifetime.Dispose();
                }
            }, this.Lifetime);


            this.Governor.Rate = TimeSpan.FromSeconds(-1);
        }
Beispiel #5
0
        public static ILocationF GetNudgeLocation(this SpacialElement el, IRectangularF desiredLocation = null, float optimalAngle = 0, int?z = null)
        {
            desiredLocation = desiredLocation ?? el.EffectiveBounds();
            var obstacles = el.GetObstacles(z: z);

            if (obstacles.Where(o => o.Touches(desiredLocation)).Any() || SpaceTime.CurrentSpaceTime.Bounds.Contains(desiredLocation) == false)
            {
                foreach (var angle in Enumerate360Angles(optimalAngle))
                {
                    for (var d = .1f; d < 15f; d += .1f)
                    {
                        var effectiveAngle = angle % 360;
                        var testLoc        = desiredLocation.MoveTowards(effectiveAngle, d);
                        var testArea       = RectangularF.Create(testLoc.Left, testLoc.Top, desiredLocation.Width, desiredLocation.Height);
                        if (obstacles.Where(o => o.Touches(testArea)).None() && SpaceTime.CurrentSpaceTime.Bounds.Contains(testArea))
                        {
                            return(testLoc.TopLeft());
                        }
                    }
                }
                return(null);
            }
            else
            {
                return(el.TopLeft());
            }
        }
Beispiel #6
0
        public static float OverlapPercentage(this IRectangularF rectangle, IRectangularF other)
        {
            var numerator   = NumberOfPixelsThatOverlap(rectangle, other);
            var denominator = other.Width * other.Height;

            if (numerator == 0)
            {
                return(0);
            }
            else if (numerator == denominator)
            {
                return(1);
            }

            var amount = numerator / denominator;

            if (amount < 0)
            {
                amount = 0;
            }
            else if (amount > 1)
            {
                amount = 1;
            }

            if (amount > .999)
            {
                amount = 1;
            }

            return(amount);
        }
Beispiel #7
0
        public static NudgeEvent NudgeFree(this SpacialElement el, IRectangularF desiredLocation = null, float optimalAngle = 0, int?z = null)
        {
            var loc = GetNudgeLocation(el, desiredLocation, optimalAngle, z);

            if (loc != null)
            {
                if (el is IHaveMassBounds == false)
                {
                    el.MoveTo(loc.Left, loc.Top, z);
                }
                else
                {
                    var elBounds = el.EffectiveBounds();
                    var dx       = el.Left - elBounds.Left;
                    var dy       = el.Top - elBounds.Top;
                    el.MoveTo(loc.Left + dx, loc.Top + dy, z);
                }
                var ev = new NudgeEvent()
                {
                    Element = el, Success = true
                };
                OnNudge.Fire(ev);
                return(ev);
            }
            else
            {
                var ev = new NudgeEvent()
                {
                    Element = el, Success = false
                };
                OnNudge.Fire(ev);
                return(ev);
            }
        }
Beispiel #8
0
        public static bool HasLineOfSight(this IRectangularF from, IRectangularF to, List <IRectangularF> obstacles)
        {
            var a = from.CalculateAngleTo(to);
            var d = Geometry.CalculateNormalizedDistanceTo(from, to);

            foreach (var o in obstacles)
            {
                if (o == from || o == to)
                {
                    continue;
                }
                var dO = Geometry.CalculateNormalizedDistanceTo(from, o);

                if (dO > d)
                {
                    continue;
                }
                // todo - define this curve smoothly with real math
                var angleDiffThreshold = d < 2 ? 180 :
                                         d < 5 ? 60 :
                                         d < 10 ? 40 :
                                         d < 20 ? 25 :
                                         d < 40 ? 20 : 15;

                var aO     = from.CalculateAngleTo(o);
                var aODiff = a.DiffAngle(aO);

                if (aODiff < angleDiffThreshold)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #9
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);
        }
Beispiel #10
0
        public static IRectangularF MoveTowards(this IRectangularF r, float angle, float distance)
        {
            var newLoc = MoveTowards(r.TopLeft(), angle, distance);
            var ret    = RectangularF.Create(newLoc.Left, newLoc.Top, r.Width, r.Height);

            return(ret);
        }
Beispiel #11
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));
        }
Beispiel #12
0
 public override void Setter(IRectangularF target, IRectangularF bounds)
 {
     (target as SpacialElement).MoveTo(bounds.Left, bounds.Top);
     if (target.Width != bounds.Width || target.Height != bounds.Height)
     {
         (target as SpacialElement).ResizeTo(bounds.Width, bounds.Height);
     }
 }
Beispiel #13
0
        public bool IsComingTowards(IRectangularF target)
        {
            var d = Element.CalculateDistanceTo(target);
            var projectedLocation = this.Element.TopLeft().MoveTowards(this.Angle, d);
            var projectedRect     = RectangularF.Create(projectedLocation.Left, projectedLocation.Top, Element.Width, Element.Height);
            var ret = projectedRect.CalculateDistanceTo(target);

            return(ret < .5);
        }
Beispiel #14
0
 public static IRectangularF Round(this IRectangularF rect)
 {
     return(RectangularF.Create(
                (int)Math.Round(rect.Left),
                (int)Math.Round(rect.Top),
                (int)Math.Round(rect.Width),
                (int)Math.Round(rect.Height)
                ));
 }
Beispiel #15
0
 public static IRectangularF Round(this IRectangularF rect)
 {
     return(RectangularF.Create(
                Geometry.Round(rect.Left),
                Geometry.Round(rect.Top),
                Geometry.Round(rect.Width),
                Geometry.Round(rect.Height)
                ));
 }
Beispiel #16
0
        public static IEnumerable <ILocationF> Corners(this IRectangularF rect)
        {
            yield return(rect.TopLeft());

            yield return(rect.TopRight());

            yield return(rect.BottomLeft());

            yield return(rect.BottomRight());
        }
Beispiel #17
0
        public static IRectangularF Resize(this IRectangularF me, float ratio)
        {
            var newW       = me.Width * ratio;
            var newH       = me.Height * ratio;
            var leftAdjust = (me.Width - newW) / 2;
            var topAdjust  = (me.Height - newH) / 2;
            var ret        = RectangularF.Create(me.Left + leftAdjust, me.Top + topAdjust, newW, newH);

            return(ret);
        }
Beispiel #18
0
 private bool CausesExplosion(IRectangularF thingHit)
 {
     if (thingHit is WeaponElement || thingHit is Character)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Beispiel #19
0
 private static bool IsIncluded(HitDetectionOptions options, IRectangularF obj)
 {
     if (options.Exclusions == null)
     {
         return(true);
     }
     else
     {
         return(options.Exclusions.Contains(obj) == false);
     }
 }
Beispiel #20
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);
        }
Beispiel #21
0
        public static float NumberOfPixelsThatOverlap(this IRectangularF rectangle, IRectangularF other)
        {
            var rectangleRight = rectangle.Right();
            var otherRight     = other.Right();

            var rectangleBottom = rectangle.Bottom();
            var otherBottom     = other.Bottom();

            var ret =
                Math.Max(0, Math.Min(rectangleRight, otherRight) - Math.Max(rectangle.Left, other.Left)) *
                Math.Max(0, Math.Min(rectangleBottom, otherBottom) - Math.Max(rectangle.Top, other.Top));

            ret = (float)Math.Round(ret, 4);
            return(ret);
        }
Beispiel #22
0
            public NetMatter(Net net) : base(net)
            {
                Speed             = new Velocity(this);
                this.initialBonds = this.CopyBounds();
                this.initialTime  = Time.CurrentTime.Now;

                this.Added.SubscribeOnce(async() =>
                {
                    while (this.Lifetime.IsExpired == false)
                    {
                        Evaluate();
                        await Time.CurrentTime.YieldAsync();
                    }
                });
            }
Beispiel #23
0
        public Projectile(Weapon w, float speed, float angle, bool autoLocate = true) : base(w)
        {
            this.ResizeTo(1, 1);

            if (w?.Holder != null)
            {
                if (w.Holder.Velocity.Angle.DiffAngle(angle) < 45)
                {
                    speed += w.Holder.Velocity.Speed;
                }

                this.MoveTo(w.Holder.EffectiveBounds().CenterX() - Width / 2, w.Holder.EffectiveBounds().CenterY() - Height / 2, w.Holder.ZIndex);
                var offset = this.MoveTowards(angle, 1, false);
                this.MoveTo(offset.Left, offset.Top);
            }

            Time.CurrentTime.InvokeNextCycle(() =>
            {
                if (autoLocate && w?.Holder != null)
                {
                    this.MoveTo(w.Holder.EffectiveBounds().CenterX() - Width / 2, w.Holder.EffectiveBounds().CenterY() - Height / 2, w.Holder.ZIndex);
                    var offset = this.MoveTowards(angle, 1, false);
                    this.MoveTo(offset.Left, offset.Top);
                }
                startLocation = this.Bounds;
            });



            this.AddTag(Weapon.WeaponTag);
            Velocity = new Velocity(this);
            Velocity.ImpactOccurred.SubscribeForLifetime(Speed_ImpactOccurred, this.Lifetime);
            this.Velocity.HitDetectionExclusionTypes.Add(typeof(Projectile));
            if (w?.Holder != null)
            {
                this.Velocity.HitDetectionExclusions.Add(w.Holder);
            }
            Velocity.Speed = speed;
            Velocity.Angle = angle;

            this.SizeOrPositionChanged.SubscribeForLifetime(() =>
            {
                if (startLocation != null && Range > 0 && this.CalculateDistanceTo(startLocation) > Range)
                {
                    this.Lifetime.Dispose();
                }
            }, this.Lifetime);
        }
Beispiel #24
0
        public static float NumberOfPixelsThatOverlap(this IRectangularF rectangle, IRectangularF other)
        {
            var rectangleRight  = rectangle.Left + rectangle.Width;
            var otherRight      = other.Left + other.Width;
            var rectangleBottom = rectangle.Top + rectangle.Height;
            var otherBottom     = other.Top + other.Height;
            var a = Math.Max(0, Math.Min(rectangleRight, otherRight) - Math.Max(rectangle.Left, other.Left));

            if (a == 0)
            {
                return(0);
            }
            var b = Math.Max(0, Math.Min(rectangleBottom, otherBottom) - Math.Max(rectangle.Top, other.Top));

            return(a * b);
        }
Beispiel #25
0
        public static void UpdateEdges(IRectangularF rect, Edge[] edgeBuffer)
        {
            edgeBuffer[0].From = rect.TopLeft();
            edgeBuffer[0].To   = rect.TopRight();

            edgeBuffer[1].From = rect.TopRight();
            edgeBuffer[1].To   = rect.BottomRight();


            edgeBuffer[2].From = rect.BottomRight();
            edgeBuffer[2].To   = rect.BottomLeft();


            edgeBuffer[3].From = rect.BottomLeft();
            edgeBuffer[3].To   = rect.TopLeft();
        }
Beispiel #26
0
        public static float CalculateDistanceTo(this IRectangularF a, IRectangularF b)
        {
            var left   = b.Right() < a.Left;
            var right  = a.Right() < b.Left;
            var bottom = b.Bottom() < a.Top;
            var top    = a.Bottom() < b.Top;

            if (top && left)
            {
                return(CalculateDistanceTo(a.Left, a.Bottom(), b.Right(), b.Top));
            }
            else if (left && bottom)
            {
                return(CalculateDistanceTo(a.Left, a.Top, b.Right(), b.Bottom()));
            }
            else if (bottom && right)
            {
                return(CalculateDistanceTo(a.Right(), a.Top, b.Left, b.Bottom()));
            }
            else if (right && top)
            {
                return(CalculateDistanceTo(a.Right(), a.Bottom(), b.Left, b.Top));
            }
            else if (left)
            {
                return(a.Left - b.Right());
            }
            else if (right)
            {
                return(b.Left - a.Right());
            }
            else if (bottom)
            {
                return(a.Top - b.Bottom());
            }
            else if (top)
            {
                return(b.Top - a.Bottom());
            }
            else
            {
                return(0);
            }
        }
Beispiel #27
0
        public static ILocationF GetNudgeLocation(this SpacialElement el, IRectangularF desiredLocation = null, float initialAngle = 0)
        {
            desiredLocation = desiredLocation ?? el.EffectiveBounds();
            var obstacles = el.GetObstacles();

            if (obstacles.Where(o => o.Touches(desiredLocation)).Any())
            {
                for (var d = 1f; d < 15; d++)
                {
                    for (var angle = initialAngle; angle < initialAngle + 360; angle += 20)
                    {
                        var effectiveAngle = angle % 360;
                        var testLoc        = desiredLocation.MoveTowards(effectiveAngle, d);
                        var testArea       = RectangularF.Create(testLoc.Left, testLoc.Top, desiredLocation.Width, desiredLocation.Height);
                        if (obstacles.Where(o => o.Touches(testArea)).None() && SpaceTime.CurrentSpaceTime.Bounds.Contains(testArea))
                        {
                            return(testLoc.TopLeft());
                        }
                    }
                }
            }
            return(null);
        }
Beispiel #28
0
 public static float CalculateAngleTo(this IRectangularF from, IRectangularF to) => CalculateAngleTo(from.Center(), to.Center());
Beispiel #29
0
 public static bool Touches(this IRectangularF rectangle, IRectangularF other) => NumberOfPixelsThatOverlap(rectangle, other) > 0;
Beispiel #30
0
 public static bool Contains(this IRectangularF rectangle, IRectangularF other) => OverlapPercentage(rectangle, other) == 1;