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); } }); }
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); }
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); } } }
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); }
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()); } }
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); }
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); } }
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); }
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); }
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); }
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)); }
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); } }
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); }
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) )); }
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) )); }
public static IEnumerable <ILocationF> Corners(this IRectangularF rect) { yield return(rect.TopLeft()); yield return(rect.TopRight()); yield return(rect.BottomLeft()); yield return(rect.BottomRight()); }
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); }
private bool CausesExplosion(IRectangularF thingHit) { if (thingHit is WeaponElement || thingHit is Character) { return(true); } else { return(false); } }
private static bool IsIncluded(HitDetectionOptions options, IRectangularF obj) { if (options.Exclusions == null) { return(true); } else { return(options.Exclusions.Contains(obj) == false); } }
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); }
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); }
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(); } }); }
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); }
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); }
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(); }
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); } }
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); }
public static float CalculateAngleTo(this IRectangularF from, IRectangularF to) => CalculateAngleTo(from.Center(), to.Center());
public static bool Touches(this IRectangularF rectangle, IRectangularF other) => NumberOfPixelsThatOverlap(rectangle, other) > 0;
public static bool Contains(this IRectangularF rectangle, IRectangularF other) => OverlapPercentage(rectangle, other) == 1;