summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--DungeonSlime/Game1.cs205
-rw-r--r--MonoGameLibrary/Core.cs2
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();