Implemented getting and setting high scores from server

This commit is contained in:
Max 2025-03-07 09:26:54 +01:00
parent c103ffb339
commit d3e2d425bf
17 changed files with 346 additions and 17 deletions

View file

@ -12,7 +12,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 6b94e2e73105498fac9021dca1250c4b, type: 3} m_Script: {fileID: 11500000, guid: 6b94e2e73105498fac9021dca1250c4b, type: 3}
m_Name: 01_30x30_5_monster m_Name: 01_30x30_5_monster
m_EditorClassIdentifier: m_EditorClassIdentifier:
DungeonName: Abomination Vault Name: Abomination Vaults
Id: 1
Thumbnail: {fileID: 21300000, guid: 64f388d4f370f6d4db97a9fd30afb6a9, type: 3} Thumbnail: {fileID: 21300000, guid: 64f388d4f370f6d4db97a9fd30afb6a9, type: 3}
SceneName: 01_30x30_5_monster SceneName: 01_30x30_5_monster
WinMessage: Now you may return to Otari a hero! WinMessage: Now you may return to Otari a hero!

View file

@ -12,7 +12,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 6b94e2e73105498fac9021dca1250c4b, type: 3} m_Script: {fileID: 11500000, guid: 6b94e2e73105498fac9021dca1250c4b, type: 3}
m_Name: 02_30x30_5_monster m_Name: 02_30x30_5_monster
m_EditorClassIdentifier: m_EditorClassIdentifier:
DungeonName: Tomb of Annihilation Name: Tomb of Annihilation
Id: 2
Thumbnail: {fileID: 21300000, guid: 2d9ec4bca04e08448924650a381b2041, type: 3} Thumbnail: {fileID: 21300000, guid: 2d9ec4bca04e08448924650a381b2041, type: 3}
SceneName: 02_30x30_5_monster SceneName: 02_30x30_5_monster
WinMessage: The curse is broken, but the scars remain WinMessage: The curse is broken, but the scars remain

View file

@ -12,7 +12,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 6b94e2e73105498fac9021dca1250c4b, type: 3} m_Script: {fileID: 11500000, guid: 6b94e2e73105498fac9021dca1250c4b, type: 3}
m_Name: 03_30x30_5_monster m_Name: 03_30x30_5_monster
m_EditorClassIdentifier: m_EditorClassIdentifier:
DungeonName: Descent Into Avernus Name: Descent into Avernus
Id: 3
Thumbnail: {fileID: 21300000, guid: ef152ae0fa820c2429781e262a724da4, type: 3} Thumbnail: {fileID: 21300000, guid: ef152ae0fa820c2429781e262a724da4, type: 3}
SceneName: 03_30x30_5_monster SceneName: 03_30x30_5_monster
WinMessage: You killed them all... but at what cost? WinMessage: You killed them all... but at what cost?

View file

@ -8037,6 +8037,7 @@ GameObject:
- component: {fileID: 1417835872} - component: {fileID: 1417835872}
- component: {fileID: 1417835871} - component: {fileID: 1417835871}
- component: {fileID: 1417835873} - component: {fileID: 1417835873}
- component: {fileID: 1417835874}
m_Layer: 0 m_Layer: 0
m_Name: GameManager m_Name: GameManager
m_TagString: Untagged m_TagString: Untagged
@ -8089,6 +8090,19 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
dungeonData: {fileID: 11400000, guid: acaf9288bf3a20c41a924587743eba81, type: 2} dungeonData: {fileID: 11400000, guid: acaf9288bf3a20c41a924587743eba81, type: 2}
scoreManager: {fileID: 1417835874}
--- !u!114 &1417835874
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1417835870}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c4a5bac4f66aaf84991ec68d8f2a4705, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1425310156 --- !u!1 &1425310156
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View file

@ -8989,6 +8989,7 @@ GameObject:
- component: {fileID: 1417835872} - component: {fileID: 1417835872}
- component: {fileID: 1417835871} - component: {fileID: 1417835871}
- component: {fileID: 1417835873} - component: {fileID: 1417835873}
- component: {fileID: 1417835874}
m_Layer: 0 m_Layer: 0
m_Name: GameManager m_Name: GameManager
m_TagString: Untagged m_TagString: Untagged
@ -9041,6 +9042,19 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
dungeonData: {fileID: 11400000, guid: 74afdc22b525eeb43935ac56a2da2b37, type: 2} dungeonData: {fileID: 11400000, guid: 74afdc22b525eeb43935ac56a2da2b37, type: 2}
scoreManager: {fileID: 1417835874}
--- !u!114 &1417835874
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1417835870}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c4a5bac4f66aaf84991ec68d8f2a4705, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &1431493912 --- !u!1001 &1431493912
PrefabInstance: PrefabInstance:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View file

