Implemented getting and setting high scores from server
This commit is contained in:
parent
c103ffb339
commit
d3e2d425bf
17 changed files with 346 additions and 17 deletions
|
|
@ -6,7 +6,8 @@ namespace DungeonSelection
|
|||
[CreateAssetMenu(fileName = "New Dungeon", menuName = "Dungeon")]
|
||||
public class DungeonData : ScriptableObject
|
||||
{
|
||||
public string DungeonName;
|
||||
public string Name;
|
||||
public int Id;
|
||||
public Sprite Thumbnail;
|
||||
public string SceneName;
|
||||
public string WinMessage;
|
||||
|
|
|
|||
|
|
@ -1,21 +1,51 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Scores;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace DungeonSelection
|
||||
{
|
||||
public class DungeonDisplayData
|
||||
{
|
||||
public DungeonDisplayData(DungeonData dungeonData, List<ScoreDisplay> highScores)
|
||||
{
|
||||
DungeonData = dungeonData;
|
||||
HighScores = highScores;
|
||||
}
|
||||
public DungeonData DungeonData;
|
||||
public List<ScoreDisplay> HighScores;
|
||||
}
|
||||
|
||||
public class ScoreDisplay
|
||||
{
|
||||
public ScoreDisplay(string playerName, int score)
|
||||
{
|
||||
PlayerName = playerName;
|
||||
Score = score;
|
||||
}
|
||||
|
||||
public string PlayerName;
|
||||
public int Score;
|
||||
}
|
||||
|
||||
public class DungeonSelector : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private DungeonData[] dungeons;
|
||||
[SerializeField] private ScoreManager scoreManager;
|
||||
private DungeonData _currentlySelectedDungeonData;
|
||||
private int _currentlySelectedDungeonIndex = 0;
|
||||
private Dictionary<int, List<ScoreDisplay>> scoresByLevelId = new Dictionary<int, List<ScoreDisplay>>();
|
||||
|
||||
private bool _scoresReceived = false;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
UIEvents.NextDungeonClicked += SelectNextDungeon;
|
||||
UIEvents.PreviousDungeonClicked += SelectPreviousDungeon;
|
||||
UIEvents.EnterDungeonClicked += LoadDungeon;
|
||||
scoreManager.ScoresRecieved += HandleScoresRecieved;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
|
|
@ -23,6 +53,7 @@ namespace DungeonSelection
|
|||
UIEvents.NextDungeonClicked -= SelectNextDungeon;
|
||||
UIEvents.PreviousDungeonClicked -= SelectPreviousDungeon;
|
||||
UIEvents.EnterDungeonClicked -= LoadDungeon;
|
||||
scoreManager.ScoresRecieved -= HandleScoresRecieved;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
|
|
@ -30,7 +61,18 @@ namespace DungeonSelection
|
|||
GameEvents.DungeonSelectionStarted?.Invoke();
|
||||
|
||||
_currentlySelectedDungeonData = dungeons[_currentlySelectedDungeonIndex];
|
||||
GameEvents.ShowingDungeon?.Invoke(_currentlySelectedDungeonData);
|
||||
StartCoroutine(WaitForScoresAndShowDungeon());
|
||||
}
|
||||
|
||||
private IEnumerator WaitForScoresAndShowDungeon()
|
||||
{
|
||||
while (!_scoresReceived)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
scoresByLevelId.TryGetValue(_currentlySelectedDungeonData.Id, out var scoreDisplays);
|
||||
GameEvents.ShowingDungeon?.Invoke(new DungeonDisplayData(_currentlySelectedDungeonData, scoreDisplays ?? new List<ScoreDisplay>()));
|
||||
if (_currentlySelectedDungeonIndex == 0)
|
||||
{
|
||||
GameEvents.ShowingFirstDugeon?.Invoke();
|
||||
|
|
@ -47,7 +89,8 @@ namespace DungeonSelection
|
|||
if (_currentlySelectedDungeonIndex + 1 >= dungeons.Length) return;
|
||||
_currentlySelectedDungeonIndex++;
|
||||
_currentlySelectedDungeonData = dungeons[_currentlySelectedDungeonIndex];
|
||||
GameEvents.ShowingDungeon?.Invoke(_currentlySelectedDungeonData);
|
||||
scoresByLevelId.TryGetValue(_currentlySelectedDungeonData.Id, out var scoreDisplays);
|
||||
GameEvents.ShowingDungeon?.Invoke(new DungeonDisplayData(_currentlySelectedDungeonData, scoreDisplays ?? new List<ScoreDisplay>()));
|
||||
if (_currentlySelectedDungeonIndex == dungeons.Length - 1)
|
||||
{
|
||||
GameEvents.ShowingLastDungeon?.Invoke();
|
||||
|
|
@ -59,11 +102,37 @@ namespace DungeonSelection
|
|||
if (_currentlySelectedDungeonIndex - 1 < 0) return;
|
||||
_currentlySelectedDungeonIndex--;
|
||||
_currentlySelectedDungeonData = dungeons[_currentlySelectedDungeonIndex];
|
||||
GameEvents.ShowingDungeon?.Invoke(_currentlySelectedDungeonData);
|
||||
scoresByLevelId.TryGetValue(_currentlySelectedDungeonData.Id, out var scoreDisplays);
|
||||
GameEvents.ShowingDungeon?.Invoke(new DungeonDisplayData(_currentlySelectedDungeonData, scoreDisplays ?? new List<ScoreDisplay>()));
|
||||
if (_currentlySelectedDungeonIndex == 0)
|
||||
{
|
||||
GameEvents.ShowingFirstDugeon?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleScoresRecieved(ScoreEntry[] scores)
|
||||
{
|
||||
scoresByLevelId = new Dictionary<int, List<ScoreDisplay>>();
|
||||
foreach (ScoreEntry score in scores)
|
||||
{
|
||||
if (scoresByLevelId.TryGetValue(score.level_id, out var scoresDisplay))
|
||||
{
|
||||
scoresDisplay.Add(new ScoreDisplay(score.player, score.score));
|
||||
}
|
||||
else
|
||||
{
|
||||
scoresByLevelId[score.level_id] = new List<ScoreDisplay>()
|
||||
{ new ScoreDisplay(score.player, score.score) };
|
||||
}
|
||||
}
|
||||
|
||||
foreach (List<ScoreDisplay> scoresDisplay in scoresByLevelId.Values)
|
||||
{
|
||||
// Sort highest to lowest
|
||||
scoresDisplay.Sort((a, b) => b.Score.CompareTo(a.Score));
|
||||
}
|
||||
|
||||
_scoresReceived = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace DungeonSelection
|
|||
public static Action DungeonSelectionStarted;
|
||||
public static Action ShowingLastDungeon;
|
||||
public static Action ShowingFirstDugeon;
|
||||
public static Action<DungeonData> ShowingDungeon;
|
||||
public static Action<DungeonDisplayData> ShowingDungeon;
|
||||
public static Action<DungeonData> LoadDungeon;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,5 +10,6 @@ namespace DungeonSelection
|
|||
public static Action<DungeonData> EnterDungeonClicked;
|
||||
public static Action CloseRules;
|
||||
public static Action ShowRules;
|
||||
public static Action GetScores;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using DungeonSelection;
|
||||
using Scores;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class LeaveDungeonHandler : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private DungeonData dungeonData;
|
||||
[SerializeField] private ScoreManager scoreManager;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
EndGameController.LeaveDungeonClicked += LeaveDungeon;
|
||||
|
|
@ -20,7 +24,7 @@ public class LeaveDungeonHandler : MonoBehaviour
|
|||
|
||||
private void SaveScore(string name, int score)
|
||||
{
|
||||
Debug.Log($"{name} | {score}");
|
||||
scoreManager.PostScore(name, dungeonData.Id, score);
|
||||
}
|
||||
|
||||
private void LeaveDungeon()
|
||||
|
|
|
|||
8
PuzzleGameProject/Assets/Scripts/Scores.meta
Normal file
8
PuzzleGameProject/Assets/Scripts/Scores.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 294874e36d5de2f49b7a3532869a918e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
122
PuzzleGameProject/Assets/Scripts/Scores/ScoreManager.cs
Normal file
122
PuzzleGameProject/Assets/Scripts/Scores/ScoreManager.cs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using DungeonSelection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Scores
|
||||
{
|
||||
[Serializable]
|
||||
public class ScoreEntry
|
||||
{
|
||||
public int level_id;
|
||||
public string player;
|
||||
public int score;
|
||||
public string timestamp;
|
||||
}
|
||||
|
||||
public class ScoreManager : MonoBehaviour
|
||||
{
|
||||
public event Action<ScoreEntry[]> ScoresRecieved;
|
||||
|
||||
private string _getScoresUrl = "https://games.maxdodd.net/get_scores.php";
|
||||
private string _postScoreUrl = "https://games.maxdodd.net/set_score.php";
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
UIEvents.GetScores += GetScores;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
UIEvents.GetScores -= GetScores;
|
||||
}
|
||||
|
||||
public void GetScores()
|
||||
{
|
||||
StartCoroutine(GetScoresFromServer());
|
||||
}
|
||||
|
||||
public void PostScore(string planterName, int levelId, int score)
|
||||
{
|
||||
StartCoroutine(PostScoreToServer(planterName, levelId, score));
|
||||
}
|
||||
|
||||
IEnumerator GetScoresFromServer()
|
||||
{
|
||||
using (UnityWebRequest request = UnityWebRequest.Get(_getScoresUrl))
|
||||
{
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
string jsonResponse = request.downloadHandler.text;
|
||||
|
||||
try
|
||||
{
|
||||
// Parse the JSON response
|
||||
ScoreEntry[] scores = JsonHelper.FromJson<ScoreEntry>(jsonResponse);
|
||||
|
||||
// Print out the scores
|
||||
foreach (ScoreEntry score in scores)
|
||||
{
|
||||
ScoresRecieved?.Invoke(scores);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Failed to parse scores: " + e.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to fetch scores: " + request.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator PostScoreToServer(string playerName, int levelId, int score)
|
||||
{
|
||||
Debug.Log("Post coroutine started");
|
||||
string url = _postScoreUrl;
|
||||
WWWForm form = new WWWForm();
|
||||
form.AddField("player", playerName);
|
||||
form.AddField("level_id", levelId);
|
||||
form.AddField("score", score);
|
||||
|
||||
using (UnityWebRequest request = UnityWebRequest.Post(url, form))
|
||||
{
|
||||
Debug.Log("Sending Request");
|
||||
yield return request.SendWebRequest();
|
||||
Debug.Log("Request sent");
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
Debug.Log("Score submitted: " + request.downloadHandler.text);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to submit score: " + request.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class to handle JSON arrays
|
||||
public static class JsonHelper
|
||||
{
|
||||
public static T[] FromJson<T>(string json)
|
||||
{
|
||||
string wrappedJson = "{\"items\":" + json + "}";
|
||||
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(wrappedJson);
|
||||
return wrapper.items;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class Wrapper<T>
|
||||
{
|
||||
public T[] items;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c4a5bac4f66aaf84991ec68d8f2a4705
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DungeonSelection;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
|
@ -7,21 +8,25 @@ using UnityEngine.UIElements;
|
|||
|
||||
public class DungeonSelectMenuController : MonoBehaviour
|
||||
{
|
||||
private const int NUM_HIGH_SCORES = 10;
|
||||
|
||||
private Button _next;
|
||||
private Button _previous;
|
||||
private Button _start;
|
||||
private Image _thumbnailImage;
|
||||
private Label _dungeonName;
|
||||
private VisualElement _dungeonThumbnail;
|
||||
private ListView _highScores;
|
||||
|
||||
private DungeonData _currentlyShowingDungeon;
|
||||
private DungeonDisplayData _currentlyShowingDungeon;
|
||||
private List<string> _highScoreData = new List<string>();
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
VisualElement root = GetComponent<UIDocument>().rootVisualElement;
|
||||
|
||||
Button rules = root.Q<Button>("Rules");
|
||||
rules.clicked += UIEvents.ShowRules;
|
||||
rules.clicked += RulesClicked;
|
||||
_dungeonThumbnail = root.Q<VisualElement>("DungeonThumbnail");
|
||||
_next = root.Q<Button>("Next");
|
||||
_next.clicked += NextClicked;
|
||||
|
|
@ -30,16 +35,26 @@ public class DungeonSelectMenuController : MonoBehaviour
|
|||
_start = root.Q<Button>("Start");
|
||||
_start.clicked += StartClicked;
|
||||
_dungeonName = root.Q<Label>("DungeonName");
|
||||
_highScores = root.Q<ListView>("HighScoresListView");
|
||||
_highScores.makeItem = () => new Label();
|
||||
_highScores.bindItem = (element, index) => { (element as Label).text = _highScoreData[index]; };
|
||||
_highScores.itemsSource = _highScoreData;
|
||||
_highScores.makeNoneElement = () => new Label();
|
||||
|
||||
GameEvents.ShowingDungeon += ShowDungeon;
|
||||
GameEvents.ShowingFirstDugeon += () => SetPreviousButtonEnabled(false);
|
||||
GameEvents.ShowingLastDungeon += () => SetNextButtonEnabled(false);
|
||||
}
|
||||
|
||||
private void ShowDungeon(DungeonData dungeon)
|
||||
private void Start()
|
||||
{
|
||||
UIEvents.GetScores?.Invoke();
|
||||
}
|
||||
|
||||
private void ShowDungeon(DungeonDisplayData dungeon)
|
||||
{
|
||||
_currentlyShowingDungeon = dungeon;
|
||||
_dungeonName.text = _currentlyShowingDungeon.DungeonName;
|
||||
_dungeonName.text = _currentlyShowingDungeon.DungeonData.Name;
|
||||
|
||||
if (_thumbnailImage == null)
|
||||
{
|
||||
|
|
@ -48,7 +63,18 @@ public class DungeonSelectMenuController : MonoBehaviour
|
|||
_dungeonThumbnail.Add(_thumbnailImage);
|
||||
}
|
||||
|
||||
_thumbnailImage.image = _currentlyShowingDungeon.Thumbnail.texture;
|
||||
_thumbnailImage.image = _currentlyShowingDungeon.DungeonData.Thumbnail.texture;
|
||||
|
||||
_highScoreData.Clear();
|
||||
int rank = 1;
|
||||
foreach (ScoreDisplay score in dungeon.HighScores)
|
||||
{
|
||||
if (rank > NUM_HIGH_SCORES) break;
|
||||
string formattedScore = $"{rank}. {score.PlayerName} {score.Score}";
|
||||
_highScoreData.Add(formattedScore);
|
||||
rank++;
|
||||
}
|
||||
_highScores.RefreshItems();
|
||||
}
|
||||
|
||||
private void SetPreviousButtonEnabled(bool enabled)
|
||||
|
|
@ -77,6 +103,11 @@ public class DungeonSelectMenuController : MonoBehaviour
|
|||
|
||||
private void StartClicked()
|
||||
{
|
||||
UIEvents.EnterDungeonClicked?.Invoke(_currentlyShowingDungeon);
|
||||
UIEvents.EnterDungeonClicked?.Invoke(_currentlyShowingDungeon.DungeonData);
|
||||
}
|
||||
|
||||
private void RulesClicked()
|
||||
{
|
||||
UIEvents.ShowRules?.Invoke();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue