2024-11-18 09:16:03 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
using Random = System.Random;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// gameplay behaviour class
|
|
|
|
/// </summary>
|
|
|
|
public class Gameplay
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// countdown text label for showing the countdown
|
|
|
|
/// </summary>
|
|
|
|
private readonly Label _countdownText;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// list of played rounds
|
|
|
|
/// </summary>
|
|
|
|
private readonly List<RoundInfo> _playedRounds = new(5);
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// response colour for the player to match
|
|
|
|
/// </summary>
|
|
|
|
private readonly VisualElement _responseColour;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// round text label for showing the current round
|
|
|
|
/// </summary>
|
|
|
|
private readonly Label _roundText;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// template colour for the player to match
|
|
|
|
/// </summary>
|
|
|
|
private readonly VisualElement _templateColour;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// game countdown timer
|
|
|
|
/// </summary>
|
|
|
|
private DateTime _countdownDatetime;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// game round counter
|
|
|
|
/// </summary>
|
2024-11-18 10:34:29 +08:00
|
|
|
public int Round = -1;
|
2024-11-18 09:16:03 +08:00
|
|
|
|
2024-11-18 10:34:29 +08:00
|
|
|
/// <summary>
|
|
|
|
/// singleton instance of the gameplay class
|
|
|
|
/// </summary>
|
|
|
|
private const int RoundsPerGame = 5;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// seconds per round
|
|
|
|
/// </summary>
|
|
|
|
private const double SecondsPerRound = 15d;
|
2024-11-18 09:16:03 +08:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// constructor for the gameplay class
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="ui">the visual element object for the ui document with the GameView</param>
|
2024-11-18 10:34:29 +08:00
|
|
|
public Gameplay(VisualElement ui)
|
2024-11-18 09:16:03 +08:00
|
|
|
{
|
|
|
|
_roundText = ui.Q<Label>("RoundText");
|
|
|
|
_countdownText = ui.Q<Label>("TimeText");
|
|
|
|
_templateColour = ui.Q<VisualElement>("TemplateColour");
|
|
|
|
_responseColour = ui.Q<VisualElement>("ResponseColour");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// function for starting the game
|
|
|
|
/// </summary>
|
2024-11-18 10:34:29 +08:00
|
|
|
public void StartGame()
|
2024-11-18 09:16:03 +08:00
|
|
|
{
|
2024-11-18 10:34:29 +08:00
|
|
|
Round = 0;
|
2024-11-18 09:16:03 +08:00
|
|
|
AdvanceToNextRound();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
2024-11-18 10:34:29 +08:00
|
|
|
/// (to be) called once per frame
|
2024-11-18 09:16:03 +08:00
|
|
|
/// </summary>
|
2024-11-18 10:34:29 +08:00
|
|
|
public void Update()
|
2024-11-18 09:16:03 +08:00
|
|
|
{
|
2024-11-18 10:34:29 +08:00
|
|
|
if (Round < 1) return;
|
2024-11-18 09:16:03 +08:00
|
|
|
if (_countdownDatetime < DateTime.Now) AdvanceToNextRound();
|
|
|
|
Render();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// function for advancing to the next round
|
|
|
|
/// </summary>
|
|
|
|
private void AdvanceToNextRound()
|
|
|
|
{
|
2024-11-18 10:34:29 +08:00
|
|
|
if (Round > 0) StoreRoundInfo();
|
2024-11-18 09:16:03 +08:00
|
|
|
GenerateNewTemplateColour();
|
|
|
|
|
2024-11-18 10:34:29 +08:00
|
|
|
if (Round < RoundsPerGame)
|
2024-11-18 09:16:03 +08:00
|
|
|
{
|
2024-11-18 10:34:29 +08:00
|
|
|
Debug.Log("round advance");
|
|
|
|
Round++;
|
2024-11-18 09:16:03 +08:00
|
|
|
_countdownDatetime = DateTime.Now.AddSeconds(SecondsPerRound);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// end game
|
2024-11-18 10:34:29 +08:00
|
|
|
Round = -1;
|
2024-11-18 09:16:03 +08:00
|
|
|
GameManager.Instance.SignalGameEnd(_playedRounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// function for storing the round information
|
|
|
|
/// </summary>
|
|
|
|
private void StoreRoundInfo()
|
|
|
|
{
|
|
|
|
_playedRounds.Add(new RoundInfo
|
|
|
|
{
|
|
|
|
TemplateColour = _templateColour.style.backgroundColor.value,
|
|
|
|
ResponseColour = _responseColour.style.backgroundColor.value
|
|
|
|
});
|
2024-11-18 10:34:29 +08:00
|
|
|
Debug.Log("stored round info");
|
2024-11-18 09:16:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// function for generating a new template colour
|
|
|
|
/// (a random colour that isn't hard to visually match)
|
|
|
|
/// </summary>
|
|
|
|
private void GenerateNewTemplateColour()
|
|
|
|
{
|
|
|
|
var r = new Random();
|
|
|
|
|
|
|
|
// - lightness: 0.4-0.8
|
|
|
|
// - chroma: 0.0-0.2
|
|
|
|
// - hue: all (0-360)
|
|
|
|
|
|
|
|
var colour = Colorimetry.RawLchToColor(
|
|
|
|
Math.Clamp(r.NextDouble() * 0.4d + 0.4d, 0.4d, 0.8d),
|
|
|
|
Math.Clamp(r.NextDouble() * 0.2d, 0d, 0.2d),
|
|
|
|
Math.Clamp(r.NextDouble() * 360d, 0d, 360d)
|
|
|
|
);
|
|
|
|
|
|
|
|
_templateColour.style.backgroundColor = new StyleColor(colour);
|
2024-11-18 10:34:29 +08:00
|
|
|
Debug.Log($"generated new template colour {colour}");
|
2024-11-18 09:16:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// function for rendering the game state
|
|
|
|
/// </summary>
|
|
|
|
private void Render()
|
|
|
|
{
|
|
|
|
var remaining = (_countdownDatetime - DateTime.Now).TotalSeconds;
|
2024-11-18 10:34:29 +08:00
|
|
|
_roundText.text = $"{Round}/{RoundsPerGame}";
|
2024-11-18 09:16:03 +08:00
|
|
|
_countdownText.text = $"{remaining:F}";
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// struct for storing round information
|
|
|
|
/// </summary>
|
|
|
|
public struct RoundInfo
|
|
|
|
{
|
|
|
|
public Color TemplateColour;
|
|
|
|
public Color ResponseColour;
|
|
|
|
}
|
|
|
|
}
|