using System; using EscapeRoomEngine.Engine.Runtime.Measurements; 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 { if (_foundGameControl == null) { _foundGameControl = FindObjectOfType(); } return _foundGameControl; } } private static GameControl _foundGameControl; [BoxGroup("Internal")] [SerializeField] private Button startButton, stopButton, pauseButton, addTimeButton, removeTimeButton; [BoxGroup("Internal")] [SerializeField] private Text timeText, targetTimeText, estimateTimeText; [BoxGroup("Internal")] [SerializeField] private float uiUpdateInterval = 1; [HideInInspector] public GameState gameState = GameState.Stopped; private float _timeElapsed, _targetTime; private float _previousUIUpdate; private void Awake() { _targetTime = Engine.Instance.initialTargetTime; } private void Start() { SetTimeText(); } private void Update() { // update time if (gameState == GameState.Running) { _timeElapsed += Time.deltaTime; } // update ui if (Time.time > _previousUIUpdate + uiUpdateInterval) { _previousUIUpdate = Time.time; SetTimeText(); } // 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().Paused = true; break; case GameState.Paused: gameState = GameState.Running; pauseButton.GetComponent().Paused = false; break; } } /// /// Change the allowed time by a specified amount of seconds. /// /// The amount of seconds that will be added to the time. Can be negative to remove time. public void ChangeTime(int seconds) { if (_targetTime + seconds >= _timeElapsed) { _targetTime += seconds; } } private void SetTimeText() { timeText.text = TimeToText(_timeElapsed); targetTimeText.text = TimeToText(_targetTime); estimateTimeText.text = TimeToText(_timeElapsed); } private static string TimeToText(float time) => $"{time.ToTimeSpan():mm':'ss}"; #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 } } }