#nullable enable using System; using NaughtyAttributes; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using TMPro; //Could be a singleton public class GameFlowManager : MonoBehaviour { [SerializeField] [Required] GameTimer gameTimer = null!; [SerializeField] [Required] MainMenuManager mainMenu = null!; [SerializeField] [Required] Canvas UICanvas = null!; BlurFade blurFade = null!; public enum PauseLevel { NotPaused, PreventActions, NothingMoves, TimeStop, } [field: SerializeField] public PauseLevel pauseLevel { get; private set; } = PauseLevel.PreventActions; public bool CanDoAction => pauseLevel <= PauseLevel.NotPaused; public BaseState CurrentState { get; private set; } = null!; bool lastStartButton; bool lastAcceptButton; [field: SerializeField] float fadingTime = 3f; [field: SerializeField] float minFadingValue = 0.1f; float fadeStep = 0.02f; float fadingTimer; bool fadingIn = false; [field: SerializeField] TMP_Text startTxt = null!; [field: SerializeField] TMP_Text endTxt = null!; public event Action? stateChanged; #region Unity Messages void Awake() { blurFade = GetComponentInChildren(); CurrentState = new StartMenuFlowState(this); if (startTxt != null) { startTxt.transform.parent.gameObject.SetActive(true); } if (endTxt != null) { endTxt.transform.parent.gameObject.SetActive(false); } } void Start() => CurrentState.EnterState(); void Update() { if (CurrentState.UpdateState() is {} newState) SwitchState(newState); } #endregion void SetPauseLevel(PauseLevel value) { pauseLevel = value; Time.timeScale = value >= PauseLevel.TimeStop ? 0f : 1f; } public void GameOver(){ if (endTxt != null) { endTxt.transform.parent.gameObject.SetActive(true); } SwitchState(new DeadFlowState(this)); } public void FadeStartTxt(){ fadingTimer += fadeStep; if(fadingTimer >= fadingTime){ if(fadingIn){ fadingIn = false; fadingTimer = 0; }else{ fadingIn = true; fadingTimer = 0; } } if(!fadingIn){ startTxt.color = new Color(startTxt.color.r, startTxt.color.g, startTxt.color.b, (1+minFadingValue) - (fadingTimer/fadingTime)); }else{ startTxt.color = new Color(startTxt.color.r, startTxt.color.g, startTxt.color.b, (fadingTimer/fadingTime) + minFadingValue); } } /// /// For calling from main menu button /// public void ToStartFlowState() => SwitchState(new StartFlowState(this)); #region Inputs public void OnStart(InputAction.CallbackContext ctx) { if (!ctx.WasPressedThisFrame(ref lastStartButton)) return; switch (CurrentState) { case StartFlowState _: SwitchState(new GameplayFlowState(this)); break; case GameplayFlowState _: SwitchState(new PauseMenuFlowState(this)); break; case PauseMenuFlowState _: SwitchState(new GameplayFlowState(this)); break; } } public void OnAccept(InputAction.CallbackContext ctx) { if (!ctx.WasPressedThisFrame(ref lastAcceptButton)) return; if (CurrentState is DeadFlowState deadState) deadState.ReloadGame(); } #endregion #region States void SwitchState(BaseState newState) { CurrentState.LeaveState(); CurrentState = newState; newState.EnterState(); stateChanged?.Invoke(newState); } public abstract class GameFlowState : BaseState { readonly protected GameFlowManager gameFlowManager; protected GameFlowState(GameFlowManager gameFlowManager) { this.gameFlowManager = gameFlowManager; } } class StartMenuFlowState : GameFlowState { public StartMenuFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {} public override void EnterState() { base.EnterState(); gameFlowManager.mainMenu.gameObject.SetActive(true); gameFlowManager.mainMenu.SetMenuMode(MainMenuManager.MenuMode.MainMenu); gameFlowManager.UICanvas.gameObject.SetActive(false); gameFlowManager.blurFade.SetBlurred(true); } public override void LeaveState() { base.LeaveState(); gameFlowManager.mainMenu.ResetMenuState(); gameFlowManager.mainMenu.gameObject.SetActive(false); gameFlowManager.UICanvas.gameObject.SetActive(true); gameFlowManager.blurFade.SetBlurred(false); } } class StartFlowState : GameFlowState { public StartFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {} public override void EnterState() { base.EnterState(); gameFlowManager.startTxt.transform.parent.gameObject.SetActive(true); gameFlowManager.SetPauseLevel(PauseLevel.PreventActions); } public override BaseState? UpdateState(){ gameFlowManager.FadeStartTxt(); return null; } public override void LeaveState() => gameFlowManager.startTxt.transform.parent.gameObject.SetActive(false); } class GameplayFlowState : GameFlowState { public GameplayFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {} public override void EnterState() { base.EnterState(); gameFlowManager.gameTimer.stopped = false; gameFlowManager.SetPauseLevel(PauseLevel.NotPaused); } public override void LeaveState() { base.LeaveState(); gameFlowManager.gameTimer.stopped = true; } } class PauseMenuFlowState : GameFlowState { public PauseMenuFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {} public override void EnterState() { base.EnterState(); gameFlowManager.mainMenu.gameObject.SetActive(true); gameFlowManager.mainMenu.SetMenuMode(MainMenuManager.MenuMode.PauseMenu); gameFlowManager.SetPauseLevel(PauseLevel.TimeStop); gameFlowManager.blurFade.SetBlurred(true); } public override void LeaveState() { base.EnterState(); gameFlowManager.mainMenu.ResetMenuState(); gameFlowManager.mainMenu.gameObject.SetActive(false); gameFlowManager.SetPauseLevel(PauseLevel.NotPaused); gameFlowManager.blurFade.SetBlurred(false); } } class DeadFlowState : GameFlowState { public DeadFlowState(GameFlowManager gameFlowManager) : base(gameFlowManager) {} public override void EnterState() { base.EnterState(); Debug.Log("You died!\nPress Accept to restart!"); gameFlowManager.SetPauseLevel(PauseLevel.PreventActions); gameFlowManager.blurFade.SetBlurred(true); } public override void LeaveState() => gameFlowManager.blurFade.SetBlurred(false); public void ReloadGame() { Debug.Log("Reloading scene..."); SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); } } #endregion }