feat(engine): Enter dismisses Win Summary and starts a fresh deal
The post-win modal's "Play Again" was click-only — keyboard-only players had to reach for the mouse to leave the celebration screen, and the button advertised no accelerator the way every other modal button does. - handle_win_summary_keyboard reads Enter while WinSummaryOverlay is in the world; despawns the overlay and writes the same NewGameRequestEvent the click handler takes. - The button label gains a trailing return-key glyph so the keyboard path is discoverable on first sight. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -235,6 +235,7 @@ impl Plugin for WinSummaryPlugin {
|
|||||||
collect_session_achievements,
|
collect_session_achievements,
|
||||||
spawn_win_summary_after_delay,
|
spawn_win_summary_after_delay,
|
||||||
handle_win_summary_buttons,
|
handle_win_summary_buttons,
|
||||||
|
handle_win_summary_keyboard,
|
||||||
apply_screen_shake,
|
apply_screen_shake,
|
||||||
reveal_score_breakdown,
|
reveal_score_breakdown,
|
||||||
)
|
)
|
||||||
@@ -624,6 +625,31 @@ fn handle_win_summary_buttons(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Keyboard accelerator for the win summary's "Play Again" button.
|
||||||
|
/// Enter / Return collapses the win modal and starts a fresh deal —
|
||||||
|
/// the same path the click handler takes — so a keyboard-only player
|
||||||
|
/// can dismiss the post-win celebration without reaching for the mouse.
|
||||||
|
fn handle_win_summary_keyboard(
|
||||||
|
keys: Option<Res<ButtonInput<KeyCode>>>,
|
||||||
|
overlays: Query<Entity, With<WinSummaryOverlay>>,
|
||||||
|
mut commands: Commands,
|
||||||
|
mut new_game: MessageWriter<NewGameRequestEvent>,
|
||||||
|
) {
|
||||||
|
if overlays.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(keys) = keys else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !keys.just_pressed(KeyCode::Enter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for entity in &overlays {
|
||||||
|
commands.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
new_game.write(NewGameRequestEvent::default());
|
||||||
|
}
|
||||||
|
|
||||||
/// Applies a decaying sinusoidal offset to the main `Camera2d` each frame
|
/// Applies a decaying sinusoidal offset to the main `Camera2d` each frame
|
||||||
/// while `ScreenShakeResource::remaining > 0`.
|
/// while `ScreenShakeResource::remaining > 0`.
|
||||||
///
|
///
|
||||||
@@ -798,8 +824,11 @@ fn spawn_overlay(
|
|||||||
BackgroundColor(ACCENT_PRIMARY),
|
BackgroundColor(ACCENT_PRIMARY),
|
||||||
))
|
))
|
||||||
.with_children(|b| {
|
.with_children(|b| {
|
||||||
|
// Append the Enter / Return glyph so keyboard players see
|
||||||
|
// the accelerator on the button itself — mirrors the
|
||||||
|
// chip-style hints on every modal button helper.
|
||||||
b.spawn((
|
b.spawn((
|
||||||
Text::new("Play Again"),
|
Text::new("Play Again \u{21B5}"),
|
||||||
TextFont { font_size: TYPE_BODY_LG, ..default() },
|
TextFont { font_size: TYPE_BODY_LG, ..default() },
|
||||||
TextColor(BG_BASE),
|
TextColor(BG_BASE),
|
||||||
));
|
));
|
||||||
|
|||||||
Reference in New Issue
Block a user