From ec8c24e5b6be2b8bab842d945185bca684f899ce Mon Sep 17 00:00:00 2001 From: Colin McMillen Date: Wed, 25 Mar 2020 15:16:31 -0400 Subject: [PATCH] FSM: deal with IStates directly, don't parametrize on an input type. --- Shared/FSM.cs | 22 ++++++++++++---------- Shared/NPC.cs | 33 ++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Shared/FSM.cs b/Shared/FSM.cs index 23f8704..42d0812 100644 --- a/Shared/FSM.cs +++ b/Shared/FSM.cs @@ -1,27 +1,29 @@ using System.Collections.Generic; namespace SemiColinGames { - public interface IState { + public interface IState { + // Called automatically whenever this state is transitioned to. Should reset whichever + // state-specific variables need resetting. public void Enter(); // Returns the name of the new state, or null if we should stay in the same state. - public string Update(T obj, float modelTime, World world); + public string Update(float modelTime, World world); } - public class FSM { - readonly Dictionary> states; - IState state; + public class FSM { + readonly Dictionary states; + IState state; - public FSM(Dictionary> states, string initial) { + public FSM(string initialStateName, Dictionary states) { this.states = states; - StateName = initial; + StateName = initialStateName; Transition(StateName); } public string StateName { get; private set; } - public void Update(T obj, float modelTime, World world) { - string newState = state.Update(obj, modelTime, world); + public void Update(float modelTime, World world) { + string newState = state.Update(modelTime, world); if (newState != null) { Transition(newState); } @@ -29,7 +31,7 @@ namespace SemiColinGames { void Transition(string state) { StateName = state; - IState newState = states[state]; + IState newState = states[state]; this.state = newState; this.state.Enter(); } diff --git a/Shared/NPC.cs b/Shared/NPC.cs index bcd4dcc..1541be3 100644 --- a/Shared/NPC.cs +++ b/Shared/NPC.cs @@ -3,14 +3,19 @@ using Microsoft.Xna.Framework.Graphics; using System.Collections.Generic; namespace SemiColinGames { - class IdleState : IState { - float timeInState = 0; + class IdleState : IState { + private NPC npc; + private float timeInState = 0; + + public IdleState(NPC npc) { + this.npc = npc; + } public void Enter() { timeInState = 0; } - public string Update(NPC npc, float modelTime, World world) { + public string Update(float modelTime, World world) { timeInState += modelTime; if (timeInState > 1.0f) { npc.Facing *= -1; @@ -20,10 +25,16 @@ namespace SemiColinGames { } } - class RunState : IState { + class RunState : IState { + private NPC npc; + + public RunState(NPC npc) { + this.npc = npc; + } + public void Enter() {} - public string Update(NPC npc, float modelTime, World world) { + public string Update(float modelTime, World world) { float moveSpeed = 120; float desiredX = npc.Position.X + moveSpeed * npc.Facing * modelTime; float testPoint = desiredX + npc.Box.HalfSize.X * npc.Facing; @@ -52,7 +63,7 @@ namespace SemiColinGames { private readonly Vector2 spriteCenter; private readonly Vector2 eyeOffset = new Vector2(4, -9); - private readonly FSM fsm; + private readonly FSM fsm; private readonly Vector2 halfSize = new Vector2(11, 24); public NPC(Vector2 position, int facing) { @@ -64,10 +75,10 @@ namespace SemiColinGames { Box = new AABB(Position, halfSize); Facing = facing; - fsm = new FSM(new Dictionary> { - { "idle", new IdleState() }, - { "run", new RunState() } - }, "run"); + fsm = new FSM("run", new Dictionary { + { "idle", new IdleState(this) }, + { "run", new RunState(this) } + }); } public int Facing; @@ -99,7 +110,7 @@ namespace SemiColinGames { } public void Update(float modelTime, World world) { - fsm.Update(this, modelTime, world); + fsm.Update(modelTime, world); Box = new AABB(Position, halfSize); Debug.AddRect(Box, Color.White); }