mirror of
https://github.com/MaddyThorson/StrawberryBF.git
synced 2024-11-28 16:58:56 +08:00
StateMachine Component
This commit is contained in:
parent
aed77272ac
commit
be9e1cd877
137
src/Components/Logic/StateMachine.bf
Normal file
137
src/Components/Logic/StateMachine.bf
Normal file
|
@ -0,0 +1,137 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Strawberry
|
||||
{
|
||||
public class StateMachine<TIndex> : Component where TIndex : struct, IHashable
|
||||
{
|
||||
private Dictionary<TIndex, State> states = new Dictionary<TIndex, State>() ~ delete _;
|
||||
private TIndex state;
|
||||
private bool inStateCall;
|
||||
|
||||
public TIndex PreviousState { get; private set; }
|
||||
public TIndex NextState { get; private set; }
|
||||
|
||||
public this(TIndex startState)
|
||||
: base(true, false)
|
||||
{
|
||||
NextState = PreviousState = state = startState;
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
for (let s in states.Values)
|
||||
delete s;
|
||||
}
|
||||
|
||||
public override void Started()
|
||||
{
|
||||
CallEnter();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
CallUpdate();
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Add(TIndex state, delegate TIndex() enter = null, delegate TIndex() update = null, delegate TIndex() exit = null)
|
||||
{
|
||||
let s = new State();
|
||||
s.Enter = enter;
|
||||
s.Update = update;
|
||||
s.Exit = exit;
|
||||
states[state] = s;
|
||||
}
|
||||
|
||||
public TIndex State
|
||||
{
|
||||
get => state;
|
||||
set => Set(value);
|
||||
}
|
||||
|
||||
private Result<bool> Set(TIndex to)
|
||||
{
|
||||
if (inStateCall)
|
||||
Runtime.FatalError("Cannot set State directly from inside a State Enter/Exit/Update call. Return the desired State change instead.");
|
||||
|
||||
if (to != state)
|
||||
{
|
||||
NextState = to;
|
||||
if (CallExit())
|
||||
return true;
|
||||
|
||||
PreviousState = state;
|
||||
state = to;
|
||||
|
||||
CallEnter();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CallEnter()
|
||||
{
|
||||
let s = states[state];
|
||||
if (s != null)
|
||||
{
|
||||
inStateCall = true;
|
||||
let set = s.Enter();
|
||||
inStateCall = false;
|
||||
return Set(set);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CallUpdate()
|
||||
{
|
||||
let s = states[state];
|
||||
if (s != null)
|
||||
{
|
||||
inStateCall = true;
|
||||
let set = s.Update();
|
||||
inStateCall = false;
|
||||
return Set(set);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CallExit()
|
||||
{
|
||||
let s = states[state];
|
||||
if (s != null)
|
||||
{
|
||||
inStateCall = true;
|
||||
let set = s.Exit();
|
||||
inStateCall = false;
|
||||
return Set(set);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public class State
|
||||
{
|
||||
public delegate TIndex() Enter;
|
||||
public delegate TIndex() Update;
|
||||
public delegate TIndex() Exit;
|
||||
|
||||
public ~this()
|
||||
{
|
||||
if (Enter != null)
|
||||
delete Enter;
|
||||
if (Update != null)
|
||||
delete Update;
|
||||
if (Exit != null)
|
||||
delete Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,33 @@ namespace Strawberry
|
|||
RemoveOnComplete = destroyOnComplete;
|
||||
}
|
||||
|
||||
public override void Started()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
value -= Time.Delta;
|
||||
if (value <= 0)
|
||||
{
|
||||
value = 0;
|
||||
Active = false;
|
||||
|
||||
OnComplete?.Invoke();
|
||||
if (RemoveOnComplete)
|
||||
RemoveSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public float Value
|
||||
{
|
||||
[Inline]
|
||||
|
@ -47,23 +74,6 @@ namespace Strawberry
|
|||
Active = false;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
value -= Time.Delta;
|
||||
if (value <= 0)
|
||||
{
|
||||
value = 0;
|
||||
Active = false;
|
||||
|
||||
OnComplete?.Invoke();
|
||||
if (RemoveOnComplete)
|
||||
RemoveSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public implicit operator bool(Timer timer)
|
||||
{
|
||||
return timer.value > 0;
|
|
@ -15,30 +15,19 @@ namespace Strawberry
|
|||
Visible = visible;
|
||||
}
|
||||
|
||||
public void Added(Entity entity)
|
||||
private void Added(Entity entity)
|
||||
{
|
||||
Entity = entity;
|
||||
}
|
||||
|
||||
public void Removed()
|
||||
private void Removed()
|
||||
{
|
||||
Entity = null;
|
||||
}
|
||||
|
||||
public virtual void Started()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Draw()
|
||||
{
|
||||
|
||||
}
|
||||
public abstract void Started();
|
||||
public abstract void Update();
|
||||
public abstract void Draw();
|
||||
|
||||
[Inline]
|
||||
public void RemoveSelf()
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace Strawberry
|
|||
{
|
||||
components.Remove(c);
|
||||
Scene.[Friend]UntrackComponent(c);
|
||||
c.Removed();
|
||||
c.[Friend]Removed();
|
||||
delete c;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace Strawberry
|
|||
{
|
||||
components.Add(c);
|
||||
Scene.[Friend]TrackComponent(c);
|
||||
c.Added(this);
|
||||
c.[Friend]Added(this);
|
||||
}
|
||||
|
||||
toAdd.Clear();
|
||||
|
|
|
@ -39,7 +39,6 @@ namespace Strawberry
|
|||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
MovedByGeometry = Point.Zero;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user