///<summary>Handles making ellipse controls for each ball in the game, as while as showing their death animations.</summary> public static void SetupDrawBallsAsControls(this Game game, PerishableCollection<UIElement> controls, TimeSpan deathFadeOutDuration, double deathFinalRadiusFactor) { game.Balls.CurrentAndFutureItems().Subscribe( e => { // create an ellipse control to visually represent the ball var ball = e.Value; var color = ball.Hue.HueToApproximateColor(period: 3); var ellipseControl = new Ellipse { Width = ball.Radius * 2, Height = ball.Radius * 2, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, Fill = new SolidColorBrush(color) }; // 'root' balls have a black border if (ball.Generation == 1) { ellipseControl.StrokeThickness = 3; ellipseControl.Stroke = new SolidColorBrush(Colors.Black); } // reposition ellipse control during each game loop, until ball is dead game.LoopActions.Add( step => ellipseControl.Reposition(ball.Pos, ball.Radius), e.Lifetime); // once ball is dead, expand and fade out the ellipse var controlLifetime = e.Lifetime.ThenResurrect(() => game.AnimateWith( deathFadeOutDuration, (step, portion, dt) => { // fade out ellipseControl.Fill = new SolidColorBrush(color.LerpToTransparent(portion)); // expand var radius = ball.Radius * 1.LerpTo(deathFinalRadiusFactor, portion); ellipseControl.Reposition(ball.Pos, radius); })); controls.Add(ellipseControl, controlLifetime); }, game.Life); }