Example #1
0
        ///<summary>Handles periodically adding children to existing balls.</summary>
        public static void SetupPeriodicChildSpawning(this Game game, double expectedPerBallPerSecond, int maxChildrenPerBall, int maxGeneration)
        {
            game.Balls.CurrentAndFutureItems().Subscribe(
                ball => {
                if (ball.Value.Generation > maxGeneration)
                {
                    return;
                }

                // keep track of children
                var curChildCount = 0;
                var children      = new PerishableCollection <Ball>();
                children
                .CurrentAndFutureItems()
                .ObserveNonPerishedCount(completeWhenSourceCompletes: true)
                .Subscribe(e => curChildCount = e, ball.Lifetime);

                // spawn children periodically at random
                game.StochasticRate(
                    expectedPerBallPerSecond,
                    ball.Lifetime,
                    () => {
                    if (curChildCount >= maxChildrenPerBall)
                    {
                        return;
                    }
                    var child = game.SpawnBall(parent: ball.Value);
                    game.Connectors.Add(new Connector {
                        Child = child, Parent = ball.Value
                    }, child.Life.Lifetime);
                    children.Add(child, child.Life.Lifetime);
                });
            },
                game.Life);
        }
        private void SetupAndRunGame(Game game, bool initial)
        {
            // controls added to this collection should be displayed on the canvas until they perish
            var controls = new PerishableCollection <UIElement>();

            controls.CurrentAndFutureItems().Subscribe(
                e => {
                canvas.Children.Add(e.Value);
                e.Lifetime.WhenDead(() => canvas.Children.Remove(e.Value));
            },
                game.Life);

            // balls should move and bounce off borders
            game.SetupMoveAndBounceBalls(
                playArea: () => new Rect(0, 0, canvas.ActualWidth, canvas.ActualHeight));

            // connected balls should be be gently tugged towards each other
            game.SetupAttractBalls(
                deadRadius: 50,
                accellerationPerSecondChild: 10,
                accellerationPerSecondParent: 5);

            // balls should periodically spawn dependent children
            game.SetupPeriodicChildSpawning(
                expectedPerBallPerSecond: 0.2,
                maxChildrenPerBall: 2,
                maxGeneration: 5);

            // balls should be drawn using ellipse controls and have death animations
            game.SetupDrawBallsAsControls(
                controls,
                deathFadeOutDuration: 800.Milliseconds(),
                deathFinalRadiusFactor: 3);

            // ball connectors should be drawn using line controls and have cut and death animations
            game.SetupDrawConnectorsAsControls(
                controls,
                deathFadeDuration: 800.Milliseconds(),
                deathFinalThicknessFactor: 6,
                propagateBangColor: Colors.Green,
                propagateBangDuration: 400.Milliseconds(),
                propagateBangRotationsPerSecond: 3,
                propagateBangMaxRadius: 10,
                cutBangColor: Colors.Red,
                cutBangDuration: 400.Milliseconds(),
                cutBangMaxRadius: 15);

            // connectors that touch the cursor should die
            SetupMouseCutter(game, controls);

            // text displays of game state should track that state
            if (!initial)
            {
                SetupEnergyAndTime(
                    game,
                    energyLossForCutting: 2.5,
                    energyGainPerConnectorBroken: 1);
            }

            // there should be a few root balls to start with
            foreach (var repeat in 5.Range())
            {
                game.SpawnBall(parent: new Ball {
                    Pos    = new Point(game.Rng.NextDouble() * canvas.ActualWidth, game.Rng.NextDouble() * canvas.ActualHeight),
                    Radius = 10,
                    Life   = new LifetimeSource(),
                    Hue    = game.Rng.NextDouble() * 3
                });
            }

            // run the game loop until the game is over
            game.Loop().ContinueWith(e => {
                // exceptions?
            });
        }
        private void SetupAndRunGame(Game game, bool initial) {
            // controls added to this collection should be displayed on the canvas until they perish
            var controls = new PerishableCollection<UIElement>();
            controls.CurrentAndFutureItems().Subscribe(
                e => {
                    canvas.Children.Add(e.Value);
                    e.Lifetime.WhenDead(() => canvas.Children.Remove(e.Value));
                },
                game.Life);

            // balls should move and bounce off borders
            game.SetupMoveAndBounceBalls(
                playArea: () => new Rect(0, 0, canvas.ActualWidth, canvas.ActualHeight));

            // connected balls should be be gently tugged towards each other
            game.SetupAttractBalls(
                deadRadius: 50,
                accellerationPerSecondChild: 10,
                accellerationPerSecondParent: 5);

            // balls should periodically spawn dependent children
            game.SetupPeriodicChildSpawning(
                expectedPerBallPerSecond: 0.2, 
                maxChildrenPerBall: 2, 
                maxGeneration: 5);

            // balls should be drawn using ellipse controls and have death animations
            game.SetupDrawBallsAsControls(
                controls, 
                deathFadeOutDuration: 800.Milliseconds(), 
                deathFinalRadiusFactor: 3);

            // ball connectors should be drawn using line controls and have cut and death animations
            game.SetupDrawConnectorsAsControls(
                controls,
                deathFadeDuration: 800.Milliseconds(),
                deathFinalThicknessFactor: 6,
                propagateBangColor: Colors.Green,
                propagateBangDuration: 400.Milliseconds(),
                propagateBangRotationsPerSecond: 3,
                propagateBangMaxRadius: 10,
                cutBangColor: Colors.Red,
                cutBangDuration: 400.Milliseconds(),
                cutBangMaxRadius: 15);

            // connectors that touch the cursor should die
            SetupMouseCutter(game, controls);

            // text displays of game state should track that state
            if (!initial) SetupEnergyAndTime(
                game,
                energyLossForCutting: 2.5,
                energyGainPerConnectorBroken: 1);

            // there should be a few root balls to start with
            foreach (var repeat in 5.Range()) {
                game.SpawnBall(parent: new Ball {
                    Pos = new Point(game.Rng.NextDouble()*canvas.ActualWidth, game.Rng.NextDouble()*canvas.ActualHeight),
                    Radius = 10,
                    Life = new LifetimeSource(),
                    Hue = game.Rng.NextDouble()*3
                });
            }

            // run the game loop until the game is over
            game.Loop().ContinueWith(e => {
                // exceptions?
            });
        }