builds
This commit is contained in:
264
Scripts/GameHandlers/DataBearer.cs
Normal file
264
Scripts/GameHandlers/DataBearer.cs
Normal file
@@ -0,0 +1,264 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using Newtonsoft.Json;
|
||||
using static GameHandler;
|
||||
using static LevelSpawner;
|
||||
using static PlayerScript;
|
||||
using static PlayersHandler;
|
||||
|
||||
namespace Assets.Scripts
|
||||
{
|
||||
public class DataBearer : SingletonMB<DataBearer>
|
||||
{
|
||||
#region PROPERTIES
|
||||
public bool DataSaved { get; private set; }
|
||||
|
||||
public Attempt CurrentAttempt { get; private set; }
|
||||
|
||||
public SessionData Session
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_session == null)
|
||||
{
|
||||
_session = GetSettings();
|
||||
}
|
||||
return _session;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_session = value;
|
||||
}
|
||||
} private SessionData _session = null;
|
||||
|
||||
public GameState GameState { get; set; } = new();
|
||||
|
||||
public Players Players { get { return Session.Players; } }
|
||||
public Rules Rules { get { return Session.Rules; } }
|
||||
|
||||
#endregion
|
||||
#region VARIABLES
|
||||
|
||||
private GameHandler _gameHandler;
|
||||
private ScoreHandler _scoreHandler;
|
||||
private PlayersHandler _playerHandler;
|
||||
private LevelSpawner _levelSpawner;
|
||||
|
||||
|
||||
#endregion
|
||||
#region EVENTS
|
||||
public void RegisterAttempt_OnAttemptEnded(object sender, AttemptEventArgs eventArgs)
|
||||
{
|
||||
Session.Attempts.Add(CurrentAttempt);
|
||||
CurrentAttempt = null;
|
||||
} //
|
||||
|
||||
public void RegisterPlayer_OnPlayerInstanciated(object sender, PlayerEventArgs args)
|
||||
{
|
||||
var player = args.player;
|
||||
var newPlayer = new RegisteredPlayer()
|
||||
{
|
||||
Name = player.Name,
|
||||
Id = player.Id,
|
||||
Human = player.IsHuman
|
||||
};
|
||||
if(!Session.RegisteredPlayers.Exists(rp => rp.Name == newPlayer.Name))
|
||||
{
|
||||
Session.RegisteredPlayers.Add(newPlayer);
|
||||
}
|
||||
|
||||
player.OnBonusTouched += RecordBonus_OnBonusTouched;
|
||||
player.OnObstacleTouched += RecordObstacle_OnObstacleTouched;
|
||||
} //
|
||||
|
||||
public void CreateAttemptRecord_OnAttemptStarted(object sender, AttemptEventArgs args)
|
||||
{
|
||||
CurrentAttempt = args.attempt;
|
||||
|
||||
foreach(var player in Session.RegisteredPlayers)
|
||||
{
|
||||
PlayerAttempt playerAttempt = new PlayerAttempt()
|
||||
{
|
||||
PlayerName = player.Name
|
||||
};
|
||||
CurrentAttempt.PlayersAttempts.Add(player.Name, playerAttempt);
|
||||
}
|
||||
} //
|
||||
|
||||
public void RecordAttemptObstacle_OnPrefabSpawned(object sender, PrefabSpawnedEventArgs args)
|
||||
{
|
||||
LevelPrefab obstacle = new() {
|
||||
PrefabName = args.pattern.name, //todo : prefab name has "(clone)" at the end
|
||||
PrefabNumber = CurrentAttempt.Level.Count + 1,
|
||||
TickTimeWhenTouched = _gameHandler.TickAttemptDuration
|
||||
};
|
||||
CurrentAttempt.Level.Add(obstacle);
|
||||
} //
|
||||
|
||||
public void RecordObstacle_OnObstacleTouched(object sender, PrefabTouchedEventArgs args)
|
||||
{
|
||||
var prefab = args.objectTouched;
|
||||
TouchedGameObject touchedGameObject = new()
|
||||
{
|
||||
FullObjectName = prefab.name, //todo : prefab name is laser... It should be full pattern name
|
||||
ObjectTypeName = SortingLayer.IDToName(prefab.layer), // todo : <unknown layer>
|
||||
GameSpeed = _gameHandler.MapSpeed,
|
||||
PrefabName = prefab.name,
|
||||
TickTimeWhenTouched = _gameHandler.TickAttemptDuration
|
||||
};
|
||||
CurrentAttempt.PlayersAttempts[args.playerName].ObstaclesTouched.Add(touchedGameObject);
|
||||
|
||||
RecordPlayerScore(args.playerId, args.playerName);
|
||||
} //
|
||||
|
||||
public void RecordBonus_OnBonusTouched(object sender, PrefabTouchedEventArgs args)
|
||||
{
|
||||
var prefab = args.objectTouched;
|
||||
TouchedGameObject touchedGameObject = new()
|
||||
{
|
||||
FullObjectName = prefab.name,
|
||||
ObjectTypeName = SortingLayer.IDToName(prefab.layer),
|
||||
GameSpeed = _gameHandler.MapSpeed,
|
||||
PrefabName = prefab.name,
|
||||
TickTimeWhenTouched = _gameHandler.TickAttemptDuration
|
||||
};
|
||||
CurrentAttempt.PlayersAttempts[args.playerName].BonusTouched.Add(touchedGameObject);
|
||||
RecordPlayerScore(args.playerId, args.playerName);
|
||||
} //
|
||||
|
||||
#endregion
|
||||
#region ENDPOINTS
|
||||
|
||||
public void ResetSession()
|
||||
{
|
||||
_session = null;
|
||||
}
|
||||
|
||||
public void SaveData()
|
||||
{
|
||||
string directoryPath = Path.Combine(Application.persistentDataPath, "SessionsData");
|
||||
if (!Directory.Exists(directoryPath))// Crée le répertoire s'il n'existe pas déjà
|
||||
{
|
||||
Directory.CreateDirectory(directoryPath);
|
||||
}
|
||||
|
||||
var existingFiles = Directory.GetFiles(directoryPath, "*.json");
|
||||
int sessionNumber = existingFiles.Length + 1;
|
||||
Session.SessionNumber = sessionNumber;
|
||||
|
||||
string jsonData = JsonConvert.SerializeObject(Session);
|
||||
|
||||
string fileName = $"Session_{sessionNumber}.json";
|
||||
string filePath = Path.Combine(directoryPath, fileName);
|
||||
File.WriteAllText(filePath, jsonData);
|
||||
|
||||
|
||||
DataSaved = true;
|
||||
Debug.Log($"Session saved to {filePath}");
|
||||
}
|
||||
|
||||
|
||||
public void RecordSessionTime(float time)
|
||||
{
|
||||
Session.SessionTime = time;
|
||||
}
|
||||
public void RecordSessionDate(DateTime date)
|
||||
{
|
||||
Session.Date = date;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record all players scores
|
||||
/// </summary>
|
||||
public void RecordPlayersScore()
|
||||
{
|
||||
Session.RegisteredPlayers.ForEach(p =>
|
||||
{
|
||||
RecordPlayerScore(p.Id, p.Name);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find and record a player score
|
||||
/// </summary>
|
||||
public void RecordPlayerScore(int playerId, string playerName)
|
||||
{
|
||||
int score = (int) _scoreHandler.GetPlayerScore(playerId);
|
||||
var tickTime = _gameHandler.TickAttemptDuration;
|
||||
|
||||
GenericVector<int, int> ScoreByTime = new() { X = tickTime, Y = score };
|
||||
|
||||
CurrentAttempt.PlayersAttempts[playerName].PlayerScoresOverTicksTime.Add(ScoreByTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record a player final score
|
||||
/// </summary>
|
||||
public void RecordPlayerFinalScore(int score, string playerName)
|
||||
{
|
||||
CurrentAttempt.PlayersAttempts[playerName].FinalScore = score;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record the distance parcoured by the player
|
||||
/// </summary>
|
||||
public void RecordPlayerDistance(string playerName)
|
||||
{
|
||||
CurrentAttempt.PlayersAttempts[playerName].Distance = (int)_gameHandler.TotalDistance;
|
||||
}
|
||||
|
||||
public void RecordPlayerAttemptDuration(string playerName)
|
||||
{
|
||||
CurrentAttempt.PlayersAttempts[playerName].AttemptDurationSeconds = _gameHandler.TimeAttemptDuration;
|
||||
CurrentAttempt.PlayersAttempts[playerName].AttemptDurationTicks = _gameHandler.TickAttemptDuration;
|
||||
}
|
||||
#endregion
|
||||
#region METHODS
|
||||
|
||||
private SessionData GetSettings()
|
||||
{
|
||||
SessionData session = new();
|
||||
session.Players.Human = bool.Parse(PlayerPrefs.GetString(Settings.HumanPlayerSelected));
|
||||
session.Players.OmnicientBot = bool.Parse(PlayerPrefs.GetString(Settings.OmnicientBotSelected));
|
||||
session.Players.ObserverBot = bool.Parse(PlayerPrefs.GetString(Settings.ObserverBotSelected));
|
||||
session.Players.IteratorBot = bool.Parse(PlayerPrefs.GetString(Settings.IteratorBotSelected));
|
||||
session.Rules.ChangeSeedEachTry = bool.Parse(PlayerPrefs.GetString(Settings.ChangeSeedSetting));
|
||||
session.Rules.UsesDefaultSeed = bool.Parse(PlayerPrefs.GetString(Settings.UseDefaultSeedSetting));
|
||||
session.Rules.Lasers = bool.Parse(PlayerPrefs.GetString(Settings.LaserSettingToggle));
|
||||
session.Rules.Missiles = bool.Parse(PlayerPrefs.GetString(Settings.MissileSettingToggle));
|
||||
session.Rules.BonusCoins = bool.Parse(PlayerPrefs.GetString(Settings.CoinSettingToggle));
|
||||
session.Rules.MalusCoins = bool.Parse(PlayerPrefs.GetString(Settings.BadCoinSettingToggle));
|
||||
session.Rules.ScoreOnDistance = bool.Parse(PlayerPrefs.GetString(Settings.SurviveScoreSettingToggle));
|
||||
session.Rules.RushMode = bool.Parse(PlayerPrefs.GetString(Settings.RushModeSettingToggle));
|
||||
session.Rules.MaxDistance = PlayerPrefs.GetFloat(Settings.MaxDistanceSettingValue);
|
||||
session.Rules.MaxAttempts = PlayerPrefs.GetInt(Settings.MaxTrySettingValue);
|
||||
session.Rules.MaxSessionTime = PlayerPrefs.GetInt(Settings.MaxTimeSettingValue);
|
||||
session.Rules.MaxSpeed = PlayerPrefs.GetFloat(Settings.MaxSpeedSettingValue);
|
||||
session.Rules.StartSpeed = PlayerPrefs.GetFloat(Settings.StartSpeedSettingValue);
|
||||
session.Rules.DifficultyMultiplier = PlayerPrefs.GetFloat(Settings.DifficultyMultiplierSettingValue);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region LIFECYCLE
|
||||
protected override void Awake()
|
||||
{
|
||||
DataSaved = false;
|
||||
Session = GetSettings();
|
||||
base.Awake();
|
||||
|
||||
_gameHandler = GameHandler.Instance;
|
||||
_scoreHandler = ScoreHandler.Instance;
|
||||
_playerHandler = PlayersHandler.Instance;
|
||||
_levelSpawner = LevelSpawner.Instance;
|
||||
|
||||
_gameHandler.OnAttemptEnded += RegisterAttempt_OnAttemptEnded;
|
||||
_gameHandler.OnAttemptStarted += CreateAttemptRecord_OnAttemptStarted;
|
||||
_playerHandler.OnPlayerInstanciated += RegisterPlayer_OnPlayerInstanciated;
|
||||
_levelSpawner.OnPrefabSpawned += RecordAttemptObstacle_OnPrefabSpawned;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
164
Scripts/GameHandlers/GameController.cs
Normal file
164
Scripts/GameHandlers/GameController.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using static GameHandler;
|
||||
|
||||
public class GameController : SingletonMB<GameController>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public bool IsExiting { get; private set; }
|
||||
public SessionData Session { get; private set; } = new SessionData();
|
||||
|
||||
#endregion
|
||||
#region VARIABLES
|
||||
|
||||
private GameHandler _gameHandler;
|
||||
private ScoreHandler _scoreHandler;
|
||||
private LevelSpawner _LevelSpawner;
|
||||
private PlayersHandler _playerHandler;
|
||||
private DataBearer _dataBearer;
|
||||
|
||||
private int maxSessionTime;
|
||||
private float currentSessionTime;
|
||||
private int maxAttempts;
|
||||
private int currentAttempts;
|
||||
#endregion
|
||||
#region EVENTS
|
||||
public event EventHandler<SessionEventArgs> OnSessionEnded;
|
||||
public class SessionEventArgs : EventArgs
|
||||
{
|
||||
public SessionData session;
|
||||
public SessionEventArgs(SessionData session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessNextAttempt_OnAttemptEnded(object sender, AttemptEventArgs args)
|
||||
{
|
||||
if(!IsExiting)
|
||||
{
|
||||
PrepareNextRound();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region METHODS
|
||||
/// <summary>
|
||||
/// Initialize a new round if there are more available attempts
|
||||
/// </summary>
|
||||
public void PrepareNextRound()
|
||||
{
|
||||
currentAttempts+=1;
|
||||
|
||||
|
||||
if(maxAttempts == 0 || _dataBearer.Session.Attempts.Count < maxAttempts)
|
||||
{
|
||||
_gameHandler.InitAttempt();
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitToMenu("Nombre maximum d'essais atteint");
|
||||
}
|
||||
}
|
||||
|
||||
public void ExitToMenu(string message)
|
||||
{
|
||||
IsExiting = true;
|
||||
Debug.Log("Session END");
|
||||
//StartCoroutine(ExitToMenuCoroutine(message));
|
||||
_gameHandler.ResumeGame();
|
||||
//yield return null;
|
||||
if (!_gameHandler.AttemptEnding) _gameHandler.HaltAttempt(message);
|
||||
Clean();
|
||||
SceneManager.LoadScene("MainMenu");
|
||||
_dataBearer.ResetSession();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//private IEnumerator ExitToMenuCoroutine(string message)
|
||||
//{
|
||||
// _gameHandler.ResumeGame();
|
||||
// //yield return null;
|
||||
// if(!_gameHandler.AttemptEnding) _gameHandler.HaltAttempt(message);
|
||||
// _dataBearer.ResetSession();
|
||||
// Clean();
|
||||
// SceneManager.LoadScene("MainMenu");
|
||||
//}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
#region LIFECYCLE
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
Debug.Log($"Start session for {Session.Rules.MaxAttempts} rounds");
|
||||
_dataBearer.RecordSessionDate(DateTime.Now);
|
||||
|
||||
|
||||
currentSessionTime = 0f;
|
||||
PrepareNextRound();
|
||||
}
|
||||
|
||||
// Awake is called before Start
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_gameHandler = GameHandler.Instance;
|
||||
_scoreHandler = ScoreHandler.Instance;
|
||||
_playerHandler = PlayersHandler.Instance;
|
||||
_dataBearer = DataBearer.Instance;
|
||||
|
||||
_gameHandler.OnAttemptEnded += ProcessNextAttempt_OnAttemptEnded;
|
||||
|
||||
maxAttempts = _dataBearer.Rules.MaxAttempts;
|
||||
maxSessionTime = _dataBearer.Rules.MaxSessionTime;
|
||||
currentAttempts = 0;
|
||||
}
|
||||
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
currentSessionTime += Time.deltaTime;
|
||||
_dataBearer.RecordSessionTime(currentSessionTime);
|
||||
|
||||
|
||||
if (maxSessionTime > 0 && currentSessionTime >= maxSessionTime)
|
||||
{
|
||||
currentSessionTime = maxSessionTime;
|
||||
_dataBearer.RecordSessionTime(currentSessionTime);
|
||||
ExitToMenu("Temps <20>coul<75>");
|
||||
}
|
||||
}
|
||||
|
||||
//Unsubscribe events, save databearer;
|
||||
private void OnDestroy()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
_gameHandler.OnAttemptEnded -= ProcessNextAttempt_OnAttemptEnded;
|
||||
|
||||
if (!_dataBearer.DataSaved)
|
||||
{
|
||||
//datasaving logic
|
||||
_dataBearer.RecordSessionTime(currentSessionTime);
|
||||
|
||||
_dataBearer.SaveData();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
299
Scripts/GameHandlers/GameHandler.cs
Normal file
299
Scripts/GameHandlers/GameHandler.cs
Normal file
@@ -0,0 +1,299 @@
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEngine;
|
||||
using static PlayersHandler;
|
||||
|
||||
/// <summary>
|
||||
/// GameHandler gère le fonctionnement général d'une partie de jeu. Il se charge de faire apparaître les joueurs
|
||||
/// </summary>
|
||||
public class GameHandler : SingletonMB<GameHandler>
|
||||
{
|
||||
|
||||
|
||||
|
||||
#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<AttemptEventArgs> OnAttemptStarted;
|
||||
public event EventHandler<AttemptEventArgs> OnAttemptEnding;
|
||||
public event EventHandler<AttemptEventArgs> OnAttemptEnded;
|
||||
public event EventHandler<EventArgs> OnGamePaused;
|
||||
public event EventHandler<EventArgs> OnGameResumed;
|
||||
public event EventHandler<EventArgs> 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
|
||||
|
||||
/// <summary>
|
||||
/// Return a seed which depend on selected settings and attempt number
|
||||
/// </summary>
|
||||
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<HumanPlayerBehaviour>(playerSpawnPosition);
|
||||
if (_dataBearer.Session.Players.OmnicientBot)
|
||||
_playerHandler.InstanciatePlayer<OmnicientBehaviour>(playerSpawnPosition);
|
||||
if (_dataBearer.Session.Players.ObserverBot)
|
||||
_playerHandler.InstanciatePlayer<ObserverBehaviour>(playerSpawnPosition);
|
||||
if (_dataBearer.Session.Players.IteratorBot)
|
||||
_playerHandler.InstanciatePlayer<IteratorBehaviour>(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<Renderer>())
|
||||
{
|
||||
if(renderer.gameObject.GetComponent<ScorePannelScript>()==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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Halt the current attempt
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
215
Scripts/GameHandlers/PlayersHandler.cs
Normal file
215
Scripts/GameHandlers/PlayersHandler.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using static PlayersHandler;
|
||||
|
||||
public class PlayersHandler : SingletonMB<PlayersHandler>
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
[SerializeField] private GameObject playerPrefab;
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
public Dictionary<int, PlayerScript> Players { get; private set; } = new();
|
||||
|
||||
#endregion
|
||||
#region VARIABLES
|
||||
|
||||
private ScoreHandler _scoreHandler;
|
||||
private GameHandler _gameHandler;
|
||||
|
||||
#endregion
|
||||
#region EVENTS
|
||||
|
||||
/// <summary>
|
||||
/// Fires when a player is instanciated in the game
|
||||
/// </summary>
|
||||
public event EventHandler<PlayerEventArgs> OnPlayerInstanciated;
|
||||
/// <summary>
|
||||
/// Fires when a player have finished their attempt
|
||||
/// </summary>
|
||||
public event EventHandler<PlayerEventArgs> OnPlayerFinished;
|
||||
/// <summary>
|
||||
/// Fires when all players have finished their attempt
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> OnAllPlayersFinished;
|
||||
public class PlayerEventArgs : EventArgs
|
||||
{
|
||||
|
||||
public PlayerScript player;
|
||||
|
||||
public PlayerEventArgs(PlayerScript player)
|
||||
{
|
||||
this.player = player;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region ENDPOINTS
|
||||
/// <summary>
|
||||
/// Remove a player from the game and fire a PlayerFinished event. Fire AllPlayerFinished event if needed
|
||||
/// </summary>
|
||||
/// <param name="playerId"></param>
|
||||
public void RemovePlayer(int playerId)
|
||||
{
|
||||
if (Players.TryGetValue(playerId, out PlayerScript player))
|
||||
{
|
||||
Players.Remove(playerId);
|
||||
if(!_gameHandler.AttemptEnding)
|
||||
OnPlayerFinished.Invoke(this, new PlayerEventArgs(player));
|
||||
player.Dispose();
|
||||
}
|
||||
|
||||
if(Players.Count == 0 && !_gameHandler.AttemptEnding)
|
||||
{
|
||||
OnAllPlayersFinished.Invoke(this, new EventArgs());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool InstanciatePlayer<T>(Vector3 position) where T : MonoBehaviour
|
||||
{
|
||||
|
||||
var player = SpawnPlayer(new Vector3(position.x, position.y, -1));
|
||||
|
||||
PlayerScript script = player.GetComponent<PlayerScript>();
|
||||
player.AddComponent<T>();
|
||||
Players.Add(script.Id, script);
|
||||
|
||||
DecoratePlayer(player);
|
||||
CreateScorePanel(script);
|
||||
|
||||
Debug.Log($"# Player \"{script.Name}\" instanciated !");
|
||||
OnPlayerInstanciated?.Invoke(this, new PlayerEventArgs(script));
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region METHODS
|
||||
|
||||
private GameObject SpawnPlayer(Vector3 position)
|
||||
{
|
||||
var player = Instantiate(playerPrefab, position, Quaternion.identity);
|
||||
var script = player.GetComponent<PlayerScript>();
|
||||
script.SetId(Players.Count);
|
||||
return player;
|
||||
}
|
||||
|
||||
private void CreateScorePanel(PlayerScript script)
|
||||
{
|
||||
_scoreHandler.AddScorePanel(script.Name, script.Id, script.Color);
|
||||
}
|
||||
|
||||
//private GameObject InstantiatePlayer(string playerName, Vector3 position)
|
||||
//{
|
||||
// incrementialId++;
|
||||
// var player = Instantiate(playerPrefab, position, Quaternion.identity);
|
||||
// var script = player.GetComponent<PlayerScript>();
|
||||
// script.SetName(playerName);
|
||||
// script.SetId(incrementialId);
|
||||
|
||||
// _scoreHandler.AddScorePanel(script.Name, script.Id, script.Color);
|
||||
|
||||
// Players.Add(script);
|
||||
// return player;
|
||||
//}
|
||||
|
||||
private void DecoratePlayer(GameObject player)
|
||||
{
|
||||
Transform child = player.transform.Find("sprite");
|
||||
PlayerScript script = player.GetComponent<PlayerScript>();
|
||||
var components = child.GetComponentsInChildren<SpriteRenderer>();
|
||||
var jetpackFront = child.transform.Find("JetpackFront").GetComponent<SpriteRenderer>();
|
||||
var jetpackBack = child.transform.Find("JetpackBack").GetComponent<SpriteRenderer>();
|
||||
|
||||
float alpha = _gameHandler.HaveHumanPlayer && !script.IsHuman ? 0.4f : 1.0f;
|
||||
|
||||
var scriptColor = script.Color!=null ? script.Color : new Color(255, 255, 255);
|
||||
scriptColor.a = alpha;
|
||||
foreach ( var component in components )
|
||||
{
|
||||
component.color = new Color(255, 255, 255, alpha);
|
||||
}
|
||||
|
||||
jetpackFront.color = scriptColor;
|
||||
jetpackBack.color = scriptColor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region LIFECYCLE
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_scoreHandler = ScoreHandler.Instance;
|
||||
_gameHandler = GameHandler.Instance;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//public void InstanciateOmnicient(Vector3 position)
|
||||
//{
|
||||
// var bot = SpawnPlayer(position);
|
||||
|
||||
// PlayerScript script = bot.GetComponent<PlayerScript>();
|
||||
// Players.Add(script.Id, script);
|
||||
// DecoratePlayer(bot);
|
||||
|
||||
// CreateScorePanel(script);
|
||||
|
||||
// OnPlayerInstanciated?.Invoke(this, new PlayerEventArgs(script));
|
||||
//}
|
||||
|
||||
//public void InstanciateObserver(Vector3 position)
|
||||
//{
|
||||
// var bot = SpawnPlayer(position);
|
||||
// PlayerScript script = bot.GetComponent<PlayerScript>();
|
||||
// Players.Add(script.Id, script);
|
||||
// DecoratePlayer(bot);
|
||||
|
||||
// CreateScorePanel(script);
|
||||
|
||||
// OnPlayerInstanciated?.Invoke(this, new PlayerEventArgs(script));
|
||||
//}
|
||||
|
||||
//public void InstanciateIterator(Vector3 position)
|
||||
//{
|
||||
// var bot = SpawnPlayer(position);
|
||||
// PlayerScript script = bot.GetComponent<PlayerScript>();
|
||||
// Players.Add(script.Id, script);
|
||||
// DecoratePlayer(bot);
|
||||
|
||||
// CreateScorePanel(script);
|
||||
|
||||
// OnPlayerInstanciated?.Invoke(this, new PlayerEventArgs(script));
|
||||
//}
|
||||
|
||||
//public void InstanciateHumanPlayer(Vector3 position)
|
||||
//{
|
||||
// Debug.Log("Instanciate Human");
|
||||
|
||||
// var humanPlayer = SpawnPlayer(new Vector3(position.x, position.y, -1));
|
||||
|
||||
// PlayerScript script = humanPlayer.GetComponent<PlayerScript>();
|
||||
// script.IsHuman = true;
|
||||
// humanPlayer.AddComponent<HumanPlayer>();
|
||||
// DecoratePlayer(humanPlayer);
|
||||
|
||||
// CreateScorePanel(script);
|
||||
|
||||
// Players.Add(script.Id, script);
|
||||
// OnPlayerInstanciated?.Invoke(this, new PlayerEventArgs(script));
|
||||
//}
|
201
Scripts/GameHandlers/ScoreHandler.cs
Normal file
201
Scripts/GameHandlers/ScoreHandler.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Assets.Scripts;
|
||||
using System;
|
||||
using static GameController;
|
||||
using static PlayersHandler;
|
||||
using static GameHandler;
|
||||
using System.Linq;
|
||||
|
||||
public class ScoreHandler : SingletonMB<ScoreHandler>
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
private Dictionary<int, PlayerScore> PlayersScores { get; set; }
|
||||
private Dictionary<int, PlayerScore> OuttedPlayers { get; set; }
|
||||
|
||||
#endregion
|
||||
#region VARIABLES
|
||||
|
||||
[SerializeField] private GameObject ScorePanelPrefab;
|
||||
[SerializeField] private GameObject UiDocument;
|
||||
private GameController _gameController;
|
||||
private PlayersHandler _playersHandler;
|
||||
private GameHandler _gameHandler;
|
||||
private DataBearer _dataBearer;
|
||||
|
||||
#endregion
|
||||
#region EVENTS
|
||||
|
||||
public event EventHandler<ScoreEventArgs> OnScoreReachingZero;
|
||||
|
||||
public class ScoreEventArgs : EventArgs
|
||||
{
|
||||
public int playerId;
|
||||
public ScoreEventArgs(int id)
|
||||
{
|
||||
playerId = id;
|
||||
}
|
||||
}
|
||||
internal void RemovePlayer_OnPlayerFinished(object sender, PlayerEventArgs args)
|
||||
{
|
||||
if (PlayersScores.TryGetValue(args.player.Id, out PlayerScore looser))
|
||||
{
|
||||
_dataBearer.RecordPlayerDistance(looser.PlayerName);
|
||||
_dataBearer.RecordPlayerScore(looser.PlayerId, looser.PlayerName);
|
||||
_dataBearer.RecordPlayerAttemptDuration(looser.PlayerName);
|
||||
|
||||
OuttedPlayers.Add(looser.PlayerId, looser);
|
||||
PlayersScores.Remove(looser.PlayerId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
private void RemoveScores_OnAttemptEnded(object sender, AttemptEventArgs args)
|
||||
{
|
||||
List<int> keys;
|
||||
if (PlayersScores.Count > 0)
|
||||
{
|
||||
keys = new List<int>(PlayersScores.Keys);
|
||||
foreach(var key in keys)
|
||||
{
|
||||
_dataBearer.RecordPlayerDistance(PlayersScores[key].PlayerName);
|
||||
_dataBearer.RecordPlayerScore(key, PlayersScores[key].PlayerName);
|
||||
_dataBearer.RecordPlayerAttemptDuration(PlayersScores[key].PlayerName);
|
||||
|
||||
OuttedPlayers.Add(key, PlayersScores[key]);
|
||||
_playersHandler.RemovePlayer(key);
|
||||
}
|
||||
PlayersScores.Clear();
|
||||
}
|
||||
keys = new List<int>(OuttedPlayers.Keys);
|
||||
foreach (var key in keys)
|
||||
{
|
||||
_dataBearer.RecordPlayerFinalScore((int)OuttedPlayers[key].Score, OuttedPlayers[key].PlayerName);
|
||||
|
||||
|
||||
OuttedPlayers[key].ScorePanel.Dispose();
|
||||
}
|
||||
OuttedPlayers = new();
|
||||
PlayersScores = new();
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region ENDPOINTS
|
||||
|
||||
public void AddScorePanel(string playerName, int playerId)
|
||||
{
|
||||
var newScorePanel = Instantiate(ScorePanelPrefab, UiDocument.transform);
|
||||
var scoreScript = newScorePanel.GetComponent<ScorePannelScript>();
|
||||
scoreScript.SetPlayerName(playerName);
|
||||
PlayerScore newRecord = new PlayerScore(playerName, playerId, scoreScript);
|
||||
PlayersScores.Add(playerId, newRecord);
|
||||
}
|
||||
|
||||
public void AddScorePanel(string playerName, int playerId, Color playerColor)
|
||||
{
|
||||
var newScorePanel = Instantiate(ScorePanelPrefab, UiDocument.transform);
|
||||
var scoreScript = newScorePanel.GetComponent<ScorePannelScript>();
|
||||
scoreScript.SetColor(playerColor);
|
||||
scoreScript.SetPlayerName(playerName);
|
||||
PlayerScore newRecord = new PlayerScore(playerName, playerId, scoreScript);
|
||||
PlayersScores.Add(playerId, newRecord);
|
||||
}
|
||||
|
||||
public void SetScore(float score, int playerId)
|
||||
{
|
||||
if (PlayersScores.TryGetValue(playerId, out PlayerScore updatedScore))
|
||||
{
|
||||
updatedScore.Score = score;
|
||||
updatedScore.ScorePanel.SetScore(score);
|
||||
PlayersScores[playerId] = updatedScore;
|
||||
}
|
||||
|
||||
if ( score <= 0) //false &&
|
||||
{
|
||||
OnScoreReachingZero.Invoke(this, new ScoreEventArgs(playerId));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddToScore(float score, int playerId)
|
||||
{
|
||||
if (PlayersScores.TryGetValue(playerId, out PlayerScore updatedScore))
|
||||
{
|
||||
updatedScore.Score += score;
|
||||
SetScore(updatedScore.Score, playerId);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddScoreToAllAlivePlayers(float scoreToAdd)
|
||||
{
|
||||
var keys = new List<int>(PlayersScores.Keys);
|
||||
foreach (var key in keys)
|
||||
{
|
||||
AddToScore(scoreToAdd, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public float GetPlayerScore(int playerId)
|
||||
{
|
||||
return PlayersScores.TryGetValue(playerId, out PlayerScore pscore)
|
||||
? pscore.Score
|
||||
: OuttedPlayers.TryGetValue(playerId, out PlayerScore oscore)
|
||||
? oscore.Score
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#region METHODS
|
||||
#endregion
|
||||
#region LIFECYCLE
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_gameController = GameController.Instance;
|
||||
_playersHandler = PlayersHandler.Instance;
|
||||
_gameHandler = GameHandler.Instance;
|
||||
_dataBearer = DataBearer.Instance;
|
||||
|
||||
_playersHandler.OnPlayerFinished += RemovePlayer_OnPlayerFinished;
|
||||
_gameHandler.OnAttemptEnding += RemoveScores_OnAttemptEnded;
|
||||
|
||||
PlayersScores = new();
|
||||
OuttedPlayers = new();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
struct PlayerScore
|
||||
{
|
||||
|
||||
internal string PlayerName { get; set; }
|
||||
internal int PlayerId { get; set; }
|
||||
internal float Score { get; set; }
|
||||
internal ScorePannelScript ScorePanel { get; set; }
|
||||
public PlayerScore(string playerName, int playerId, ScorePannelScript scorePannel)
|
||||
{
|
||||
PlayerName = playerName;
|
||||
PlayerId = playerId;
|
||||
Score = 0f;
|
||||
ScorePanel = scorePannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
#endregion
|
||||
#region VARIABLES
|
||||
#endregion
|
||||
#region EVENTS
|
||||
#endregion
|
||||
#region METHODS
|
||||
#endregion
|
||||
#region LIFECYCLE
|
||||
#endregion
|
Reference in New Issue
Block a user