Files
Crash-Course/Assets/Scripts/Game/GameManager.cs

259 lines
8.6 KiB
C#
Raw Normal View History

2025-04-04 12:09:40 -04:00
using System.Collections;
2025-02-19 20:11:57 -05:00
using System.Collections.Generic;
2025-02-17 18:23:05 -05:00
using UnityEngine;
using UnityEngine.Events;
2025-03-07 11:56:19 -05:00
using UnityEngine.InputSystem;
2025-02-17 18:23:05 -05:00
public class GameManager : MonoBehaviour
{
2025-02-28 14:01:55 -05:00
public static GameManager Instance { get; private set; }
2025-03-28 13:00:37 -04:00
public float time = 180f;
public delegate void GameEvent();
public event GameEvent StartGameEvent;
public event GameEvent EndGameEvent;
public static List<GameObject> players = new List<GameObject>();
2025-03-07 16:25:59 -05:00
public static List<Color> playerColors = new List<Color>();
2025-03-07 16:50:04 -05:00
public float offset = 1f;
public static bool music = true;
2025-03-07 16:50:04 -05:00
public bool gameOver = false;
2025-03-20 14:45:29 -04:00
public GameTimer gameTimer;
public static Dictionary<GameObject, float> playerHoldTimes = new Dictionary<GameObject, float>();
public static GameMode gameMode = GameMode.freeForAll; // loads a default gamemode as a safety net
public static string map = "Platformer With Headroom"; // loads a default map as a safety net
public Vector2 spawnPosition;
2025-03-29 15:18:27 -04:00
public List<Vector2> hatSpawnPositions = new List<Vector2>();
public Canvas LeaderboardCanvas;
public Canvas TimerCanvas;
public GameObject hatObject;
public enum GameMode
{
freeForAll,
keepAway,
obstacleCourse
}
2025-02-28 14:01:55 -05:00
private void Awake() // Ensures only one instance of GameManager exists
2025-03-04 20:10:28 -05:00
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
}
}
private void Start() // Starts the game and music
2025-02-28 13:17:06 -05:00
{
MusicManager.Instance.StartPlaylist();
2025-02-28 13:17:06 -05:00
StartGame();
}
2025-03-28 21:27:09 -04:00
private void Update() // Continuously updates player hold times
{
if (gameOver) return;
2025-03-31 18:43:02 -04:00
if (gameMode == GameMode.keepAway)
2025-03-28 21:27:09 -04:00
{
2025-03-31 18:43:02 -04:00
foreach (var player in players)
{
float holdTime = GetPlayerHoldTime(player);
UpdatePlayerHoldTime(player, holdTime);
}
2025-03-28 21:27:09 -04:00
}
}
private float GetPlayerHoldTime(GameObject player)
{
UseItem useItem = player.GetComponent<UseItem>();
if (useItem != null)
{
return useItem.holdTime;
}
return 0f;
}
public void StartGame() // Sets up the proper gamemode
2025-02-26 18:16:51 -05:00
{
2025-03-20 14:45:29 -04:00
GameManager.playerHoldTimes.Clear();
2025-03-07 16:50:04 -05:00
if (GameManager.players.Count == 0) return;
StartGameEvent?.Invoke();
2025-03-03 18:23:54 -05:00
print("Starting game with mode: " + gameMode + " and map: " + map);
if (gameMode == GameMode.freeForAll) // Sets up the game for free for all mode
2025-02-26 18:16:51 -05:00
{
foreach (GameObject player in players)
{
2025-03-25 11:56:06 -04:00
player.transform.position = spawnPosition + (offset * players.IndexOf(player) * Vector2.right);
2025-03-17 19:59:41 -04:00
player.GetComponent<Damageable>().lives = 5;
}
2025-02-26 18:16:51 -05:00
}
if (gameMode == GameMode.keepAway) // Sets up the game for keep away mode
2025-02-26 18:16:51 -05:00
{
2025-03-28 13:00:37 -04:00
gameTimer.startTime = time;
2025-03-20 14:45:29 -04:00
gameTimer.StartTimer();
foreach (GameObject player in players)
{
2025-03-25 11:56:06 -04:00
player.transform.position = spawnPosition + (offset * players.IndexOf(player) * Vector2.right);
2025-03-17 19:59:41 -04:00
player.GetComponent<Damageable>().lives = 0;
}
2025-02-26 18:16:51 -05:00
}
if (gameMode == GameMode.obstacleCourse) // Sets up the game for obstacle course mode
2025-02-26 18:16:51 -05:00
{
foreach (GameObject player in players)
{
player.transform.position = spawnPosition;
2025-03-31 18:28:05 -04:00
player.GetComponent<Damageable>().lives = 0;
}
2025-02-26 18:16:51 -05:00
}
}
public void PlayerDied(Damageable player) // Handles player deaths for the respective gamemode
2025-02-28 14:01:55 -05:00
{
UseItem useItem = player.GetComponent<UseItem>(); // Drop the item the player is holding
if (useItem != null)
{
2025-04-04 12:09:40 -04:00
if (gameOver == false)
{
useItem.DropItem();
}
else
{
return; // Prevents winner from dropping the item if the game is over
}
}
if (gameMode == GameMode.freeForAll) // Respawns player if they have lives left
2025-02-28 14:01:55 -05:00
{
2025-03-07 10:03:16 -05:00
player.lives--;
2025-03-08 13:33:19 -05:00
if (player.lives <= 0 && !gameOver)
2025-02-28 14:01:55 -05:00
{
2025-03-08 13:33:19 -05:00
player.gameObject.SetActive(false);
if (AlivePlayers().Count <= 1)
{
GameOver(); // Winner is called when only one player is left
2025-03-08 13:33:19 -05:00
}
2025-02-28 14:01:55 -05:00
}
else
{
2025-03-07 10:03:16 -05:00
RespawnPlayer(player.gameObject);
2025-02-28 14:01:55 -05:00
}
}
if (gameMode == GameMode.keepAway) // Always respawns player regardless of lives
2025-02-28 14:01:55 -05:00
{
2025-03-17 19:59:41 -04:00
RespawnPlayer(player.gameObject);
2025-02-28 14:01:55 -05:00
}
if (gameMode == GameMode.obstacleCourse)
{
2025-03-31 18:43:02 -04:00
RespawnPlayer(player.gameObject);
2025-02-28 14:01:55 -05:00
}
}
private void RespawnPlayer(GameObject player) // Respawns player at the spawn point and resets health
2025-02-28 14:01:55 -05:00
{
RespawnOnTriggerEnter respawnScript = player.GetComponent<RespawnOnTriggerEnter>();
if (respawnScript != null)
{
player.transform.position = respawnScript.spawnPoint;
player.GetComponent<Damageable>().ResetDamage();
2025-03-07 10:03:16 -05:00
player.GetComponent<Damageable>().Respawn();
2025-02-28 14:01:55 -05:00
}
}
public void GameOver() // Ends game and displays winner
2025-02-28 14:01:55 -05:00
{
2025-03-08 13:33:19 -05:00
gameOver = true;
EndGameEvent?.Invoke();
LeaderboardCanvas.gameObject.SetActive(false);
TimerCanvas.gameObject.SetActive(false);
if (gameMode == GameMode.freeForAll) // Last player alive wins
2025-03-20 14:45:29 -04:00
{
GameObject winner = AlivePlayers()[0];
print(winner.name + " is the winner");
FindFirstObjectByType<PlayerCameraMovement>().WinScene(winner);
WinScreen.Instance.ShowWinScreen(players.IndexOf(winner) + 1);
2025-03-20 14:45:29 -04:00
FindFirstObjectByType<LifeDisplayManager>().HideLifeDisplay();
}
if (gameMode == GameMode.keepAway) // Player with the most time holding the hat wins
2025-03-20 14:45:29 -04:00
{
GameObject winner = null;
2025-03-31 18:28:05 -04:00
float maxHoldTime = -1f;
2025-03-20 14:45:29 -04:00
foreach (var player in GameManager.playerHoldTimes)
{
if (player.Value > maxHoldTime)
{
maxHoldTime = player.Value;
winner = player.Key;
}
}
if (winner != null)
{
print(winner.name + " is the winner with " + maxHoldTime + " seconds!");
FindFirstObjectByType<PlayerCameraMovement>().WinScene(winner);
WinScreen.Instance.ShowWinScreen(players.IndexOf(winner) + 1);
FindFirstObjectByType<LifeDisplayManager>().HideLifeDisplay();
2025-04-04 12:09:40 -04:00
StartCoroutine(MoveHatToWinner(winner));
hatObject.SetActive(true);
hatObject.GetComponent<Collider2D>().enabled = true;
hatObject.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
2025-03-20 14:45:29 -04:00
}
}
2025-04-04 12:09:40 -04:00
if (gameMode == GameMode.obstacleCourse) // Player who reached the end first wins
2025-03-31 18:28:05 -04:00
{
GameObject winner = ObstacleCourse.playerWon;
print(winner.name + " is the winner!");
FindFirstObjectByType<PlayerCameraMovement>().WinScene(winner);
WinScreen.Instance.ShowWinScreen(players.IndexOf(winner) + 1);
FindFirstObjectByType<LifeDisplayManager>().HideLifeDisplay();
}
2025-03-07 10:03:16 -05:00
}
2025-04-04 12:09:40 -04:00
private IEnumerator MoveHatToWinner(GameObject winner)
{
while (!winner.GetComponent<UseItem>().IsHoldingItem())
{
hatObject.transform.position = winner.transform.position + Vector3.up * 3/2;
yield return null;
}
}
2025-03-07 10:03:16 -05:00
public List<GameObject> AlivePlayers() // Returns a list of all players that are alive
2025-03-07 10:03:16 -05:00
{
List<GameObject> alivePlayers = new();
foreach (GameObject player in players)
{
if (player.activeInHierarchy) alivePlayers.Add(player);
}
return alivePlayers;
2025-02-28 14:01:55 -05:00
}
2025-03-20 14:45:29 -04:00
public void UpdatePlayerHoldTime(GameObject player, float holdTime) // Updates the player's hold time and leaderboard
2025-03-20 14:45:29 -04:00
{
2025-03-28 21:27:09 -04:00
bool shouldSort = false;
2025-03-25 22:21:21 -04:00
if (playerHoldTimes.ContainsKey(player))
{
2025-03-28 21:27:09 -04:00
if (holdTime > playerHoldTimes[player])
{
shouldSort = true;
}
2025-03-25 22:21:21 -04:00
playerHoldTimes[player] = holdTime;
}
else
{
playerHoldTimes.Add(player, holdTime);
2025-03-28 21:27:09 -04:00
shouldSort = true;
}
LeaderboardManager.Instance.UpdatePlayerHoldTimeText(player, holdTime);
if (shouldSort)
{
LeaderboardManager.Instance.UpdateLeaderboard();
2025-03-25 22:21:21 -04:00
}
2025-03-20 14:45:29 -04:00
}
2025-02-17 18:23:05 -05:00
}