@ -9440,6 +9440,7 @@ GameObject:
- component: {fileID: 1417835872} - component: {fileID: 1417835872}
- component: {fileID: 1417835871} - component: {fileID: 1417835871}
- component: {fileID: 1417835873} - component: {fileID: 1417835873}
- component: {fileID: 1417835874}
m_Layer: 0 m_Layer: 0
m_Name: GameManager m_Name: GameManager
m_TagString: Untagged m_TagString: Untagged
@ -9492,6 +9493,19 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
dungeonData: {fileID: 11400000, guid: be76377cae8ede04ba4523be6e094f17, type: 2} dungeonData: {fileID: 11400000, guid: be76377cae8ede04ba4523be6e094f17, type: 2}
scoreManager: {fileID: 1417835874}
--- !u!114 &1417835874
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1417835870}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c4a5bac4f66aaf84991ec68d8f2a4705, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &1426145005 --- !u!1001 &1426145005
PrefabInstance: PrefabInstance:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View file

@ -153,6 +153,7 @@ MonoBehaviour:
- {fileID: 11400000, guid: acaf9288bf3a20c41a924587743eba81, type: 2} - {fileID: 11400000, guid: acaf9288bf3a20c41a924587743eba81, type: 2}
- {fileID: 11400000, guid: 74afdc22b525eeb43935ac56a2da2b37, type: 2} - {fileID: 11400000, guid: 74afdc22b525eeb43935ac56a2da2b37, type: 2}
- {fileID: 11400000, guid: be76377cae8ede04ba4523be6e094f17, type: 2} - {fileID: 11400000, guid: be76377cae8ede04ba4523be6e094f17, type: 2}
scoreManager: {fileID: 2121761225}
--- !u!4 &455091938 --- !u!4 &455091938
Transform: Transform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -261,7 +262,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!114 &1131314919 --- !u!114 &1131314919
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -445,6 +446,50 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &2121761223
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2121761224}
- component: {fileID: 2121761225}
m_Layer: 0
m_Name: ScoreManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2121761224
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2121761223}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.773548, y: 1.0709885, z: -0.04651529}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2121761225
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2121761223}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c4a5bac4f66aaf84991ec68d8f2a4705, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1660057539 &9223372036854775807 --- !u!1660057539 &9223372036854775807
SceneRoots: SceneRoots:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -454,3 +499,4 @@ SceneRoots:
- {fileID: 455091938} - {fileID: 455091938}
- {fileID: 1131314920} - {fileID: 1131314920}
- {fileID: 1963856834} - {fileID: 1963856834}
- {fileID: 2121761224}

View file

