196 lines
6.0 KiB
C#
196 lines
6.0 KiB
C#
using System.Collections.Generic;
|
|
using EscapeRoomEngine.Engine.Runtime.Measurements;
|
|
using EscapeRoomEngine.Engine.Runtime.Modules;
|
|
using EscapeRoomEngine.Engine.Runtime.Utilities;
|
|
using NaughtyAttributes;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace EscapeRoomEngine.Engine.Runtime.UI
|
|
{
|
|
public enum GameState
|
|
{
|
|
Stopped, Paused, Running
|
|
}
|
|
|
|
public class GameControl : MonoBehaviour
|
|
{
|
|
public static GameControl Instance { get; private set; }
|
|
|
|
[SerializeField]
|
|
private float uiUpdateInterval = 1, planUpdateInterval = 1;
|
|
[BoxGroup("Internal")] [SerializeField]
|
|
private Button startButton, stopButton, pauseButton, addTimeButton, removeTimeButton;
|
|
[BoxGroup("Internal")] [SerializeField]
|
|
private Text timeText, roomTimeText, estimateTimeText, targetTimeText, percentileText;
|
|
[BoxGroup("Internal")] [SerializeField]
|
|
private PuzzlePlan puzzlePlan;
|
|
|
|
[HideInInspector] public GameState gameState = GameState.Stopped;
|
|
public PuzzleModuleDescription CurrentPuzzle
|
|
{
|
|
set => puzzlePlan.CurrentPuzzle = value;
|
|
}
|
|
public List<PuzzleModuleDescription> PlannedPuzzles
|
|
{
|
|
set => puzzlePlan.Puzzles = value;
|
|
}
|
|
|
|
public float TimeElapsed { get; private set; }
|
|
public float TimeInRoom { get; set; }
|
|
public float TargetTime { get; private set; }
|
|
public float EstimatedTimeRoom { get; private set; }
|
|
public float EstimatedTime { get; private set; }
|
|
|
|
private float _previousUIUpdate, _previousPlanUpdate;
|
|
|
|
private void Awake()
|
|
{
|
|
Instance = this;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
TargetTime = Engine.Instance.initialTargetTime;
|
|
|
|
SetTimeText();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
// update time
|
|
if (gameState == GameState.Running)
|
|
{
|
|
TimeElapsed += Time.deltaTime;
|
|
TimeInRoom += Time.deltaTime;
|
|
}
|
|
|
|
// update ui
|
|
if (Time.time > _previousUIUpdate + uiUpdateInterval)
|
|
{
|
|
_previousUIUpdate = Time.time;
|
|
|
|
SetTimeText();
|
|
UpdateStats();
|
|
}
|
|
|
|
// update plan
|
|
if (Time.time > _previousPlanUpdate + planUpdateInterval)
|
|
{
|
|
_previousPlanUpdate = Time.time;
|
|
|
|
Engine.Instance.PlanPuzzles();
|
|
}
|
|
|
|
// enable or disable buttons
|
|
startButton.interactable = gameState == GameState.Stopped;
|
|
stopButton.interactable = gameState != GameState.Stopped;
|
|
pauseButton.interactable = gameState is GameState.Running or GameState.Paused;
|
|
addTimeButton.interactable = gameState != GameState.Stopped;
|
|
removeTimeButton.interactable = gameState != GameState.Stopped && TargetTime >= TimeElapsed + 60;
|
|
}
|
|
|
|
#region Time Controls
|
|
|
|
public void StartGame()
|
|
{
|
|
gameState = GameState.Running;
|
|
|
|
TimeElapsed = 0;
|
|
|
|
// generate the first room if it hasn't been generated yet
|
|
Engine.Instance.CurrentRoom.Match(none: () => Engine.Instance.GenerateRoom());
|
|
|
|
// start a new session
|
|
Measure.StartSession();
|
|
}
|
|
|
|
public void StopGame()
|
|
{
|
|
if (gameState != GameState.Stopped)
|
|
{
|
|
// was running
|
|
Measure.EndSession(TimeElapsed);
|
|
}
|
|
|
|
gameState = GameState.Stopped;
|
|
}
|
|
|
|
public void PauseGame()
|
|
{
|
|
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
|
switch (gameState)
|
|
{
|
|
case GameState.Running:
|
|
gameState = GameState.Paused;
|
|
pauseButton.GetComponent<PauseButton>().Paused = true;
|
|
break;
|
|
case GameState.Paused:
|
|
gameState = GameState.Running;
|
|
pauseButton.GetComponent<PauseButton>().Paused = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Change the allowed time by a specified amount of seconds.
|
|
/// </summary>
|
|
/// <param name="seconds">The amount of seconds that will be added to the time. Can be negative to remove time.</param>
|
|
public void ChangeTime(int seconds)
|
|
{
|
|
if (TargetTime + seconds >= TimeElapsed)
|
|
{
|
|
TargetTime += seconds;
|
|
}
|
|
}
|
|
|
|
private void SetTimeText()
|
|
{
|
|
timeText.text = TimeToText(TimeElapsed);
|
|
roomTimeText.text = TimeToText(TimeInRoom);
|
|
targetTimeText.text = TimeToText(TargetTime);
|
|
|
|
Engine.Instance.CurrentRoom.Match(some: room =>
|
|
{
|
|
EstimatedTimeRoom =
|
|
TimeElapsed - TimeInRoom + Mathf.Max(TimeInRoom, Measure.EstimateTime(room));
|
|
EstimatedTime = EstimatedTimeRoom + Engine.Instance.EstimatedTimeRemaining;
|
|
|
|
estimateTimeText.text = TimeToText(EstimatedTime);
|
|
});
|
|
}
|
|
|
|
private void UpdateStats()
|
|
{
|
|
percentileText.text = PercentageToText(Measure.SessionPercentile());
|
|
}
|
|
|
|
private static string TimeToText(float time) => $"{time.ToTimeSpan():mm':'ss}";
|
|
|
|
private static string PercentageToText(float percentage) => $"{percentage:P1}";
|
|
|
|
#endregion
|
|
|
|
#region Measurements
|
|
|
|
public void StoreMeasurements(Toggle toggle)
|
|
{
|
|
Measure.Store = toggle.isOn;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void ExitGame()
|
|
{
|
|
StopGame();
|
|
|
|
#if UNITY_STANDALONE
|
|
Application.Quit();
|
|
#endif
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorApplication.isPlaying = false;
|
|
#endif
|
|
}
|
|
}
|
|
}
|