Skip to content

Changing States

Sohom Sahaun edited this page Nov 12, 2021 · 6 revisions

We can change the state of a SnowState instance using the .change() method.

 

NOTE:
The following examples assume that the system fsm is in state A, and we are changing that to state B.

 

Calling fsm.change() changes the state immediately, but it still runs the rest of the event. To prevent the event from running any following code, you can end the event immediately when changing the state.

// In state "A"
if (some_condition) {
  fsm.change("B");
  return;
}

or simply:

// In state "A"
if (some_condition) return fsm.change("B");

 

When changing a state, we can:

 

Using a state's leave/enter event

The default leave/enter events (defined in the states themselves) are executed when we do not use the optional arguments in the .change() method. Obviously, this is the default behavior.

 

Example:

// In state "A"
fsm.change("B",
  undefined,
  undefined
);

or simply

// In state "A"
fsm.change("B");

This does the following things (in order):

  1. Executes the leave event of state A
  2. Changes the state of fsm from A to B
  3. Executes the enter event of state B

 

Using custom leave/enter event

We can choose to execute custom leave/enter events by overriding the default ones. This is done using the two optional arguments in the .change() method.
leave_func lets us execute a custom function instead of the leave event of state A.
enter_func lets us execute a custom function instead of the enter event of state B.

Example:

// In state "A"
fsm.change("B",
  undefined,
  function() {
    do_something();
  }
);

This does the following things (in order):

  1. Executes the leave event of state A
  2. Changes the state of fsm from A to B
  3. Executes a function, which:
    1. Executes a function do_something

Example:

// In state "A"
fsm.change("B",
  function() {
    do_something();
  },
  function() {
    do_something_else();
  }
);

This does the following things (in order):

  1. Executes a function, which:
    1. Executes a function do_something
  2. Changes the state of fsm from A to B
  3. Executes a function, which:
    1. Executes a function do_something_else

Overriding can also be used to skip a state's leave/enter event. We can pass an empty function.

Example:

// In state "A"
fsm.change("B",
  undefined,
  function() {}
);

This skips the enter event of state B.

 

Extending a state's leave/enter event

Sometimes, we want to execute some code on top of a state's leave/enter event. To do so, we need to fetch the state's leave/enter event using the .event_get_current_function() method, and then we can call it wherever we want in the function.
Calling .leave() or .enter() doesn't work here since these are overridden already!

Example:

// In state "A"
fsm.change("B",
  undefined,
  function() {
    var _func = event_get_current_function();
    do_something_before_enter();
    _func();
    do_something_after_enter();
  }
);

This does the following things (in order):

  1. Executes the leave event for state A
  2. Changes the state of fsm from A to B
  3. Executes a function, which:
    1. Gets the enter event of state B and stores it in a local variable _func
    2. Executes a function do_something_before_enter
    3. Executes the enter event of state B
    4. Executes a function do_something_after_enter