2727
2828using System ;
2929using System . Collections . Generic ;
30- using JetBrains . Annotations ;
3130using Microsoft . Xna . Framework ;
3231using MonoGameStateMachine . Api ;
3332using StateMachine ;
3433using StateMachine . Events ;
3534
3635namespace MonoGameStateMachine
3736{
38- [ PublicAPI ]
39- public class Fsm < TS , TT > : Fsm < TS , TT , GameTime >
40- {
41- private GameTime gt = new GameTime ( ) ;
42-
43- public Dictionary < Tuple < TS , TS > , List < Timer < TS > > > AfterEntries { get ; set ; } = new Dictionary < Tuple < TS , TS > , List < Timer < TS > > > ( ) ;
44- public List < Timer < TS > > GlobalAfterEntries { get ; set ; } = new List < Timer < TS > > ( ) ;
45-
46- public Fsm ( FsmModel < TS , TT , GameTime > model ) : base ( model )
47- {
48- }
49-
50- public Fsm ( State < TS , TT , GameTime > current , bool stackEnabled = false ) : base ( current , stackEnabled )
51- {
52- }
53-
54- /// <summary>
55- /// Gets you a builder for a Finite-State-Machine (FSM).
56- /// </summary>
57- /// <param name="startState">The start state's key.</param>
58- /// <returns></returns>
59- public new static BuilderFluent < TS , TT , GameTime > Builder ( TS startState )
60- {
61- return new FluentImplementation < TS , TT > ( startState ) ;
62- }
63-
64- private void ResetCurrentAfterEntries ( )
65- {
66- foreach ( var k in Current . Model . Transitions . Keys )
67- {
68- List < Timer < TS > > currentAfterEntries ;
69- if ( AfterEntries . TryGetValue ( new Tuple < TS , TS > ( Current . Identifier , k ) , out currentAfterEntries ) )
70- {
71- for ( int i = 0 ; i < currentAfterEntries . Count ; i ++ )
72- {
73- Timer < TS > e = currentAfterEntries [ i ] ;
74- e . Reset ( ) ;
75- currentAfterEntries [ i ] = e ;
76- }
77- }
78- }
79- }
80-
81- protected override void Entered ( StateChangeArgs < TS , TT , GameTime > args )
82- {
83- ResetCurrentAfterEntries ( ) ;
84- base . Entered ( args ) ;
85- }
86-
87- public new void Update ( GameTime gameTime )
88- {
89- // After-entries on transitions.
90- foreach ( var k in Current . Model . Transitions . Keys )
91- {
92- List < Timer < TS > > currentAfterEntries ;
93- if ( AfterEntries . TryGetValue ( new Tuple < TS , TS > ( Current . Identifier , k ) , out currentAfterEntries ) )
94- {
95- if ( CheckAfterEntries ( currentAfterEntries , Current . Model . Transitions , gameTime ) )
96- {
97- return ;
98- }
99- }
100- }
101-
102- // Global after-entries.
103- if ( CheckAfterEntries ( GlobalAfterEntries , Model . GlobalTransitions , gameTime ) )
104- {
105- return ;
106- }
107-
108- Model . Current . RaiseUpdated ( new UpdateArgs < TS , TT , GameTime > ( this , Current , gameTime ) ) ;
109- }
110-
111- private bool CheckAfterEntries ( List < Timer < TS > > afterEntries ,
112- Dictionary < TS , Transition < TS , TT , GameTime > > transitions , GameTime g )
113- {
114- for ( int i = 0 ; i < afterEntries . Count ; i ++ )
115- {
116- Timer < TS > e = afterEntries [ i ] ;
117- Transition < TS , TT , GameTime > t ;
118- if ( transitions . TryGetValue ( e . Target , out t ) )
119- {
120- if ( t . ConditionsMet ( Current . Identifier ) )
121- {
122- double timerMax = e . Time ;
123- double ? r = e . Tick ( g . ElapsedGameTime . TotalMilliseconds ) ;
124- afterEntries [ i ] = e ;
125- if ( r . HasValue )
126- {
127- // It triggered.
128- DoTransition ( e . Target , default ( TT ) , t . Pop ) ;
129- gt . IsRunningSlowly = g . IsRunningSlowly ;
130- gt . TotalGameTime = g . TotalGameTime . Subtract ( TimeSpan . FromMilliseconds ( timerMax ) ) ;
131- gt . ElapsedGameTime =
132- g . ElapsedGameTime . Subtract ( TimeSpan . FromMilliseconds ( timerMax ) ) ;
133- Update ( gt ) ;
134- return true ;
135- }
136- }
137- }
138- }
139- return false ;
140- }
141- }
37+ public class Fsm < TS , TT > : Fsm < TS , TT , GameTime >
38+ {
39+ private readonly GameTime gt = new GameTime ( ) ;
40+
41+ public Dictionary < Tuple < TS , TS > , List < Timer < TS > > > AfterEntries { get ; set ; } =
42+ new Dictionary < Tuple < TS , TS > , List < Timer < TS > > > ( ) ;
43+
44+ public List < Timer < TS > > GlobalAfterEntries { get ; set ; } = new List < Timer < TS > > ( ) ;
45+
46+ public Fsm ( FsmModel < TS , TT , GameTime > model ) : base ( model )
47+ {
48+ }
49+
50+ public Fsm ( State < TS , TT , GameTime > current , bool stackEnabled = false ) : base ( current , stackEnabled )
51+ {
52+ }
53+
54+ /// <summary>
55+ /// Gets you a builder for a Finite-State-Machine (FSM).
56+ /// </summary>
57+ /// <param name="startState">The start state's key.</param>
58+ /// <returns></returns>
59+ public new static BuilderFluent < TS , TT , GameTime > Builder ( TS startState )
60+ {
61+ return new FluentImplementation < TS , TT > ( startState ) ;
62+ }
63+
64+ private void ResetCurrentAfterEntries ( )
65+ {
66+ foreach ( var k in Current . Model . Transitions . Keys )
67+ {
68+ if ( ! AfterEntries . TryGetValue ( new Tuple < TS , TS > ( Current . Identifier , k ) , out var currentAfterEntries ) ) continue ;
69+ for ( var i = 0 ; i < currentAfterEntries . Count ; i ++ )
70+ {
71+ var e = currentAfterEntries [ i ] ;
72+ e . Reset ( ) ;
73+ currentAfterEntries [ i ] = e ;
74+ }
75+ }
76+ }
77+
78+ protected override void Entered ( StateChangeArgs < TS , TT , GameTime > args )
79+ {
80+ ResetCurrentAfterEntries ( ) ;
81+ base . Entered ( args ) ;
82+ }
83+
84+ public new void Update ( GameTime gameTime )
85+ {
86+ // After-entries on transitions.
87+ foreach ( var k in Current . Model . Transitions . Keys )
88+ {
89+ if ( ! AfterEntries . TryGetValue ( new Tuple < TS , TS > ( Current . Identifier , k ) , out var currentAfterEntries ) ) continue ;
90+ if ( CheckAfterEntries ( currentAfterEntries , Current . Model . Transitions , gameTime ) )
91+ return ;
92+ }
93+
94+ // Global after-entries.
95+ if ( CheckAfterEntries ( GlobalAfterEntries , Model . GlobalTransitions , gameTime ) )
96+ {
97+ return ;
98+ }
99+
100+ Model . Current . RaiseUpdated ( new UpdateArgs < TS , TT , GameTime > ( this , Current , gameTime ) ) ;
101+ }
102+
103+ private bool CheckAfterEntries ( List < Timer < TS > > afterEntries ,
104+ Dictionary < TS , Transition < TS , TT , GameTime > > transitions , GameTime g )
105+ {
106+ for ( var i = 0 ; i < afterEntries . Count ; i ++ )
107+ {
108+ var e = afterEntries [ i ] ;
109+ if ( ! transitions . TryGetValue ( e . Target , out var t ) ) continue ;
110+ if ( ! t . ConditionsMet ( Current . Identifier ) ) continue ;
111+
112+ var timerMax = e . Time ;
113+ var r = e . Tick ( g . ElapsedGameTime . TotalMilliseconds ) ;
114+ afterEntries [ i ] = e ;
115+
116+ if ( ! r . HasValue ) continue ;
117+
118+ // It triggered.
119+ DoTransition ( e . Target , default ( TT ) , t . Pop ) ;
120+ gt . IsRunningSlowly = g . IsRunningSlowly ;
121+ gt . TotalGameTime = g . TotalGameTime . Subtract ( TimeSpan . FromMilliseconds ( timerMax ) ) ;
122+ gt . ElapsedGameTime =
123+ g . ElapsedGameTime . Subtract ( TimeSpan . FromMilliseconds ( timerMax ) ) ;
124+ Update ( gt ) ;
125+ return true ;
126+ }
127+
128+ return false ;
129+ }
130+ }
142131}
0 commit comments