Space-Smash-Out/Assets/Scripts/GameManager.cs

240 lines
5.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using static InputActionMaps;
public enum GameState { Starting, Match, End, Paused }
public class GameManager : MonoBehaviour
{
public static GameManager GM { get; private set; }
[SerializeField] ZoneRules zone;
[SerializeField] Announcments announcements;
[SerializeField] int minPlayerCount = 2;
public GameState currentState { get; private set; }
private Dictionary<int, PlayerController> players = new Dictionary<int, PlayerController>();
private Dictionary<int, string> playerControlSchemes = new Dictionary<int, string>();
private float restartMatchTime = 0;
private ControlSchemeDetection controlSchemeDetector;
void Awake()
{
if (GM != null)
{
GM.zone = zone;
GM.announcements = announcements;
Destroy(gameObject);
}
else
{
GM = this;
DontDestroyOnLoad(gameObject);
}
}
// void OnEnable()
// {
// SceneManager.sceneLoaded += OnSceneLoaded;
// }
// void OnDisable()
// {
// SceneManager.sceneLoaded -= OnSceneLoaded;
// }
// void OnSceneLoaded(Scene scene, LoadSceneMode mode)
// {
// StartControlAssignment();
// }
void Update()
{
if (restartMatchTime > 0)
{
restartMatchTime -= Time.deltaTime;
}
else if (currentState == GameState.End)
{
restartMatchTime = 0;
StartNewMatch();
enabled = false;
}
}
// Start is called before the first frame update
void Start()
{
if (currentState == GameState.End)
{
return;
}
currentState = GameState.Starting;
controlSchemeDetector = new ControlSchemeDetection();
controlSchemeDetector.ControlSchemeDetected += DetectPlayerControls;
controlSchemeDetector.EnableDetection();
announcements.AnnounceText("Choose your control schemes \n Each player press a button \n to start the match \n (see description for controls)");
}
void StartMatch()
{
if (zone != null)
{
zone.onPlayZoneExited += CheckLosingCondition;
}
if (announcements != null)
{
announcements.StopAnnouncement();
announcements.QueueAnnounceText("Match Start", 1.6f);
}
}
private void CheckLosingCondition(GameObject go)
{
if (!go.CompareTag("Player") || currentState == GameState.End)
return;
PlayerController pc = go.GetComponent<PlayerController>();
currentState = GameState.End;
zone.onPlayZoneExited -= CheckLosingCondition;
announcements.AnnounceText(pc.playerName + " has lost the match", 2f);
Destroy(go);
restartMatchTime = 2.2f;
enabled = true;
}
private void StartNewMatch()
{
string currentSceneName = SceneManager.GetActiveScene().name;
players.Clear();
SceneManager.LoadScene(currentSceneName);
currentState = GameState.Starting;
}
public void RegisterPlayer(PlayerController pc)
{
if (!players.ContainsKey(pc.playerId))
{
players[pc.playerId] = pc;
}
DetectPlayerControls(this);
}
private void DetectPlayerControls(object sender, string controlScheme = "New Player")
{
if (players.Count < minPlayerCount)
{
return;
}
AssignPlayerControls(controlScheme);
if (players.Count <= playerControlSchemes.Count)
{
if (players.All(pc => PlayerHasActiveControls(pc.Value)))
{
controlSchemeDetector.DisableDetection();
currentState = GameState.Match;
StartMatch();
}
}
}
private void AssignPlayerControls(string controlScheme = "New Player")
{
foreach (int playerId in players.Keys)
{
PlayerController pc = players[playerId];
if (PlayerHasActiveControls(pc))
{
continue;
}
if (playerControlSchemes.ContainsKey(playerId))
{
controlScheme = playerControlSchemes[playerId];
}
else if (playerControlSchemes.ContainsValue(controlScheme))
{
return;
}
if (controlScheme.Contains("Keyboard"))
{
pc.playerInput.SwitchCurrentControlScheme(controlScheme, Keyboard.current);
}
else if (controlScheme.Contains("Controller"))
{
pc.playerInput.SwitchCurrentControlScheme(controlScheme, Gamepad.current);
}
if (controlScheme != "New Player")
{
playerControlSchemes[playerId] = controlScheme;
}
}
}
private bool PlayerHasActiveControls(PlayerController pc)
{
if (pc == null)
{
return false;
}
string currentScheme = pc.playerInput.currentControlScheme;
if (currentScheme != null && currentScheme != "New Player")
{
return true;
}
return false;
}
}
public class ControlSchemeDetection : IPlayerActions
{
InputActionMaps actionMaps;
public event EventHandler<string> ControlSchemeDetected;
public ControlSchemeDetection()
{
actionMaps = new InputActionMaps();
actionMaps.Player.SetCallbacks(this);
}
public void EnableDetection()
{
actionMaps.Player.Enable();
}
public void DisableDetection()
{
actionMaps.Player.Disable();
}
public void OnBoost(InputAction.CallbackContext context)
{
readControlScheme(context);
}
public void OnReset(InputAction.CallbackContext context)
{
readControlScheme(context);
}
public void OnSteer(InputAction.CallbackContext context)
{
readControlScheme(context);
}
public void OnThrust(InputAction.CallbackContext context)
{
readControlScheme(context);
}
public void readControlScheme(InputAction.CallbackContext context)
{
if (!context.canceled || context.performed)
{
return;
}
int bindingIndex = context.action.GetBindingIndexForControl(context.control);
InputBinding binding = context.action.bindings[bindingIndex];
string controlScheme = binding.groups.Split(';')[0];
ControlSchemeDetected.Invoke(this, controlScheme);
}
}