@ -6,7 +6,8 @@ namespace DungeonSelection
[CreateAssetMenu(fileName = "New Dungeon", menuName = "Dungeon")] [CreateAssetMenu(fileName = "New Dungeon", menuName = "Dungeon")]
public class DungeonData : ScriptableObject public class DungeonData : ScriptableObject
{ {
public string DungeonName; public string Name;
public int Id;
public Sprite Thumbnail; public Sprite Thumbnail;
public string SceneName; public string SceneName;
public string WinMessage; public string WinMessage;

View file

@ -1,21 +1,51 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Scores;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization; using UnityEngine.Serialization;
namespace DungeonSelection 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 public class DungeonSelector : MonoBehaviour
{ {
[SerializeField] private DungeonData[] dungeons; [SerializeField] private DungeonData[] dungeons;
[SerializeField] private ScoreManager scoreManager;
private DungeonData _currentlySelectedDungeonData; private DungeonData _currentlySelectedDungeonData;
private int _currentlySelectedDungeonIndex = 0; private int _currentlySelectedDungeonIndex = 0;
private Dictionary<int, List<ScoreDisplay>> scoresByLevelId = new Dictionary<int, List<ScoreDisplay>>();
private bool _scoresReceived = false;
private void OnEnable() private void OnEnable()
{ {
UIEvents.NextDungeonClicked += SelectNextDungeon; UIEvents.NextDungeonClicked += SelectNextDungeon;
UIEvents.PreviousDungeonClicked += SelectPreviousDungeon; UIEvents.PreviousDungeonClicked += SelectPreviousDungeon;
UIEvents.EnterDungeonClicked += LoadDungeon; UIEvents.EnterDungeonClicked += LoadDungeon;
scoreManager.ScoresRecieved += HandleScoresRecieved;
} }
private void OnDisable() private void OnDisable()
@ -23,6 +53,7 @@ namespace DungeonSelection
UIEvents.NextDungeonClicked -= SelectNextDungeon; UIEvents.NextDungeonClicked -= SelectNextDungeon;
UIEvents.PreviousDungeonClicked -= SelectPreviousDungeon; UIEvents.PreviousDungeonClicked -= SelectPreviousDungeon;
UIEvents.EnterDungeonClicked -= LoadDungeon; UIEvents.EnterDungeonClicked -= LoadDungeon;
scoreManager.ScoresRecieved -= HandleScoresRecieved;
} }
private void Start() private void Start()
@ -30,7 +61,18 @@ namespace DungeonSelection
GameEvents.DungeonSelectionStarted?.Invoke(); GameEvents.DungeonSelectionStarted?.Invoke();
_currentlySelectedDungeonData = dungeons[_currentlySelectedDungeonIndex]; _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) if (_currentlySelectedDungeonIndex == 0)
{ {
GameEvents.ShowingFirstDugeon?.Invoke(); GameEvents.ShowingFirstDugeon?.Invoke();
@ -47,7 +89,8 @@ namespace DungeonSelection
if (_currentlySelectedDungeonIndex + 1 >= dungeons.Length) return; if (_currentlySelectedDungeonIndex + 1 >= dungeons.Length) return;
_currentlySelectedDungeonIndex++; _currentlySelectedDungeonIndex++;
_currentlySelectedDungeonData = dungeons[_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) if (_currentlySelectedDungeonIndex == dungeons.Length - 1)
{ {
GameEvents.ShowingLastDungeon?.Invoke(); GameEvents.ShowingLastDungeon?.Invoke();
@ -59,11 +102,37 @@ namespace DungeonSelection
if (_currentlySelectedDungeonIndex - 1 < 0) return; if (_currentlySelectedDungeonIndex - 1 < 0) return;
_currentlySelectedDungeonIndex--; _currentlySelectedDungeonIndex--;
_currentlySelectedDungeonData = dungeons[_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) if (_currentlySelectedDungeonIndex == 0)
{ {
GameEvents.ShowingFirstDugeon?.Invoke(); 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;
}
} }
} }

View file

@ -8,7 +8,7 @@ namespace DungeonSelection
public static Action DungeonSelectionStarted; public static Action DungeonSelectionStarted;
public static Action ShowingLastDungeon; public static Action ShowingLastDungeon;
public static Action ShowingFirstDugeon; public static Action ShowingFirstDugeon;
public static Action<DungeonData> ShowingDungeon; public static Action<DungeonDisplayData> ShowingDungeon;
public static Action<DungeonData> LoadDungeon; public static Action<DungeonData> LoadDungeon;
} }
} }

View file

@ -10,5 +10,6 @@ namespace DungeonSelection
public static Action<DungeonData> EnterDungeonClicked; public static Action<DungeonData> EnterDungeonClicked;
public static Action CloseRules; public static Action CloseRules;
public static Action ShowRules; public static Action ShowRules;
public static Action GetScores;
} }
} }

View file

