Example #1
0
        /// <summary>
        /// Enters the state.
        /// </summary>
        /// <param name="transition">The firing transition.</param>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        internal void EnterState(Transition transition, StateEventArgs eventArgs)
        {
            if (!IsActive)
              {
            // State is not active. Raise Enter event.
            OnEnter(eventArgs);
              }

              // Call Enter for sub-states.
              if (_parallelSubStates != null)
            foreach (var stateCollection in _parallelSubStates)
              stateCollection.EnterState(transition, eventArgs);
        }
Example #2
0
        /// <summary>
        /// Exits to the specified target state.
        /// </summary>
        /// <param name="transition">The firing transition.</param>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        /// <returns>
        /// <see langword="true"/> if this state was exited. <see langword="false"/> if this state is 
        /// still active because the target state is a sub-state of this state.
        /// </returns>
        internal bool ExitState(Transition transition, StateEventArgs eventArgs)
        {
            Debug.Assert(IsActive, "Exit should only be called for active states.");

              if (transition != null && !Transitions.Contains(transition) && Contains(transition.TargetState))
              {
            // The transition is not from this state and the target is a sub-state
            // --> We do not leave the current state!
            // We have to find the sub-state collection that contains the target. In this sub-state
            // collection the active state will exit (and the target state will be entered later).
            if (_parallelSubStates != null)
              foreach (var stateCollection in _parallelSubStates)
            if (stateCollection.ContainsRecursive(transition.TargetState))
              stateCollection.ExitState(transition, eventArgs);

            return false;

            // This approach assumes that there are no transitions from a state to a state in a
            // parallel set. This is not explicitly forbidden (it is never verified in the state
            // machine).
            // Programmers must not create such transitions and graphical state machine editors
            // should prohibit such constructs.
              }

              // The target state is no sub-state. --> Exit all sub-state collections.
              if (_parallelSubStates != null)
            foreach (var stateCollection in _parallelSubStates)
              stateCollection.ExitState(null, eventArgs);

              // Raise Exit event.
              OnExit(eventArgs);

              return true;
        }
Example #3
0
    private void CreateStateMachine()
    {
      // Let's create a state machine that manages all states and transitions.
      _stateMachine = new StateMachine();

      // ----- First we need to define all possible states of the game component:

      // The initial state is the "Loading" state. In this state a "Loading..."
      // text is rendered and all required assets are loaded in the background.
      var loadingState = new State { Name = "Loading" };
      loadingState.Enter += OnEnterLoadingScreen;
      loadingState.Exit += OnExitLoadingScreen;

      // The second state is the "Start" state. Once loading is finished the text
      // "Press Start button" is shown until the users presses the Start button
      // on the gamepad.
      var startState = new State { Name = "Start" };
      startState.Enter += OnEnterStartScreen;
      startState.Update += OnUpdateStartScreen;
      startState.Exit += OnExitStartScreen;

      // The "Menu" state represents the main menu. It provides buttons to start 
      // the game, show sub menus, and exit the game.
      var menuState = new State { Name = "Menu" };
      menuState.Enter += OnEnterMenuScreen;
      menuState.Exit += OnExitMenuScreen;

      // The "SubMenu" is just a dummy menu containing a few buttons. It is shown
      // whenever a sub menu is selected in the main menu.
      var subMenuState = new State { Name = "SubMenu" };
      subMenuState.Enter += OnEnterSubMenuScreen;
      subMenuState.Update += OnUpdateSubMenuScreen;
      subMenuState.Exit += OnExitSubMenuScreen;

      // The "Game" state is a placeholder for the actual game content.
      var gameState = new State { Name = "Game" };
      gameState.Enter += OnEnterGameScreen;
      gameState.Update += OnUpdateGameScreen;
      gameState.Exit += OnExitGameScreen;

      // Register the states in the state machine.
      _stateMachine.States.Add(loadingState);
      _stateMachine.States.Add(startState);
      _stateMachine.States.Add(menuState);
      _stateMachine.States.Add(subMenuState);
      _stateMachine.States.Add(gameState);

      // Optional: Define the initially selected state.
      // (If not set explicitly then the first state in the list is used as the 
      // initial state.)
      _stateMachine.States.InitialState = loadingState;

      // ----- Next we can define the allowed transitions between states.

      // The "Loading" screen will transition to the "Start" screen once all assets
      // are loaded. The assets are loaded in the background. The background worker 
      // sets the flag _allAssetsLoaded when it has finished.
      // The transition should fire automatically. To achieve this we can set FireAlways 
      // to true and define a Guard. A Guard is a condition that needs to be fulfilled 
      // to enable the transition. This way the game component automatically switches 
      // from the "Loading" state to the "Start" state once the loading is complete.
      var loadToStartTransition = new Transition
      {
        Name = "LoadingToStart",
        TargetState = startState,
        FireAlways = true,                // Always trigger the transition, if the guard allows it.
        Guard = () => _allAssetsLoaded,   // Enable the transition when _allAssetsLoaded is true.
      };
      loadingState.Transitions.Add(loadToStartTransition);

      // The remaining transition need to be triggered manually.

      // The "Start" screen will transition to the "Menu" screen.
      var startToMenuTransition = new Transition
      {
        Name = "StartToMenu",
        TargetState = menuState,
      };
      startState.Transitions.Add(startToMenuTransition);

      // The "Menu" screen can transition to the "Game" screen or to the "SubMenu".
      var menuToGameTransition = new Transition
      {
        Name = "MenuToGame",
        TargetState = gameState,
      };
      var menuToSubMenuTransition = new Transition
      {
        Name = "MenuToSubMenu",
        TargetState = subMenuState,
      };
      menuState.Transitions.Add(menuToGameTransition);
      menuState.Transitions.Add(menuToSubMenuTransition);

      // The "Game" screen will transition back to the "Menu" screen.
      var gameToMenuTransition = new Transition
      {
        Name = "GameToMenu",
        TargetState = menuState,
      };
      gameState.Transitions.Add(gameToMenuTransition);

      // The "SubMenu" can transition to back to the "Menu" screen.
      var subMenuToMenuTransition = new Transition
      {
        Name = "SubMenuToMenu",
        TargetState = menuState,
      };
      subMenuState.Transitions.Add(subMenuToMenuTransition);
    }