using System; using MonoGameBlank2dStartKit.Core.Utils; using MoonTools.ECS; namespace MonoGameBlank2dStartKit.Core.Systems; public class EasingSystem : MoonTools.ECS.System { private record EasingFilter(Filter Filter, Action, float> ProcessEntities); private readonly EasingFilter[] _easingFilters; public EasingSystem(World world) : base(world) { _easingFilters = [ BuildEasingFilter(p => p), BuildEasingFilter(p => p * p * p), BuildEasingFilter(p => { float f = p - 1; return (f * f * f) + 1; }), BuildEasingFilter(p => { if (p < 0.5) { return 4 * p * p * p; } float f = 2 * p - 2; return 0.5f * f * f * f + 1; }), BuildEasingFilter(p => p * p * p * p * p), BuildEasingFilter(p => { float f = p - 1; return (f * f * f * f * f) + 1; }), ]; } private EasingFilter BuildEasingFilter(Func easingFunc) where T : unmanaged, IMovement { var filter = FilterBuilder.Include().Build(); return new EasingFilter(filter, (entities, deltaSec) => { foreach (var entity in entities) { var currentMovement = World.Get(entity); ApplyMovement(deltaSec, entity, currentMovement, easingFunc); } }); } public override void Update(TimeSpan delta) { float deltaSec = delta.SecFloat(); foreach (var easingFilter in _easingFilters) { easingFilter.ProcessEntities(easingFilter.Filter.Entities, deltaSec); } } private void ApplyMovement( float deltaSec, Entity entity, T currentMovement, Func easingFunction) where T : unmanaged, IMovement { float newProgressSec = currentMovement.ProgressSec + deltaSec; float percentComplete = newProgressSec / currentMovement.DurationSec; if (percentComplete >= 1) { World.Set(entity, currentMovement.Target); World.Remove(entity); } else { var diff = currentMovement.Target.Vector2 - currentMovement.Start.Vector2; var newPos = new Position((currentMovement.Start.Vector2) + (diff * easingFunction(percentComplete))); World.Set(entity, newPos); World.Set(entity, currentMovement with { ProgressSec = newProgressSec }); } } }