using Assets.Scripts; using System; using System.Collections; using Unity.VisualScripting; using UnityEditor.Rendering; using UnityEngine; using static PlayersHandler; /// /// GameHandler gère le fonctionnement général d'une partie de jeu. Il se charge de faire apparaître les joueurs /// public class GameHandler : SingletonMB { #region PROPERTIES int Seed { get { return _seed; } set { _seed = value; UnityEngine.Random.InitState(value); } } private int _seed; public float FrameDistance { get; private set; } public float TotalDistance { get; private set; } [SerializeField] public float MapSpeed { get; private set; } public Attempt CurrentAttempt { get; private set; } public bool MaxDifficultyReached { get; private set; } public bool IsPaused { get; private set; } = false; public bool HaveHumanPlayer { get; private set; } = false; public bool AttemptEnding { get; private set; } public int TickAttemptDuration { get; private set; } public float TimeAttemptDuration {get; private set;} #endregion #region VARIABLES private const float DIFFICULTY_DAMP = 0.01f; [SerializeField] private GameObject finishLine; private ScoreHandler _scoreHandler; private LevelSpawner _levelSpawner; private PlayersHandler _playerHandler; private DataBearer _dataBearer; private TileSpawner _tileSpawner; private Vector3 playerSpawnPosition = new Vector3(-3, 0, 0); private float maxSpeed; private float maxDistance; private bool raiseScoreOnDistance; private float difficultyMultiplier; private bool finishLineSpawned; private short tickCounter; #endregion #region EVENTS public event EventHandler OnAttemptStarted; public event EventHandler OnAttemptEnding; public event EventHandler OnAttemptEnded; public event EventHandler OnGamePaused; public event EventHandler OnGameResumed; public event EventHandler OnInstanciatingPlayers; public class AttemptEventArgs : EventArgs { public Attempt attempt; public AttemptEventArgs(Attempt attempt) { this.attempt = attempt; } } public void HaltAttempt_OnAllPlayersFinished(object sender, EventArgs agrs) { HaltAttempt("Tous les joueurs sont Out"); } public void CheckIfHumanPlayer_OnPlayerInstanciated(object sender, PlayerEventArgs args) { if (args.player.IsHuman) { HaveHumanPlayer = true; } } #endregion #region METHODS /// /// Return a seed which depend on selected settings and attempt number /// private int SetSeed() { int seed; if (_dataBearer.Session.Rules.ChangeSeedEachTry & CurrentAttempt.AttemptNumber > 1) //Get a random seed each new try { seed = UnityEngine.Random.Range(100000000, 1000000000); //generate a random 9 digits seed } else //Get either default seed or custom seed { seed = _dataBearer.Session.Rules.UsesDefaultSeed ? PlayerPrefs.GetInt(Settings.DefaultSeedSettingValue) : PlayerPrefs.GetInt(Settings.CustomSeedSettingValue); } return seed; } private void RaiseScore() { float scoreToAdd = FrameDistance;// * Time.deltaTime; _scoreHandler.AddScoreToAllAlivePlayers(scoreToAdd); } private void RaiseDifficulty() { if(MapSpeed > maxSpeed) { MapSpeed = maxSpeed; MaxDifficultyReached = true; } MapSpeed += MapSpeed * difficultyMultiplier * Time.deltaTime; } private void SpawnPlayers() { if (_dataBearer.Session.Players.Human) _playerHandler.InstanciatePlayer(playerSpawnPosition); if (_dataBearer.Session.Players.OmnicientBot) _playerHandler.InstanciatePlayer(playerSpawnPosition); if (_dataBearer.Session.Players.ObserverBot) _playerHandler.InstanciatePlayer(playerSpawnPosition); if (_dataBearer.Session.Players.IteratorBot) _playerHandler.InstanciatePlayer(playerSpawnPosition); } #endregion #region ENDPOINTS public void PauseGame() { if (!IsPaused) { StartCoroutine(PauseGameCoroutine()); } } private IEnumerator PauseGameCoroutine() { yield return null; Time.timeScale = 0; // Met le jeu en pause IsPaused = true; OnGamePaused.Invoke(this, new EventArgs()); } public void ResumeGame() { if (IsPaused) { Time.timeScale = _dataBearer.Rules.RushMode ? 15 : 1; // Reprend le jeu IsPaused = false; OnGameResumed.Invoke(this, new EventArgs()); } } public void InitAttempt() { TimeAttemptDuration = 0; TickAttemptDuration = 0; Debug.LogWarning("Initate Attempt !"); AttemptEnding = false; CurrentAttempt = new Attempt(); CurrentAttempt.AttemptNumber = _dataBearer.Session.Attempts.Count + 1; Seed = SetSeed(); CurrentAttempt.Seed = Seed; TotalDistance = 0; MapSpeed = _dataBearer.Rules.StartSpeed; raiseScoreOnDistance = _dataBearer.Rules.ScoreOnDistance; maxSpeed = _dataBearer.Rules.MaxSpeed; difficultyMultiplier = _dataBearer.Rules.DifficultyMultiplier * DIFFICULTY_DAMP; if(_dataBearer.Rules.RushMode){ Time.timeScale = 15; foreach (var renderer in FindObjectsOfType()) { if(renderer.gameObject.GetComponent()==null) {renderer.enabled = false;} } } else{ Time.timeScale = 1; } MaxDifficultyReached = false; TotalDistance = 0; FrameDistance = 0; finishLineSpawned = false; tickCounter = 0; SpawnPlayers(); _scoreHandler.AddScoreToAllAlivePlayers(500); OnAttemptStarted?.Invoke(this, new AttemptEventArgs(CurrentAttempt)); } /// /// Halt the current attempt /// public void HaltAttempt(string message) { Console.WriteLine(message); AttemptEnding = true; OnAttemptEnding?.Invoke(this, new AttemptEventArgs(CurrentAttempt)); OnAttemptEnded?.Invoke(this, new AttemptEventArgs(CurrentAttempt)); } #endregion #region LIFECYCLE protected override void Awake() { base.Awake(); _scoreHandler = ScoreHandler.Instance; _levelSpawner = LevelSpawner.Instance; _playerHandler = PlayersHandler.Instance; _dataBearer = DataBearer.Instance; _tileSpawner = TileSpawner.Instance; _playerHandler.OnAllPlayersFinished += HaltAttempt_OnAllPlayersFinished; _playerHandler.OnPlayerInstanciated += CheckIfHumanPlayer_OnPlayerInstanciated; difficultyMultiplier = _dataBearer.Rules.DifficultyMultiplier; raiseScoreOnDistance = _dataBearer.Rules.ScoreOnDistance; maxDistance = _dataBearer.Rules.MaxDistance; } void Update() { FrameDistance = MapSpeed * Time.deltaTime; TotalDistance += FrameDistance; TimeAttemptDuration += Time.deltaTime; TickAttemptDuration += 1; tickCounter += 1; if (tickCounter > 1000) { //Debug.Log("1000 TICK " + TimeAttemptDuration); tickCounter = 0; _dataBearer.RecordPlayersScore(); } if(maxDistance != 0 && TotalDistance > maxDistance) { HaltAttempt("Ligne d'arrivée atteinte"); } if (raiseScoreOnDistance) RaiseScore(); if (!MaxDifficultyReached) RaiseDifficulty(); if(maxDistance != 0 && !finishLineSpawned && maxDistance-TotalDistance < 20) { Instantiate(finishLine, new Vector3(maxDistance - TotalDistance - 3, 0, -1), finishLine.transform.rotation); finishLineSpawned = true; } if (Input.GetKeyDown(KeyCode.Escape)) (IsPaused ? (Action)ResumeGame : PauseGame)(); } private void OnDestroy() { Clean(); } private void OnDisable() { Clean(); } private void Clean() { /*StopAllCoroutines(); _playerHandler.OnAllPlayersFinished -= HaltAttempt_OnAllPlayersFinished; _playerHandler.OnPlayerInstanciated -= CheckIfHumanPlayer_OnPlayerInstanciated;*/ } #endregion }