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.
@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 ); }