153 lines
4 KiB
C#
153 lines
4 KiB
C#
|
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>
|
||
|
private int _round = -1;
|
||
|
|
||
|
public int RoundsPerGame = 5;
|
||
|
public double SecondsPerRound = 15d;
|
||
|
|
||
|
/// <summary>
|
||
|
/// constructor for the gameplay class
|
||
|
/// </summary>
|
||
|
/// <param name="ui">the visual element object for the ui document with the GameView</param>
|
||
|
private Gameplay(VisualElement ui)
|
||
|
{
|
||
|
_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>
|
||
|
private void StartGame()
|
||
|
{
|
||
|
_round = 0;
|
||
|
AdvanceToNextRound();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// called once per frame
|
||
|
/// </summary>
|
||
|
private void Update()
|
||
|
{
|
||
|
if (_round < 1) return;
|
||
|
if (_countdownDatetime < DateTime.Now) AdvanceToNextRound();
|
||
|
Render();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// function for advancing to the next round
|
||
|
/// </summary>
|
||
|
private void AdvanceToNextRound()
|
||
|
{
|
||
|
if (_round > 0) StoreRoundInfo();
|
||
|
GenerateNewTemplateColour();
|
||
|
|
||
|
if (_round < RoundsPerGame)
|
||
|
{
|
||
|
_round++;
|
||
|
_countdownDatetime = DateTime.Now.AddSeconds(SecondsPerRound);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// end game
|
||
|
_round = -1;
|
||
|
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
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/// <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);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// function for rendering the game state
|
||
|
/// </summary>
|
||
|
private void Render()
|
||
|
{
|
||
|
var remaining = (_countdownDatetime - DateTime.Now).TotalSeconds;
|
||
|
_roundText.text = $"{_round}/{RoundsPerGame}";
|
||
|
_countdownText.text = $"{remaining:F}";
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// struct for storing round information
|
||
|
/// </summary>
|
||
|
public struct RoundInfo
|
||
|
{
|
||
|
public Color TemplateColour;
|
||
|
public Color ResponseColour;
|
||
|
}
|
||
|
}
|