added scoring system for the bow game
This commit is contained in:
@@ -5,6 +5,7 @@ using _PROJECT.Scripts.Bow;
|
||||
using FishNet.Object;
|
||||
using FishNet.Object.Synchronizing;
|
||||
using TMPro;
|
||||
using Unity.XR.CoreUtils;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
@@ -24,6 +25,8 @@ public class ArcheryRange : NetworkBehaviour
|
||||
public float roundLength = 60f;
|
||||
public float targetSpawnTime = 3f;
|
||||
|
||||
public KeyboardManager keyboardManager;
|
||||
|
||||
private List<ArcheryTarget> _targets;
|
||||
|
||||
[SyncVar]
|
||||
@@ -33,6 +36,10 @@ public class ArcheryRange : NetworkBehaviour
|
||||
private float _nextTargetTime;
|
||||
private bool _roundActive;
|
||||
|
||||
private readonly List<XROrigin> _presentPlayers = new();
|
||||
|
||||
private XROrigin _scoredPlayer;
|
||||
|
||||
public override void OnStartServer()
|
||||
{
|
||||
base.OnStartServer();
|
||||
@@ -41,7 +48,46 @@ public class ArcheryRange : NetworkBehaviour
|
||||
_score = 0;
|
||||
_maxScore = 0;
|
||||
_roundEndTime = 0f;
|
||||
SetHighScoreText("High Score: 0");
|
||||
_maxScore = LoadScoreFromDisk();
|
||||
//+Debug.Log($"highScore is {_maxScore}");
|
||||
|
||||
StartCoroutine(DelayedSetHighScoreText(10f)); // Cannot immediately assign these values because fishnet needs time.
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator DelayedSetHighScoreText(float delaySeconds)
|
||||
{
|
||||
yield return new WaitForSeconds(delaySeconds);
|
||||
SetHighScoreText($"High Score: {_maxScore}");
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
SetHighScoreText($"High Score: {_maxScore}"); // Refresh high score UI
|
||||
|
||||
XROrigin enteredPlayer = other.GetComponent<XROrigin>();
|
||||
if (enteredPlayer == null || _presentPlayers.Contains(enteredPlayer))
|
||||
return;
|
||||
|
||||
_presentPlayers.Add(enteredPlayer); // Adds to the end
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
XROrigin exitedPlayer = other.GetComponent<XROrigin>();
|
||||
if (exitedPlayer == null) return;
|
||||
|
||||
_presentPlayers.Remove(exitedPlayer); // Shifts others left automatically
|
||||
|
||||
if (exitedPlayer == _scoredPlayer) keyboardManager.DeActivate(); // If the player <20>refuses to enter their name.
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void OnStopServer()
|
||||
{
|
||||
base.OnStopServer();
|
||||
SaveScoreToDisk(_maxScore);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
@@ -101,9 +147,30 @@ public class ArcheryRange : NetworkBehaviour
|
||||
|
||||
_targets = new List<ArcheryTarget>();
|
||||
if (_maxScore < _score) _maxScore = _score;
|
||||
|
||||
if(_presentPlayers.Count != 0) // If there are players in the area.
|
||||
{
|
||||
// Gives the score to the player longest-lasting in the area. It would be better to give it to the player that fired the starting arrow, but I'm not spending 10 hours on this.
|
||||
|
||||
XROrigin scoringPlayer = _presentPlayers.First();
|
||||
|
||||
Menu playermenu = scoringPlayer.GetComponentInChildren<Menu>();
|
||||
|
||||
_scoredPlayer = scoringPlayer;
|
||||
|
||||
playermenu.setCanvasVisibility(false); // Deactivates the menu to avoid overlap issues.
|
||||
|
||||
Transform keyboardPlacement = playermenu.updateMenuTransform();
|
||||
|
||||
keyboardManager.Activate(_score, keyboardPlacement);
|
||||
|
||||
SaveScoreToDisk(_maxScore);
|
||||
SetHighScoreText($"High Score: {_maxScore}");
|
||||
}
|
||||
_score = 0;
|
||||
SetHighScoreText($"High Score: {_maxScore}");
|
||||
|
||||
startTarget.ShowTarget();
|
||||
|
||||
_roundActive = false;
|
||||
SetTimeLeftText("");
|
||||
}
|
||||
@@ -139,5 +206,29 @@ public class ArcheryRange : NetworkBehaviour
|
||||
public void SetTimeLeftText(string text)
|
||||
{
|
||||
timeLeftText.text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
public class SaveData
|
||||
{
|
||||
public float HighScore;
|
||||
}
|
||||
|
||||
public void SaveScoreToDisk(float highScore)
|
||||
{
|
||||
SaveData data = new SaveData { HighScore = highScore };
|
||||
string json = JsonUtility.ToJson(data);
|
||||
System.IO.File.WriteAllText("highscore.json", json);
|
||||
}
|
||||
public float LoadScoreFromDisk()
|
||||
{
|
||||
if (System.IO.File.Exists("highscore.json"))
|
||||
{
|
||||
string json = System.IO.File.ReadAllText("highscore.json");
|
||||
SaveData data = JsonUtility.FromJson<SaveData>(json);
|
||||
return data.HighScore;
|
||||
}
|
||||
|
||||
return -1f; // default score
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
147
Assets/_PROJECT/Components/Bow/Scripts/KeyBoardManager.cs
Normal file
147
Assets/_PROJECT/Components/Bow/Scripts/KeyBoardManager.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class KeyboardManager : MonoBehaviour
|
||||
{
|
||||
public enum ShiftMode { Lowercase, NextUppercase, Uppercase }
|
||||
|
||||
[Header("UI References")]
|
||||
public TMP_Text nameTextField;
|
||||
public TMP_Text scoreTextField;
|
||||
public Button shiftButton;
|
||||
public Button backspaceButton;
|
||||
public Button enterButton;
|
||||
public Button spaceButton;
|
||||
|
||||
[Header("Letter Buttons")]
|
||||
public List<Button> letterButtons;
|
||||
|
||||
public int inputTextLimit = 12;
|
||||
public ScoreBoard scoreBoard; // Reference to ScoreBoard
|
||||
public string placeHolderText;
|
||||
private string _input = "";
|
||||
private float _currentScore;
|
||||
private ShiftMode _shiftMode = ShiftMode.Lowercase;
|
||||
|
||||
void Start()
|
||||
{
|
||||
foreach (var button in letterButtons)
|
||||
{
|
||||
button.onClick.AddListener(() => OnLetterPressed(button));
|
||||
}
|
||||
|
||||
shiftButton.onClick.AddListener(OnShiftPressed);
|
||||
backspaceButton.onClick.AddListener(OnBackspacePressed);
|
||||
enterButton.onClick.AddListener(OnEnterPressed);
|
||||
spaceButton.onClick.AddListener(OnSpacePressed);
|
||||
|
||||
|
||||
|
||||
gameObject.SetActive(false); // Start disabled
|
||||
}
|
||||
|
||||
public void Activate(float score, Transform assignedTransform)
|
||||
{
|
||||
_currentScore = score;
|
||||
_input = "";
|
||||
nameTextField.text = placeHolderText;
|
||||
Debug.Log(_currentScore);
|
||||
Debug.Log(_currentScore.ToString());
|
||||
scoreTextField.text = _currentScore.ToString();
|
||||
gameObject.SetActive(true);
|
||||
|
||||
gameObject.transform.position = assignedTransform.position;
|
||||
gameObject.transform.rotation = assignedTransform.rotation;
|
||||
|
||||
}
|
||||
|
||||
public void DeActivate()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void addToInput(string newInput)
|
||||
{
|
||||
|
||||
if (_input.Length < inputTextLimit)
|
||||
_input += newInput;
|
||||
}
|
||||
|
||||
void OnLetterPressed(Button button)
|
||||
{
|
||||
var label = button.GetComponentInChildren<TMP_Text>();
|
||||
if (label == null) return;
|
||||
|
||||
string letter = label.text;
|
||||
|
||||
switch (_shiftMode)
|
||||
{
|
||||
case ShiftMode.Lowercase:
|
||||
addToInput(letter.ToLower());
|
||||
break;
|
||||
case ShiftMode.Uppercase:
|
||||
addToInput(letter.ToUpper());
|
||||
break;
|
||||
case ShiftMode.NextUppercase:
|
||||
addToInput(letter.ToUpper());
|
||||
_shiftMode = ShiftMode.Lowercase;
|
||||
UpdateKeyLabels();
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
void OnShiftPressed()
|
||||
{
|
||||
_shiftMode = _shiftMode switch
|
||||
{
|
||||
ShiftMode.Lowercase => ShiftMode.NextUppercase,
|
||||
ShiftMode.NextUppercase => ShiftMode.Uppercase,
|
||||
ShiftMode.Uppercase => ShiftMode.Lowercase,
|
||||
_ => ShiftMode.Lowercase
|
||||
};
|
||||
|
||||
UpdateKeyLabels();
|
||||
}
|
||||
|
||||
void OnBackspacePressed()
|
||||
{
|
||||
if (_input.Length > 0)
|
||||
_input = _input.Substring(0, _input.Length - 1);
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
void OnEnterPressed()
|
||||
{
|
||||
if (_input.Length > 0)
|
||||
{
|
||||
scoreBoard.SaveScore(_input, _currentScore);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OnSpacePressed()
|
||||
{
|
||||
addToInput(" ");
|
||||
UpdateOutput();
|
||||
}
|
||||
|
||||
void UpdateOutput()
|
||||
{
|
||||
nameTextField.text = _input;
|
||||
}
|
||||
|
||||
void UpdateKeyLabels()
|
||||
{
|
||||
foreach (var button in letterButtons)
|
||||
{
|
||||
var label = button.GetComponentInChildren<TMP_Text>();
|
||||
if (label == null) continue;
|
||||
|
||||
label.text = _shiftMode == ShiftMode.Lowercase ? label.text.ToLower() : label.text.ToUpper();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 148cae225a875104fa024390b4e9f9d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
70
Assets/_PROJECT/Components/Bow/Scripts/ScoreBoard.cs
Normal file
70
Assets/_PROJECT/Components/Bow/Scripts/ScoreBoard.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class ScoreBoard : MonoBehaviour
|
||||
{
|
||||
[System.Serializable]
|
||||
public class ScoreEntry
|
||||
{
|
||||
public string name;
|
||||
public float score;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ScoreData
|
||||
{
|
||||
public List<ScoreEntry> entries = new List<ScoreEntry>();
|
||||
}
|
||||
|
||||
public TMP_Text scoreDisplayText;
|
||||
private string filePath => Path.Combine(Application.persistentDataPath, "highscores.json");
|
||||
|
||||
private ScoreData _scoreData = new ScoreData();
|
||||
|
||||
void Start()
|
||||
{
|
||||
LoadScores();
|
||||
DisplayTopScores();
|
||||
}
|
||||
|
||||
public void SaveScore(string playerName, float score)
|
||||
{
|
||||
LoadScores();
|
||||
|
||||
_scoreData.entries.Add(new ScoreEntry { name = playerName, score = score });
|
||||
_scoreData.entries = _scoreData.entries.OrderByDescending(e => e.score).Take(15).ToList(); // Keep top 15
|
||||
string json = JsonUtility.ToJson(_scoreData, true);
|
||||
File.WriteAllText(filePath, json);
|
||||
|
||||
DisplayTopScores();
|
||||
}
|
||||
|
||||
public void LoadScores()
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
string json = File.ReadAllText(filePath);
|
||||
_scoreData = JsonUtility.FromJson<ScoreData>(json);
|
||||
}
|
||||
}
|
||||
|
||||
private void DisplayTopScores()
|
||||
{
|
||||
if (_scoreData.entries.Count == 0)
|
||||
{
|
||||
scoreDisplayText.text = "No scores yet.";
|
||||
return;
|
||||
}
|
||||
|
||||
scoreDisplayText.text = "Top Scores:\n";
|
||||
for (int i = 0; i < _scoreData.entries.Count; i++)
|
||||
{
|
||||
var entry = _scoreData.entries[i];
|
||||
scoreDisplayText.text += $"{i + 1}. {entry.name} - {entry.score}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/_PROJECT/Components/Bow/Scripts/ScoreBoard.cs.meta
Normal file
11
Assets/_PROJECT/Components/Bow/Scripts/ScoreBoard.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89213b914f7728045bdfc55d900827c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user