Skip to content

Commit ece7a86

Browse files
committed
Merge branch 'feature/builder' of https://github.com/UnterrainerInformatik/FiniteStateMachine into feature/builder
2 parents 8efee62 + 25a440d commit ece7a86

File tree

8 files changed

+219
-50
lines changed

8 files changed

+219
-50
lines changed

README.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,60 +87,60 @@ private Hero hero;
8787
public void main() {
8888
horizontalMachine = Fsm.Builder<HState, HTrigger, GameTime>(STANDING)
8989
.State(STANDING)
90-
.TransisionTo(WALKING_LEFT).On(LEFT_PRESSED)
91-
.TransisionTo(WALKING_RIGHT).On(RIGHT_PRESSED)
90+
.TransitionTo(WALKING_LEFT).On(LEFT_PRESSED)
91+
.TransitionTo(WALKING_RIGHT).On(RIGHT_PRESSED)
9292
.OnEnter(e => {
9393
ConsoleOut();
9494
hero.HAnimation = HAnimation.STANDING;
9595
hero.delayTimer.StopAndReset();
9696
})
9797
.State(WALKING_LEFT)
98-
.TransisionTo(WALKING_DELAY_LEFT).On(LEFT_RELEASED)
98+
.TransitionTo(WALKING_DELAY_LEFT).On(LEFT_RELEASED)
9999
.OnEnter(e => {
100100
ConsoleOut();
101101
hero.HAnimation = HAnimation.WALK_LEFT;
102102
hero.delayTimer.StopAndReset();
103103
})
104104
.State(WALKING_RIGHT)
105-
.TransisionTo(WALKING_DELAY_RIGHT).On(RIGHT_RELEASED)
105+
.TransitionTo(WALKING_DELAY_RIGHT).On(RIGHT_RELEASED)
106106
.OnEnter(e => {
107107
ConsoleOut();
108108
hero.HAnimation = HAnimation.WALK_RIGHT;
109109
hero.delayTimer.StopAndReset();
110110
})
111111
.State(WALKING_DELAY_LEFT)
112-
.TransisionTo(WALKING_RIGHT).On(RIGHT_PRESSED)
113-
.TransisionTo(RUNNING_LEFT).On(LEFT_PRESSED)
112+
.TransitionTo(WALKING_RIGHT).On(RIGHT_PRESSED)
113+
.TransitionTo(RUNNING_LEFT).On(LEFT_PRESSED)
114114
.OnEnter(e => {
115115
hero.delayTimer.Start();
116116
})
117117
.Update(a => {
118118
hero.delayTimer.Update(a.GameTime);
119119
if(hero.delayTimer) {
120-
horizontalMachine.TransitionTo(STANDING);
120+
horizontalMachine.JumpTo(STANDING);
121121
}
122122
})
123123
.State(WALKING_DELAY_RIGHT)
124-
.TransisionTo(WALKING_LEFT).On(LEFT_PRESSED)
125-
.TransisionTo(RUNNING_RIGHT).On(RIGHT_PRESSED)
124+
.TransitionTo(WALKING_LEFT).On(LEFT_PRESSED)
125+
.TransitionTo(RUNNING_RIGHT).On(RIGHT_PRESSED)
126126
.OnEnter(e => {
127127
hero.delayTimer.Start();
128128
})
129129
.Update(a => {
130130
hero.delayTimer.Update(a.GameTime);
131131
if(hero.delayTimer) {
132-
horizontalMachine.TransitionTo(STANDING);
132+
horizontalMachine.JumpTo(STANDING);
133133
}
134134
})
135135
.State(RUNNING_LEFT)
136-
.TransisionTo(STANDING).On(LEFT_RELEASED)
136+
.TransitionTo(STANDING).On(LEFT_RELEASED)
137137
.OnEnter(e => {
138138
ConsoleOut();
139139
hero.HAnimation = HAnimation.RUNNING_LEFT;
140140
hero.delayTimer.StopAndReset();
141141
})
142142
.State(RUNNING_RIGHT)
143-
.TransisionTo(STANDING).On(RIGHT_RELEASED)
143+
.TransitionTo(STANDING).On(RIGHT_RELEASED)
144144
.OnEnter(e => {
145145
ConsoleOut();
146146
hero.HAnimation = HAnimation.RUNNING_RIGHT;
@@ -151,22 +151,22 @@ public void main() {
151151

152152
verticalMachine = Fsm.Builder<VState, VTrigger, GameTime>(STANDING)
153153
.State(STANDING)
154-
.TransisionTo(DUCKING).On(DOWN_PRESSED)
155-
.TransisionTo(JUMPING).On(UP_PRESSED)
154+
.TransitionTo(DUCKING).On(DOWN_PRESSED)
155+
.TransitionTo(JUMPING).On(UP_PRESSED)
156156
.OnEnter(e => {
157157
ConsoleOut();
158158
hero.VAnimation = VAnimation.IDLE;
159159
})
160160
.OnExit(Console.Out.WriteLine($"From [{e.From}] with [{e.Input}] to [{e.To}]"))
161161
.State(DUCKING)
162-
.TransisionTo(STANDING).On(DOWN_RELEASED)
162+
.TransitionTo(STANDING).On(DOWN_RELEASED)
163163
.OnEnter(e => {
164164
ConsoleOut();
165165
hero.VAnimation = VAnimation.DUCKING;
166166
})
167167
.OnExit(ConsoleOut)
168168
.State(JUMPING)
169-
.TransisionTo(DIVING).On(DOWN_PRESSED)
169+
.TransitionTo(DIVING).On(DOWN_PRESSED)
170170
.OnEnter(e => {
171171
ConsoleOut();
172172
hero.VAnimation = VAnimation.JUMPING;
@@ -178,7 +178,7 @@ public void main() {
178178
verticalMachine.TransitionTo(DESCENDING);
179179
})
180180
.State(DESCENDING)
181-
.TransisionTo(DIVING).On(DOWN_PRESSED)
181+
.TransitionTo(DIVING).On(DOWN_PRESSED)
182182
.OnEnter(e => {
183183
ConsoleOut();
184184
hero.VAnimation = VAnimation.DESCENDING;
@@ -192,7 +192,7 @@ public void main() {
192192
}
193193
})
194194
.State(DIVING)
195-
.TransisionTo(DESCENDING).On(DOWN_RELEASED)
195+
.TransitionTo(DESCENDING).On(DOWN_RELEASED)
196196
.OnEnter(e => {
197197
ConsoleOut();
198198
hero.VAnimation = VAnimation.DIVING;
@@ -257,19 +257,19 @@ private Dictionary<Button, Fsm<State, Trigger, GameTime>> buttonMachines = new
257257
private void CreateMachineFor(Button button)
258258
buttonMachines.Add(button, Fsm.Builder<State, Trigger, GameTime>(IDLE)
259259
.State(IDLE)
260-
.TransisionTo(OVER).On(MOUSE_OVER)
260+
.TransitionTo(OVER).On(MOUSE_OVER)
261261
.OnEnter(e => {
262262
button.State = ButtonState.IDLE;
263263
})
264264
.State(OVER)
265-
.TransisionTo(IDLE).On(MOUSE_LEAVE)
266-
.TransisionTo(PRESSED).On(MOUSE_CLICKED)
265+
.TransitionTo(IDLE).On(MOUSE_LEAVE)
266+
.TransitionTo(PRESSED).On(MOUSE_CLICKED)
267267
.OnEnter(e => {
268268
button.State = ButtonState.OVER;
269269
})
270270
.State(PRESSED)
271-
.TransisionTo(IDLE).On(MOUSE_LEAVE).If(button.Kind == Kind.FLIPBACK)
272-
.TransisionTo(REFRESHING).On(MOUSE_RELEASED)
271+
.TransitionTo(IDLE).On(MOUSE_LEAVE).If(button.Kind == Kind.FLIPBACK)
272+
.TransitionTo(REFRESHING).On(MOUSE_RELEASED)
273273
.OnEnter(e => {
274274
button.State = ButtonState.DOWN;
275275
})
@@ -282,7 +282,7 @@ private void CreateMachineFor(Button button)
282282
.Update(a => {
283283
if(button.RefreshTimer.Value <= 0F) {
284284
button.RefreshTimer.StopAndReset();
285-
machine.TransitionTo(IDLE);
285+
machine.JumpTo(IDLE);
286286
}
287287
})
288288
.Build();

StateMachine/Fsm.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public Fsm<TState, TTrigger, TData> Add(Transition<TState, TTrigger, TData> t)
124124
return this;
125125
}
126126

127-
public void TransitionTo(TState state, bool isPop = false)
127+
public void JumpTo(TState state, bool isPop = false)
128128
{
129129
State<TState, TTrigger, TData> s;
130130
if (Model.States.TryGetValue(state, out s))

StateMachine/NUnitTests/FluentSyntaxTest1.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,20 @@ private enum State
8888
OVER,
8989
PRESSED,
9090
REFRESHING
91-
};
91+
}
9292

9393
private enum Trigger
9494
{
9595
MOUSE_CLICKED,
9696
MOUSE_RELEASED,
9797
MOUSE_OVER,
9898
MOUSE_LEAVE
99-
};
99+
}
100100

101101
private readonly Dictionary<Button, Fsm<State, Trigger, float>> buttonMachines =
102102
new Dictionary<Button, Fsm<State, Trigger, float>>();
103103

104-
private void main()
104+
private void Main()
105105
{
106106
Hero hero = new Hero();
107107
CreateMachineFor(Fsm<State, Trigger>.Builder(State.IDLE), new Button(), hero);
@@ -113,17 +113,17 @@ private void CreateMachineFor(BuilderFluent<State, Trigger, float> builder, Butt
113113
buttonMachines.Add(button, builder
114114
.State(State.IDLE)
115115
.TransitionTo(State.OVER).On(Trigger.MOUSE_OVER)
116-
.OnEnter(t => { button.State = Button.ButtonState.IDLE; })
116+
.OnEnter(t => button.State = Button.ButtonState.IDLE)
117117
.State(State.OVER)
118118
.TransitionTo(State.IDLE).On(Trigger.MOUSE_LEAVE)
119119
.TransitionTo(State.PRESSED).On(Trigger.MOUSE_CLICKED)
120-
.OnEnter(t => { button.State = Button.ButtonState.OVER; })
120+
.OnEnter(t => button.State = Button.ButtonState.OVER)
121121
.State(State.PRESSED)
122122
.TransitionTo(State.IDLE)
123123
.On(Trigger.MOUSE_LEAVE)
124124
.If(a => button.Kind == Button.ButtonKind.FLIPBACK)
125125
.TransitionTo(State.REFRESHING).On(Trigger.MOUSE_RELEASED)
126-
.OnEnter(t => { button.State = Button.ButtonState.DOWN; })
126+
.OnEnter(t => button.State = Button.ButtonState.DOWN)
127127
.State(State.REFRESHING)
128128
.OnEnter(t =>
129129
{
@@ -136,7 +136,7 @@ private void CreateMachineFor(BuilderFluent<State, Trigger, float> builder, Butt
136136
if (button.RefreshTimer.Value <= 0F)
137137
{
138138
button.RefreshTimer.StopAndReset();
139-
args.Machine.TransitionTo(State.IDLE);
139+
args.Machine.JumpTo(State.IDLE);
140140
}
141141
})
142142
.Build());
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// ***************************************************************************
2+
// This is free and unencumbered software released into the public domain.
3+
//
4+
// Anyone is free to copy, modify, publish, use, compile, sell, or
5+
// distribute this software, either in source code form or as a compiled
6+
// binary, for any purpose, commercial or non-commercial, and by any
7+
// means.
8+
//
9+
// In jurisdictions that recognize copyright laws, the author or authors
10+
// of this software dedicate any and all copyright interest in the
11+
// software to the public domain. We make this dedication for the benefit
12+
// of the public at large and to the detriment of our heirs and
13+
// successors. We intend this dedication to be an overt act of
14+
// relinquishment in perpetuity of all present and future rights to this
15+
// software under copyright law.
16+
//
17+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20+
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21+
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22+
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
// OTHER DEALINGS IN THE SOFTWARE.
24+
//
25+
// For more information, please refer to <http://unlicense.org>
26+
// ***************************************************************************
27+
28+
using System;
29+
using NUnit.Framework;
30+
31+
namespace StateMachine.NUnitTests
32+
{
33+
public class FluentTests
34+
{
35+
private enum State
36+
{
37+
IDLE,
38+
OVER,
39+
PRESSED,
40+
REFRESHING
41+
}
42+
43+
private enum Trigger
44+
{
45+
MOUSE_CLICKED,
46+
MOUSE_RELEASED,
47+
MOUSE_OVER,
48+
MOUSE_LEAVE
49+
}
50+
51+
private class Button
52+
{
53+
public bool IsActivated { get; set; }
54+
public State BtnState { get; set; }
55+
public State OldState { get; set; } = State.IDLE;
56+
public float RefreshTimer { get; set; } = 1F;
57+
58+
public int UpdateCounter { get; set; }
59+
}
60+
61+
[Test]
62+
[Category("StateMachine.FluentTests.OnMethods")]
63+
public void OnMethodTests()
64+
{
65+
var button = new Button();
66+
67+
var m = Fsm<State, Trigger>.Builder(State.IDLE)
68+
.State(State.IDLE)
69+
.TransitionTo(State.OVER).On(Trigger.MOUSE_OVER)
70+
.OnEnter(t => button.BtnState = State.IDLE)
71+
.OnExit(t => button.OldState = button.BtnState)
72+
.State(State.OVER)
73+
.TransitionTo(State.IDLE).On(Trigger.MOUSE_LEAVE)
74+
.TransitionTo(State.PRESSED).On(Trigger.MOUSE_CLICKED)
75+
.OnEnter(t => button.BtnState = State.OVER)
76+
.OnExit(t => button.OldState = button.BtnState)
77+
.Update(a => button.UpdateCounter = button.UpdateCounter + 1)
78+
.State(State.PRESSED)
79+
.TransitionTo(State.IDLE).On(Trigger.MOUSE_LEAVE)
80+
.TransitionTo(State.REFRESHING).On(Trigger.MOUSE_RELEASED).If(a => button.IsActivated)
81+
.OnEnter(t => button.BtnState = State.PRESSED)
82+
.OnExit(t => button.OldState = button.BtnState)
83+
.State(State.REFRESHING)
84+
.OnEnter(t => button.BtnState = State.REFRESHING)
85+
.OnExit(t => button.OldState = button.BtnState)
86+
.Update(a =>
87+
{
88+
button.RefreshTimer -= a.Data;
89+
if (button.RefreshTimer <= 0F)
90+
{
91+
button.RefreshTimer = 0F;
92+
a.Machine.JumpTo(State.IDLE); // or m.JumpTo(State.IDLE);
93+
}
94+
button.UpdateCounter = button.UpdateCounter + 1;
95+
})
96+
.Build();
97+
98+
m.Update(2F); // Should do nothing.
99+
Assert.That(m.Current.Identifier, Is.EqualTo(State.IDLE));
100+
m.Trigger(Trigger.MOUSE_CLICKED);
101+
Assert.That(m.Current.Identifier, Is.EqualTo(State.IDLE));
102+
m.Trigger(Trigger.MOUSE_LEAVE);
103+
Assert.That(m.Current.Identifier, Is.EqualTo(State.IDLE));
104+
m.Trigger(Trigger.MOUSE_RELEASED);
105+
Assert.That(m.Current.Identifier, Is.EqualTo(State.IDLE));
106+
m.Trigger(Trigger.MOUSE_OVER);
107+
Assert.That(m.Current.Identifier, Is.EqualTo(State.OVER));
108+
Assert.That(button.BtnState, Is.EqualTo(State.OVER));
109+
Assert.That(button.OldState, Is.EqualTo(State.IDLE));
110+
m.Trigger(Trigger.MOUSE_CLICKED);
111+
Assert.That(m.Current.Identifier, Is.EqualTo(State.PRESSED));
112+
Assert.That(button.BtnState, Is.EqualTo(State.PRESSED));
113+
Assert.That(button.OldState, Is.EqualTo(State.OVER));
114+
m.Trigger(Trigger.MOUSE_RELEASED); // Button is deactivated.
115+
Assert.That(m.Current.Identifier, Is.EqualTo(State.PRESSED));
116+
Assert.That(button.BtnState, Is.EqualTo(State.PRESSED));
117+
Assert.That(button.OldState, Is.EqualTo(State.OVER));
118+
button.IsActivated = true;
119+
m.Trigger(Trigger.MOUSE_RELEASED); // Now it's activated.
120+
Assert.That(m.Current.Identifier, Is.EqualTo(State.REFRESHING));
121+
Assert.That(button.BtnState, Is.EqualTo(State.REFRESHING));
122+
Assert.That(button.OldState, Is.EqualTo(State.PRESSED));
123+
m.Update(.5F); // No transition yet...
124+
Assert.That(m.Current.Identifier, Is.EqualTo(State.REFRESHING));
125+
Assert.That(button.BtnState, Is.EqualTo(State.REFRESHING));
126+
Assert.That(button.OldState, Is.EqualTo(State.PRESSED));
127+
m.Update(.5F); // But now.
128+
Assert.That(m.Current.Identifier, Is.EqualTo(State.IDLE));
129+
Assert.That(button.BtnState, Is.EqualTo(State.IDLE));
130+
Assert.That(button.OldState, Is.EqualTo(State.REFRESHING));
131+
132+
// Update was triggered twice over all states.
133+
Assert.That(button.UpdateCounter, Is.EqualTo(2F));
134+
}
135+
}
136+
}

0 commit comments

Comments
 (0)