Skip to content

Instantly share code, notes, and snippets.

@eka
Created November 23, 2020 04:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eka/5f88e80142fe9569687797cde387d806 to your computer and use it in GitHub Desktop.
Save eka/5f88e80142fe9569687797cde387d806 to your computer and use it in GitHub Desktop.
using Godot;
using System;
public abstract class State : Node
{
[Signal]
public delegate void Finished(string nextState);
[Signal]
public delegate void Stack(string nextState);
public virtual void Enter(Node host)
{
}
public virtual void Exit(Node host)
{
}
public virtual void HandleInput(Node host, InputEvent @event)
{
}
public virtual void UnhandledInput(Node host, InputEvent @event)
{
}
public virtual void Update(Node host, float delta)
{
}
}
using Godot;
using System;
using System.Collections.Generic;
public class StateMachine : Node
{
private Godot.Collections.Dictionary<string, Node> _statesMap = new Godot.Collections.Dictionary<string, Node>();
private State _currentState;
public string CurrentState => nameof(_currentState);
private Stack<string> _statesStack = new Stack<string>();
public override void _PhysicsProcess(float delta)
{
_currentState?.Update(this, delta);
}
public override void _Input(InputEvent @event)
{
_currentState?.HandleInput(this, @event);
}
public override void _UnhandledInput(InputEvent @event)
{
_currentState?.UnhandledInput(this, @event);
}
public void ChangeState(string stateName, bool stacked=false)
{
if(_statesStack.Count > 0 && !stacked)
{
_statesStack.Pop();
}
if (stateName != "__previous__")
{
_statesStack.Push(stateName);
}
// Get the state object
var newState = States(_statesStack.Peek());
// Call exit on current state
_currentState?.Exit(this);
// Call enter on new state
if (stateName != "__previous__")
{
newState.Enter(this);
}
// Set current state on new state
_currentState = newState;
}
private State States(string stateName)
{
return (State) _statesMap[stateName];
}
public override void _Ready()
{
foreach (Node node in GetChildren())
{
_statesMap[node.Name] = node;
node.Connect("Finished", this, "_on_State_changed");
node.Connect("Stack", this, "_on_State_stacked");
}
}
// Signals
public void _on_State_changed(string nextState)
{
GD.Print($"On State Changed: {nextState}");
ChangeState(nextState);
}
public void _on_State_stacked(string nextState)
{
GD.Print($"On State Stacked: {nextState}");
ChangeState(nextState, stacked: true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment