This repository has been archived on 2024-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
colourmeok/ColourMeOKGame/Assets/Scripts/Gameplay.cs

163 lines
No EOL
4.5 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>
/// singleton instance of the gameplay class
/// </summary>
public const int RoundsPerGame = 5;
/// <summary>
/// seconds per round
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public const double SecondsPerRound = 12d;
/// <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>
public int Round = -1;
/// <summary>
/// constructor for the gameplay class
/// </summary>
/// <param name="ui">the visual element object for the ui document with the GameView</param>
public 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>
public void StartGame()
{
Round = 0;
_playedRounds.Clear();
AdvanceToNextRound();
}
/// <summary>
/// (to be) called once per frame
/// </summary>
public 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)
{
Debug.Log("round advance");
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
});
Debug.Log(
$"stored round info (Template is {_templateColour.style.backgroundColor.value}, Response is {_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()
{
// - lightness: 30-90
// - chroma: 0.03-0.20
// - hue: all (0-360)
var r = new Random();
var l = Math.Clamp(r.NextDouble() * 60d + 30d, 30d, 90d);
var c = Math.Clamp(r.NextDouble() * 0.17d + 0.03d, 0.03d, 0.20d);
var h = Math.Clamp(r.NextDouble() * 360d, 0d, 360d);
var colour = Colorimetry.RawLchToColor(l, c, h);
Debug.Log($"generated new template colour LCh({l:F}, {c:F}, {h:F}) -> {colour}");
_templateColour.style.backgroundColor = 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:F2}";
}
/// <summary>
/// struct for storing round information
/// </summary>
public struct RoundInfo
{
public Color TemplateColour;
public Color ResponseColour;
}
}