diff options
| -rw-r--r-- | DungeonSlime/Game1.cs | 205 | ||||
| -rw-r--r-- | MonoGameLibrary/Core.cs | 2 |
2 files changed, 180 insertions, 27 deletions
diff --git a/DungeonSlime/Game1.cs b/DungeonSlime/Game1.cs index 36d5a13..387f6b5 100644 --- a/DungeonSlime/Game1.cs +++ b/DungeonSlime/Game1.cs @@ -10,7 +10,8 @@ namespace DungeonSlime; internal enum GameState { MenuState, - PlayingState, + WaitingState, + PollingState, GameOverState } @@ -20,37 +21,52 @@ internal class GameStateMachine public GameStateMachine(GameState startState) { + if (!IsValidState(startState)) + { + throw new ArgumentOutOfRangeException($"{startState}"); + } + _state = startState; } public GameState State { get => _state; - set { - if (IsValidStateTransition(value)) + if (!IsValidState(value)) { - _state = value; + throw new ArgumentOutOfRangeException($"{value}"); } - else + + if (!IsValidStateTransition(value)) { throw new InvalidOperationException($"Cannot go from {State} to {value}!"); } + + _state = value; } } + private static bool IsValidState(GameState state) + { + return state is + GameState.MenuState or + GameState.WaitingState or + GameState.PollingState or + GameState.GameOverState; + } + private bool IsValidStateTransition(GameState targetState) { - switch (State) + return State switch { - case GameState.MenuState: - return targetState == GameState.PlayingState; - case GameState.PlayingState: - return targetState == GameState.GameOverState; - default: //If game is over - return targetState == GameState.MenuState || targetState == GameState.PlayingState; - } + GameState.MenuState => targetState == GameState.WaitingState, + GameState.WaitingState => targetState == GameState.PollingState || targetState == GameState.GameOverState, + GameState.PollingState => targetState == GameState.GameOverState, + GameState.GameOverState => targetState == GameState.MenuState || targetState == GameState.WaitingState, + _ => false + }; } } @@ -87,13 +103,45 @@ internal class MouseInputManager public class Game1 : Core { + private const int MinTimeToReactMilis = 50; + private const int MaxTimeToReactMillis = 400; + private GameStateMachine _stateMachine; private SpriteFont _arial; private MouseInputManager _mouseInput; + private Random _random; + private Vector2 WindowCenter + { + get + { + return new Vector2( + Window.ClientBounds.Width, + Window.ClientBounds.Height + ) * 0.5f; + } + } + private Color ClearColor + { + get + { + return _stateMachine.State switch + { + GameState.MenuState => Color.Green, + GameState.WaitingState => Color.CornflowerBlue, + GameState.PollingState => Color.Red, + GameState.GameOverState => Color.Green, + _ => throw new ArgumentOutOfRangeException($"{_stateMachine.State}"), + }; + } + } + + //Gameplay fields + private TimeSpan _timeToReact; + private bool _clickedTooEarly; public Game1() : base("Reaction Test", 1280, 720, false) { - + IsFixedTimeStep = false; //For fastest possible updates } protected override void Initialize() @@ -102,6 +150,7 @@ public class Game1 : Core _stateMachine = new GameStateMachine(GameState.MenuState); _mouseInput = new MouseInputManager(Mouse.GetState()); + _random = new Random(); } protected override void LoadContent() @@ -119,48 +168,65 @@ public class Game1 : Core case GameState.MenuState: UpdateMenu(); break; + case GameState.WaitingState: + UpdateWaiting(gameTime); + break; + case GameState.GameOverState: + UpdateGameOver(); + break; + case GameState.PollingState: + UpdatePolling(gameTime); + break; } } protected override void Draw(GameTime gameTime) { + GraphicsDevice.Clear(ClearColor); + switch (_stateMachine.State) { case GameState.MenuState: DrawMenu(); break; - default: - GraphicsDevice.Clear(Color.CornflowerBlue); + case GameState.WaitingState: + DrawWaiting(); + break; + case GameState.GameOverState: + DrawGameOver(); break; } + base.Draw(gameTime); } + private void StartPlaying() + { + _stateMachine.State = GameState.WaitingState; + _timeToReact = TimeSpan.FromMilliseconds( + MinTimeToReactMilis + _random.Next() % (MaxTimeToReactMillis - MinTimeToReactMilis + 1) + ); + _clickedTooEarly = false; + } + private void UpdateMenu() { if (_mouseInput.IsMouseClicked) { - _stateMachine.State = GameState.PlayingState; + StartPlaying(); } } private void DrawMenu() { - GraphicsDevice.Clear(Color.Green); - - SpriteBatch.Begin( - samplerState: SamplerState.PointClamp - ); + SpriteBatch.Begin(); //Draw the menu header string header = "Welcome to the reaction time test!"; SpriteBatch.DrawString( _arial, header, - new Vector2( - Window.ClientBounds.Width, - Window.ClientBounds.Height - ) * 0.5f, + WindowCenter, Color.White, 0f, _arial.MeasureString(header) * 0.5f, @@ -188,4 +254,91 @@ public class Game1 : Core SpriteBatch.End(); } + + private void ClickedTooEarly() + { + _clickedTooEarly = true; + _stateMachine.State = GameState.GameOverState; + } + + private void StartPolling() + { + _stateMachine.State = GameState.PollingState; + _timeToReact = TimeSpan.Zero; + } + + private void UpdateWaiting(GameTime gameTime) + { + _timeToReact -= gameTime.ElapsedGameTime; + + if (_timeToReact.CompareTo(TimeSpan.Zero) <= 0) + { + StartPolling(); + return; + } + + if (_mouseInput.IsMouseClicked) + { + ClickedTooEarly(); + } + } + + private void DrawWaiting() + { + SpriteBatch.Begin(); + + string message = "Click when the background turns red!"; + SpriteBatch.DrawString( + _arial, + message, + WindowCenter, + Color.White, + 0f, + _arial.MeasureString(message) * 0.5f, + 1f, + SpriteEffects.None, + 0f + ); + + SpriteBatch.End(); + } + + private void UpdatePolling(GameTime gameTime) + { + _timeToReact += gameTime.ElapsedGameTime; + + if (_mouseInput.IsMouseClicked) + { + _stateMachine.State = GameState.GameOverState; + } + } + + private void UpdateGameOver() + { + if (_mouseInput.IsMouseClicked) + { + _stateMachine.State = GameState.MenuState; + } + } + + private void DrawGameOver() + { + string header = _clickedTooEarly ? "Too Early!" : $"You reacted in {Math.Round(_timeToReact.TotalMilliseconds)}ms!"; + + SpriteBatch.Begin(); + + SpriteBatch.DrawString( + _arial, + header, + WindowCenter, + Color.White, + 0f, + _arial.MeasureString(header) * 0.5f, + 1f, + SpriteEffects.None, + 0f + ); + + SpriteBatch.End(); + } } diff --git a/MonoGameLibrary/Core.cs b/MonoGameLibrary/Core.cs index fddcc0c..1f76b51 100644 --- a/MonoGameLibrary/Core.cs +++ b/MonoGameLibrary/Core.cs @@ -29,7 +29,7 @@ public class Core : Game { Graphics.PreferredBackBufferWidth = width; Graphics.PreferredBackBufferHeight = height; Graphics.IsFullScreen = fullscreen; - Graphics.SynchronizeWithVerticalRetrace = true; + Graphics.SynchronizeWithVerticalRetrace = false; Graphics.ApplyChanges(); |
