Improved FSM

This commit is contained in:
knowledgenude 2021-02-14 19:21:26 -03:00
parent 49a599dc66
commit 0ee35adc81

View file

@ -1,49 +1,25 @@
package armory.system; package armory.system;
class FSM { class FSM<T> {
var state: Null<State>; final transitions = new Array<Transition<T>>();
var nextState: Null<State>; final tempTransitions = new Array<Transition<T>>();
var transitions = new Array<Transition>(); var state: Null<State<T>>;
var tempTransitions = new Array<Transition>();
var entered = false; var entered = false;
public function new() {} public function new() {}
/** public function bindTransition(canEnter: Void -> Bool, fromState: State<T>, toState: State<T>) {
* Set the initial / current state of the FSM and return it final transition = new Transition<T>(canEnter, fromState, toState);
* @param state The state to be set transitions.push(transition);
* @return State syncTransitions();
**/ }
public function setState(state: State) {
public function setInitState(state: State<T>) {
this.state = state; this.state = state;
syncTransitions(); syncTransitions();
return state;
} }
/** public function update() {
* Bind multiple transitions to the specified state
* @param canEnter The function that returns true or false to enter the transition
* @param toState The next state the transiiton will return
* @param fromStates The states that are allowed to be changed by the next state
* @return Void
**/
public function bindTransitions(canEnter: Void -> Bool, toState: State, fromStates: Array<State>) {
for (s in fromStates) {
transitions.push(new Transition(canEnter, s, toState));
}
syncTransitions();
}
function syncTransitions() {
tempTransitions = [];
for (t in transitions) {
if (t.isConnected(state)) tempTransitions.push(t);
}
}
public function run() {
if (!entered) { if (!entered) {
state.onEnter(); state.onEnter();
entered = true; entered = true;
@ -51,45 +27,48 @@ class FSM {
state.onUpdate(); state.onUpdate();
for (t in tempTransitions) { for (transition in tempTransitions) {
if (t.canEnter()) { if (transition.canEnter()) {
nextState = t.getNextState();
state.onExit(); state.onExit();
state = nextState; state = transition.toState;
entered = false; entered = false;
syncTransitions(); syncTransitions();
break; break;
} }
} }
} }
}
class Transition { public function syncTransitions() {
final func: Void -> Bool; tempTransitions.resize(0);
final from: State;
final to: State;
public function new(func: Void -> Bool, from: State, to: State) { for (transition in transitions) {
this.func = func; if (transition.fromState == state) tempTransitions.push(transition);
this.from = from; }
this.to = to;
}
public function canEnter() {
return func();
}
public function isConnected(state: State) {
return from == state;
}
public function getNextState() {
return to;
} }
} }
interface State { class Transition<T> {
function onEnter(): Void; public final canEnter: Void -> Bool;
function onUpdate(): Void; public final fromState: State<T>;
function onExit(): Void; public final toState: State<T>;
public function new(canEnter: Void -> Bool, fromState: State<T>, toState: State<T>) {
this.canEnter = canEnter;
this.fromState = fromState;
this.toState = toState;
}
}
class State<T> {
final owner: T;
public function new(owner: T) {
this.owner = owner;
}
public function onEnter() {}
public function onUpdate() {}
public function onExit() {}
} }