Last active
September 5, 2016 16:26
-
-
Save RevenantX/960b2d6624bc7beccd8332dac222e95c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
namespace Game.Shared.Helpers | |
{ | |
public class StateMachine<TStateEnum, TCommandEnum, TStateMachine> | |
where TStateEnum : struct, IComparable, IFormattable, IConvertible | |
where TCommandEnum : struct, IComparable, IFormattable, IConvertible | |
where TStateMachine : StateMachine<TStateEnum, TCommandEnum, TStateMachine> | |
{ | |
public interface IStateMachineOwner | |
{ | |
TStateMachine StateMachine { get; } | |
} | |
public abstract class BasicState | |
{ | |
private readonly IStateMachineOwner _owner; | |
public IStateMachineOwner Owner { get { return _owner; } } | |
protected BasicState(IStateMachineOwner owner) | |
{ | |
_owner = owner; | |
} | |
protected void SetState(TStateEnum state) | |
{ | |
_owner.StateMachine.SetState(state); | |
} | |
protected TCommandEnum CurrentCommand | |
{ | |
get { return _owner.StateMachine.CurrentCommand; } | |
} | |
protected void ChangeStateIfCommand(TCommandEnum command, TStateEnum targetState) | |
{ | |
if (_owner.StateMachine.CurrentCommand.Equals(command)) | |
{ | |
_owner.StateMachine.SetState(targetState); | |
} | |
} | |
protected bool CompareCommand(params TCommandEnum[] possible) | |
{ | |
for (int i = 0; i < possible.Length; i++) | |
if (possible[i].Equals(_owner.StateMachine.CurrentCommand)) | |
return true; | |
return false; | |
} | |
public virtual void Update(float deltaTime) { } | |
public virtual void OnCommand() { } | |
public virtual void OnEnter() { } | |
public virtual void OnExit() { } | |
} | |
public abstract class TransitionState : BasicState | |
{ | |
private float _timer; | |
private bool _forward; | |
public float TransitionTime = 1f; | |
public TStateEnum BackwardState { get; private set; } | |
public TStateEnum ForwardState { get; private set; } | |
public TCommandEnum[] BackCommands { get; private set; } | |
public TCommandEnum[] ForwardCommands { get; private set; } | |
public float Progress { get { return _timer / TransitionTime; } } | |
public float InversedProgress { get { return TransitionTime - (_timer / TransitionTime); } } | |
public float Timer { get { return _timer; } } | |
public bool Forward { get { return _forward; } } | |
protected TransitionState(IStateMachineOwner owner) : base(owner) | |
{ | |
} | |
public override void OnEnter() | |
{ | |
_timer = 0f; | |
} | |
public sealed override void OnCommand() | |
{ | |
if (CompareCommand(ForwardCommands)) | |
{ | |
if (!_forward && _timer > 0f) | |
{ | |
_timer = TransitionTime - _timer; | |
} | |
_forward = true; | |
OnStartTransition(_forward); | |
return; | |
} | |
if (CompareCommand(BackCommands)) | |
{ | |
if (_forward && _timer > 0) | |
{ | |
_timer = TransitionTime - _timer; | |
} | |
_forward = false; | |
OnStartTransition(_forward); | |
} | |
} | |
protected virtual void OnStartTransition(bool forward) | |
{ | |
} | |
public void SetBackwardCommands(TStateEnum backwardState, params TCommandEnum[] commands) | |
{ | |
BackwardState = backwardState; | |
BackCommands = commands; | |
} | |
public void SetForwardCommands(TStateEnum forwardState, params TCommandEnum[] commands) | |
{ | |
ForwardState = forwardState; | |
ForwardCommands = commands; | |
} | |
public override void Update(float deltaTime) | |
{ | |
_timer += deltaTime; | |
if (_timer >= TransitionTime) | |
{ | |
_timer = TransitionTime; | |
SetState(_forward ? ForwardState : BackwardState); | |
} | |
} | |
} | |
private BasicState _currentState; | |
private TStateEnum _currentStateName; | |
private TCommandEnum _currentCommand; | |
private readonly Dictionary<TStateEnum, BasicState> _states = new Dictionary<TStateEnum, BasicState>(); | |
public TStateEnum CurrentStateName | |
{ | |
get { return _currentStateName; } | |
} | |
public BasicState CurrentState | |
{ | |
get { return _currentState; } | |
} | |
public TCommandEnum CurrentCommand | |
{ | |
get { return _currentCommand; } | |
} | |
public void SetState(TStateEnum stateName, BasicState state) | |
{ | |
_states[stateName] = state; | |
} | |
public void CallCommand(TCommandEnum command) | |
{ | |
if (!command.Equals(_currentCommand)) | |
{ | |
_currentCommand = command; | |
_currentState.OnCommand(); | |
} | |
} | |
public void Update(float deltaTime) | |
{ | |
_currentState.Update(deltaTime); | |
} | |
public void Start(TCommandEnum startCommand, TStateEnum startState) | |
{ | |
_currentCommand = startCommand; | |
_currentStateName = startState; | |
_currentState = _states[startState]; | |
_currentState.OnEnter(); | |
_currentState.OnCommand(); | |
} | |
public void SetState(TStateEnum state) | |
{ | |
_currentState.OnExit(); | |
_currentStateName = state; | |
_currentState = _states[state]; | |
_currentState.OnEnter(); | |
_currentState.OnCommand(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment