UI/GameOverPanel.razor

Razor UI panel for the game over screen. It displays a heading, cause of death, score, length, best score, and buttons to restart or return to menu, with hover/click sounds and simple reactive properties computed from a GameSession.

Native Interop
@using Sandbox;
@using Sandbox.UI;
@namespace Coilgarden
@inherits Panel
@attribute [StyleSheet( "/UI/GameUi.razor.scss" )]

<root class="scrim">
	<div class="@CardClass">
		<div class="heading">@EndTitle</div>
		<div class="cause">@EndCause</div>

		<div class="tally">
			<div class="tally-item">
				<span class="tally-label">SCORE</span>
				<span class="tally-value">@ScoreText</span>
			</div>
			<div class="tally-item">
				<span class="tally-label">LENGTH</span>
				<span class="tally-value">@LengthText</span>
			</div>
			<div class="tally-item">
				<span class="tally-label">BEST</span>
				<span class="tally-value">@BestText</span>
			</div>
		</div>

		<div class="menu">
			<div [email protected] class="btn primary" onclick=@Restart>Play Again</div>
			<div [email protected] class="btn" onclick=@Menu>Main Menu</div>
		</div>
	</div>
</root>

@code
{
	[Parameter] public GameSession Session { get; set; }

	private SnakeGame Run => Session?.Run;

	/// <summary>A record-beating run gets an apple-red edge, restating the good news in a
	/// second channel so it lands even if the words are skimmed.</summary>
	private string CardClass => Session?.IsNewBest == true ? "card record" : "card";

	private bool Won => Run?.EndedBy == StepOutcome.FilledArena;

	private string EndTitle => Session?.IsNewBest == true ? "New best" : Won ? "Garden full" : "Game over";

	private string EndCause => Run?.EndedBy switch
	{
		StepOutcome.HitWall => "You met the edge of the tray.",
		StepOutcome.HitSelf => "You crossed your own tail.",
		StepOutcome.FilledArena => "Not a single cell left. Remarkable.",
		_ => ""
	};

	private string ScoreText => (Run?.Score ?? 0).ToString();

	private string LengthText => (Run?.Snake.Length ?? 0).ToString();

	private string BestText => (Session?.Records?.BestScore ?? 0).ToString();

	private void Restart()
	{
		UiSound.Click();
		Session?.Restart();
	}

	private void Menu()
	{
		UiSound.Click();
		Session?.ReturnToMenu();
	}

	protected override int BuildHash() => System.HashCode.Combine(
		Run?.EndedBy, Session?.IsNewBest, Run?.Score, Run?.Snake?.Length, Session?.Records?.BestScore );
}