Keep Away logic finalized and UI polished up

One animation bug found when player picks up hat (possibly when jumping)
This commit is contained in:
djkellerman
2025-03-28 22:50:33 -04:00
parent 2913d4b927
commit c7b1e55a3e
8 changed files with 478 additions and 30 deletions

View File

@@ -21,6 +21,9 @@ public class GameManager : MonoBehaviour
public static string map = "Platformer With Headroom"; // loads a default map as a safety net
public Vector2 spawnPosition;
public Vector2 hatSpawnPosition;
public Canvas LeaderboardCanvas;
public Canvas TimerCanvas;
public GameObject hatObject;
public enum GameMode
{
freeForAll,
@@ -48,6 +51,8 @@ public class GameManager : MonoBehaviour
private void Update() // Continuously updates player hold times
{
if (gameOver) return;
foreach (var player in players)
{
float holdTime = GetPlayerHoldTime(player);
@@ -101,6 +106,12 @@ public class GameManager : MonoBehaviour
public void PlayerDied(Damageable player) // Handles player deaths for the respective gamemode
{
UseItem useItem = player.GetComponent<UseItem>(); // Drop the item the player is holding
if (useItem != null)
{
useItem.DropItem();
}
if (gameMode == GameMode.freeForAll) // Respawns player if they have lives left
{
player.lives--;
@@ -127,6 +138,7 @@ public class GameManager : MonoBehaviour
}
}
private void RespawnPlayer(GameObject player) // Respawns player at the spawn point and resets health
{
RespawnOnTriggerEnter respawnScript = player.GetComponent<RespawnOnTriggerEnter>();
@@ -142,6 +154,10 @@ public class GameManager : MonoBehaviour
{
gameOver = true;
EndGameEvent?.Invoke();
LeaderboardCanvas.gameObject.SetActive(false);
TimerCanvas.gameObject.SetActive(false);
hatObject.SetActive(false);
if (gameMode == GameMode.freeForAll) // Last player alive wins
{
GameObject winner = AlivePlayers()[0];
@@ -184,7 +200,7 @@ public class GameManager : MonoBehaviour
return alivePlayers;
}
public void UpdatePlayerHoldTime(GameObject player, float holdTime)
public void UpdatePlayerHoldTime(GameObject player, float holdTime) // Updates the player's hold time and leaderboard
{
bool shouldSort = false;
@@ -201,11 +217,7 @@ public class GameManager : MonoBehaviour
playerHoldTimes.Add(player, holdTime);
shouldSort = true;
}
// Update the player's hold time text
LeaderboardManager.Instance.UpdatePlayerHoldTimeText(player, holdTime);
// Sort the leaderboard if necessary
if (shouldSort)
{
LeaderboardManager.Instance.UpdateLeaderboard();

View File

@@ -2,13 +2,50 @@ using UnityEngine;
public class HatRespawn : MonoBehaviour
{
void OnTriggerEnter2D(Collider2D collision) // Respawns the hat to the hat spawn position if it falls out of bounds
private float lastInteractionTime;
private const float respawnTime = 10f;
private bool isDropped;
void Start()
{
lastInteractionTime = Time.time;
isDropped = false;
}
void Update() // Checks if the hat has been inactive for too long
{
if (isDropped && Time.time - lastInteractionTime > respawnTime)
{
RespawnHat();
}
}
void OnTriggerEnter2D(Collider2D collision) // Respawns the hat if it falls out of bounds
{
if (collision.gameObject.CompareTag("Platformer Hazard"))
{
transform.position = GameManager.Instance.hatSpawnPosition;
GetComponent<Rigidbody2D>().linearVelocity = Vector2.zero;
transform.rotation = Quaternion.identity;
RespawnHat();
}
}
public void Interact() // Updates the player interaction time
{
lastInteractionTime = Time.time;
isDropped = false;
}
public void OnHatDropped() // Resets the timer when the hat is dropped
{
lastInteractionTime = Time.time;
isDropped = true;
}
private void RespawnHat() // Respawns the hat at the designated spawn position
{
transform.position = GameManager.Instance.hatSpawnPosition;
GetComponent<Rigidbody2D>().linearVelocity = Vector2.zero;
transform.rotation = Quaternion.identity;
lastInteractionTime = Time.time; // Reset the timer after respawning
isDropped = false;
}
}

View File

@@ -33,7 +33,7 @@ public class LeaderboardManager : MonoBehaviour
private void InitializeLeaderboard() // Creates the leaderboard icons for each player
{
RectTransform parentRectTransform = playersParent.GetComponent<RectTransform>();
parentRectTransform.anchoredPosition = new Vector2(-20f, 10f);
parentRectTransform.anchoredPosition = new Vector2(-10f, 10f);
foreach (GameObject player in GameManager.players)
{
@@ -44,27 +44,45 @@ public class LeaderboardManager : MonoBehaviour
}
}
public void UpdateLeaderboard() // Sorts the leaderboard based on player hold times
public void UpdateLeaderboard()
{
List<KeyValuePair<GameObject, float>> sortedList = new List<KeyValuePair<GameObject, float>>(GameManager.playerHoldTimes);
sortedList.Sort((pair1, pair2) => pair2.Value.CompareTo(pair1.Value));
foreach (var player in sortedList)
{
playerIcons[player.Key].transform.SetSiblingIndex(sortedList.IndexOf(player));
}
}
public void UpdatePlayerHoldTimeText(GameObject player, float holdTime) // Updates the hold times of each player shown on the leaderboard
{
if (playerIcons.ContainsKey(player))
for (int i = 0; i < sortedList.Count; i++)
{
TextMeshProUGUI holdTimeText = playerIcons[player].GetComponentInChildren<TextMeshProUGUI>();
if (holdTimeText != null)
var player = sortedList[i];
playerIcons[player.Key].transform.SetSiblingIndex(i);
// Update the number text
TextMeshProUGUI[] textComponents = playerIcons[player.Key].GetComponentsInChildren<TextMeshProUGUI>();
foreach (var textComponent in textComponents)
{
int minutes = Mathf.FloorToInt(holdTime / 60F);
int seconds = Mathf.FloorToInt(holdTime % 60F);
holdTimeText.text = string.Format("{0:0}:{1:00}", minutes, seconds);
if (textComponent.name == "Position Text")
{
textComponent.text = "#" + (i + 1).ToString();
break;
}
}
}
}
public void UpdatePlayerHoldTimeText(GameObject player, float holdTime)
{
if (playerIcons.ContainsKey(player))
{
TextMeshProUGUI[] textComponents = playerIcons[player].GetComponentsInChildren<TextMeshProUGUI>();
foreach (var textComponent in textComponents)
{
if (textComponent.name == "Text (TMP)")
{
int minutes = Mathf.FloorToInt(holdTime / 60F);
int seconds = Mathf.FloorToInt(holdTime % 60F);
textComponent.text = string.Format("{0:0}:{1:00}", minutes, seconds);
break;
}
}
}
}
}

View File

@@ -96,12 +96,17 @@ public class Damageable : MonoBehaviour
{
if (GameManager.Instance != null)
{
GetComponent<UseItem>().DropItem();
UseItem useItem = GetComponent<UseItem>();
if (useItem != null)
{
useItem.DropItem(); // Ensure the player drops the item before the death animation
}
animator.SetBool("die", true);
dying = true;
}
}
public void HandleDeath() // Removes player from dying state after respawn
{
GameManager.Instance.PlayerDied(this);

View File

@@ -7,6 +7,12 @@ public class UseItem : MonoBehaviour
private bool isHoldingItem = false;
private float holdStartTime;
public float holdTime;
private Damageable damageable;
private void Start()
{
damageable = GetComponent<Damageable>();
}
void Update()
{
@@ -25,7 +31,7 @@ public class UseItem : MonoBehaviour
private void OnCollisionEnter2D(Collision2D collision) // Player automatically picks up hat when touching it
{
if (collision.gameObject.CompareTag("Hat") && !isHoldingItem)
if (collision.gameObject.CompareTag("Hat") && !isHoldingItem && !damageable.dying)
{
PickUpItem(collision.gameObject);
}
@@ -33,12 +39,15 @@ public class UseItem : MonoBehaviour
private void PickUpItem(GameObject item) // Player picks up hat and starts hold counter
{
if (damageable.dying) return; // Prevent picking up items if the player is dying
heldItem = item;
isHoldingItem = true;
holdStartTime = Time.time;
item.GetComponent<Collider2D>().enabled = false;
item.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Static;
item.transform.rotation = Quaternion.identity;
item.GetComponent<HatRespawn>().Interact();
if (!GameManager.playerHoldTimes.ContainsKey(gameObject))
{
GameManager.playerHoldTimes[gameObject] = 0f;