@ -1,11 +1,15 @@
using System; using System;
using System.Collections;
using DungeonSelection; using DungeonSelection;
using Scores;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
public class LeaveDungeonHandler : MonoBehaviour public class LeaveDungeonHandler : MonoBehaviour
{ {
[SerializeField] private DungeonData dungeonData; [SerializeField] private DungeonData dungeonData;
[SerializeField] private ScoreManager scoreManager;
private void OnEnable() private void OnEnable()
{ {
EndGameController.LeaveDungeonClicked += LeaveDungeon; EndGameController.LeaveDungeonClicked += LeaveDungeon;
@ -20,7 +24,7 @@ public class LeaveDungeonHandler : MonoBehaviour
private void SaveScore(string name, int score) private void SaveScore(string name, int score)
{ {
Debug.Log($"{name} | {score}"); scoreManager.PostScore(name, dungeonData.Id, score);
} }
private void LeaveDungeon() private void LeaveDungeon()

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 294874e36d5de2f49b7a3532869a918e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c4a5bac4f66aaf84991ec68d8f2a4705

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using DungeonSelection; using DungeonSelection;
using Unity.VisualScripting; using Unity.VisualScripting;
using UnityEngine; using UnityEngine;
@ -7,21 +8,25 @@ using UnityEngine.UIElements;
public class DungeonSelectMenuController : MonoBehaviour public class DungeonSelectMenuController : MonoBehaviour
{ {
private const int NUM_HIGH_SCORES = 10;
private Button _next; private Button _next;
private Button _previous; private Button _previous;
private Button _start; private Button _start;
private Image _thumbnailImage; private Image _thumbnailImage;
private Label _dungeonName; private Label _dungeonName;
private VisualElement _dungeonThumbnail; private VisualElement _dungeonThumbnail;
private ListView _highScores;
private DungeonData _currentlyShowingDungeon; private DungeonDisplayData _currentlyShowingDungeon;
private List<string> _highScoreData = new List<string>();
private void OnEnable() private void OnEnable()
{ {
VisualElement root = GetComponent<UIDocument>().rootVisualElement; VisualElement root = GetComponent<UIDocument>().rootVisualElement;
Button rules = root.Q<Button>("Rules"); Button rules = root.Q<Button>("Rules");
rules.clicked += UIEvents.ShowRules; rules.clicked += RulesClicked;
_dungeonThumbnail = root.Q<VisualElement>("DungeonThumbnail"); _dungeonThumbnail = root.Q<VisualElement>("DungeonThumbnail");
_next = root.Q<Button>("Next"); _next = root.Q<Button>("Next");
_next.clicked += NextClicked; _next.clicked += NextClicked;
@ -30,16 +35,26 @@ public class DungeonSelectMenuController : MonoBehaviour
_start = root.Q<Button>("Start"); _start = root.Q<Button>("Start");
_start.clicked += StartClicked; _start.clicked += StartClicked;
_dungeonName = root.Q<Label>("DungeonName"); _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.ShowingDungeon += ShowDungeon;
GameEvents.ShowingFirstDugeon += () => SetPreviousButtonEnabled(false); GameEvents.ShowingFirstDugeon += () => SetPreviousButtonEnabled(false);
GameEvents.ShowingLastDungeon += () => SetNextButtonEnabled(false); GameEvents.ShowingLastDungeon += () => SetNextButtonEnabled(false);
} }
private void ShowDungeon(DungeonData dungeon) private void Start()
{
UIEvents.GetScores?.Invoke();
}
private void ShowDungeon(DungeonDisplayData dungeon)
{ {
_currentlyShowingDungeon = dungeon; _currentlyShowingDungeon = dungeon;
_dungeonName.text = _currentlyShowingDungeon.DungeonName; _dungeonName.text = _currentlyShowingDungeon.DungeonData.Name;
if (_thumbnailImage == null) if (_thumbnailImage == null)
{ {
@ -48,7 +63,18 @@ public class DungeonSelectMenuController : MonoBehaviour
_dungeonThumbnail.Add(_thumbnailImage); _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) private void SetPreviousButtonEnabled(bool enabled)
@ -77,6 +103,11 @@ public class DungeonSelectMenuController : MonoBehaviour
private void StartClicked() private void StartClicked()
{ {
UIEvents.EnterDungeonClicked?.Invoke(_currentlyShowingDungeon); UIEvents.EnterDungeonClicked?.Invoke(_currentlyShowingDungeon.DungeonData);
}
private void RulesClicked()
{
UIEvents.ShowRules?.Invoke();
} }
} }

View file

@ -6,7 +6,7 @@
<ui:Label text="Dungeon Name" name="DungeonName" class="MenuHeader MenuHTwo" style="-unity-text-align: upper-center; color: rgb(255, 255, 255);" /> <ui:Label text="Dungeon Name" name="DungeonName" class="MenuHeader MenuHTwo" style="-unity-text-align: upper-center; color: rgb(255, 255, 255);" />
<ui:VisualElement style="flex-grow: 1;"> <ui:VisualElement style="flex-grow: 1;">
<ui:Label text="High Scores" name="HighScores" class="MenuHThree" style="-unity-text-align: upper-center; color: rgb(255, 255, 255);" /> <ui:Label text="High Scores" name="HighScores" class="MenuHThree" style="-unity-text-align: upper-center; color: rgb(255, 255, 255);" />
<ui:ListView name="HighScoresListView" class="MenuText" style="flex-grow: 1;" /> <ui:ListView name="HighScoresListView" allow-add="false" allow-remove="false" show-bound-collection-size="false" virtualization-method="DynamicHeight" class="MenuText" style="flex-grow: 1; color: rgb(255, 255, 255); padding-left: 30px; padding-right: 30px;" />
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="DungeonView" style="right: 0; top: 0; align-self: stretch; justify-content: space-between; flex-direction: column-reverse; flex-grow: 1; position: relative; flex-shrink: 1; bottom: 0; align-items: stretch;"> <ui:VisualElement name="DungeonView" style="right: 0; top: 0; align-self: stretch; justify-content: space-between; flex-direction: column-reverse; flex-grow: 1; position: relative; flex-shrink: 1; bottom: 0; align-items: stretch;">