UI/MainMenuPanel.razor

Razor UI panel for the main menu. It displays title, play/settings buttons, an optional best-run summary (score, length, runs), and invokes session start or a settings callback; it also plays UI sounds on hover/click.

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

@*
	The title screen. A keyboard player can skip it entirely by just pressing a direction -
	GameSession takes that as both "start" and the first turn - so the buttons here exist for
	the mouse player and for reaching Settings, not because the game waits on them.
*@

<root class="scrim">
	<div class="card">
		<div class="wordmark">Coilgarden</div>
		<div class="tagline">A small garden. One apple at a time.</div>

		<div class="menu">
			<div [email protected] class="btn primary" onclick=@Play>Play</div>
			<div [email protected] class="btn" onclick=@OpenSettingsClicked>Settings</div>
		</div>

		<div class="prompt">or press a direction to begin</div>

		@if ( HasRecord )
		{
			<div class="records">
				<div class="records-title">Best run</div>
				<div class="record-row"><span>Score</span><span>@BestScoreText</span></div>
				<div class="record-row"><span>Length</span><span>@BestLengthText</span></div>
				<div class="record-row"><span>Runs played</span><span>@RunsText</span></div>
			</div>
		}
	</div>
</root>

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

	[Parameter] public Action SettingsRequested { get; set; }

	private HighScoreData Records => Session?.Records;

	private bool HasRecord => Records is { RunsPlayed: > 0 };

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

	private string BestLengthText => (Records?.BestLength ?? 0).ToString();

	private string RunsText => (Records?.RunsPlayed ?? 0).ToString();

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

	private void OpenSettingsClicked()
	{
		UiSound.Click();
		SettingsRequested?.Invoke();
	}

	protected override int BuildHash() => System.HashCode.Combine(
		Records?.BestScore, Records?.BestLength, Records?.RunsPlayed );
}