Skip to content

Instantly share code, notes, and snippets.

@RevenantX
Created August 17, 2016 16:10
Show Gist options
  • Save RevenantX/8ad9595f81c824f258b8b23b945eea05 to your computer and use it in GitHub Desktop.
Save RevenantX/8ad9595f81c824f258b8b23b945eea05 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
namespace Game.Shared.Helpers
{
public interface IStateMachineOwner
{
StateMachine StateMachine { get; }
}
public interface IState
{
void Update(float deltaTime);
void OnCommand(string command);
void OnEnter();
void OnExit();
}
public abstract class BasicState<T> : IState where T : IStateMachineOwner
{
private readonly T _owner;
public T Owner { get { return _owner; } }
protected BasicState(T owner)
{
_owner = owner;
}
protected void SetState(string state)
{
_owner.StateMachine.SetState(state);
}
protected string CurrentCommand
{
get { return _owner.StateMachine.CurrentCommand; }
}
public virtual void Update(float deltaTime) { }
public virtual void OnCommand(string command) { }
public virtual void OnEnter() { }
public virtual void OnExit() { }
}
public abstract class TransitionState<T> : BasicState<T> where T : IStateMachineOwner
{
private float _timer;
private bool _forward;
public float TransitionTime = 1f;
public string BackwardState { get; private set; }
public string ForwardState { get; private set; }
public string[] BackCommands { get; private set; }
public string[] ForwardCommands { get; private set; }
public float Progress { get { return _timer / TransitionTime; } }
public float Timer { get { return _timer; } }
public bool Forward { get { return _forward; } }
protected TransitionState(T owner) : base(owner)
{
}
public override void OnEnter()
{
_timer = 0f;
}
public sealed override void OnCommand(string command)
{
for (int i = 0; i < ForwardCommands.Length; i++)
{
if (ForwardCommands[i].Equals(command))
{
if (!_forward && _timer > 0f)
{
_timer = TransitionTime - _timer;
}
_forward = true;
OnStartTransition(_forward);
return;
}
}
for (int i = 0; i < ForwardCommands.Length; i++)
{
if (BackCommands[i].Equals(command))
{
if (_forward && _timer > 0)
{
_timer = TransitionTime - _timer;
}
_forward = false;
OnStartTransition(_forward);
return;
}
}
}
protected virtual void OnStartTransition(bool forward)
{
}
public void SetBackwardCommands(string backwardState, params string[] commands)
{
BackwardState = backwardState;
BackCommands = commands;
}
public void SetForwardCommands(string forwardState, params string[] commands)
{
ForwardState = forwardState;
ForwardCommands = commands;
}
public override void Update(float deltaTime)
{
_timer += deltaTime;
if (_timer >= TransitionTime)
{
_timer = TransitionTime;
SetState(_forward ? ForwardState : BackwardState);
}
}
}
public class StateMachine
{
private IState _currentState;
private string _currentStateName;
private string _currentCommand;
private readonly Dictionary<string, IState> _states = new Dictionary<string, IState>();
public string CurrentStateName
{
get { return _currentStateName; }
}
public IState CurrentState
{
get { return _currentState; }
}
public string CurrentCommand
{
get { return _currentCommand; }
}
public void SetState(string stateName, IState state)
{
_states[stateName] = state;
}
public void CallCommand(string command)
{
_currentCommand = command;
_currentState.OnCommand(command);
}
public void Update(float deltaTime)
{
_currentState.Update(deltaTime);
}
public void Start(string startCommand, string startState)
{
_currentCommand = startCommand;
_currentStateName = startState;
_currentState = _states[startState];
_currentState.OnEnter();
_currentState.OnCommand(startCommand);
}
public void SetState(string state)
{
_currentState.OnExit();
_currentStateName = state;
_currentState = _states[state];
_currentState.OnEnter();
_currentState.OnCommand(_currentCommand);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment