feat: endless mode UI - game over card, best score, HUD
This commit is contained in:
@@ -41,6 +41,7 @@ class _GameScreenState extends ConsumerState<GameScreen>
|
||||
);
|
||||
|
||||
bool _tutorialStartChecked = false;
|
||||
bool _endlessNewBest = false;
|
||||
|
||||
int? _dragIndex;
|
||||
Offset? _dragGlobal;
|
||||
@@ -155,9 +156,11 @@ class _GameScreenState extends ConsumerState<GameScreen>
|
||||
if (next.phase == GamePhase.won) {
|
||||
audio.play(Sfx.win);
|
||||
// recordResult keeps the best run, so re-entry is harmless.
|
||||
ref
|
||||
.read(seasonFlowProvider.notifier)
|
||||
.recordWin(stars: next.starsEarned, score: next.score);
|
||||
if (!next.endless) {
|
||||
ref
|
||||
.read(seasonFlowProvider.notifier)
|
||||
.recordWin(stars: next.starsEarned, score: next.score);
|
||||
}
|
||||
final stackBox =
|
||||
_stackKey.currentContext?.findRenderObject() as RenderBox?;
|
||||
if (stackBox != null) {
|
||||
@@ -165,6 +168,11 @@ class _GameScreenState extends ConsumerState<GameScreen>
|
||||
}
|
||||
}
|
||||
if (next.phase == GamePhase.lost) audio.play(Sfx.lose);
|
||||
if (next.phase == GamePhase.lost && next.endless) {
|
||||
ref.read(endlessBestProvider.notifier).record(next.score).then((isNew) {
|
||||
if (mounted) setState(() => _endlessNewBest = isNew);
|
||||
});
|
||||
}
|
||||
if (next.phase == GamePhase.won || next.phase == GamePhase.lost) {
|
||||
ref.read(streakProvider.notifier).onStagePlayed(DateTime.now());
|
||||
}
|
||||
@@ -381,6 +389,18 @@ class _GameScreenState extends ConsumerState<GameScreen>
|
||||
),
|
||||
],
|
||||
),
|
||||
(GamePhase.lost, _) when view.endless => (
|
||||
l10n.gameOver,
|
||||
[
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
setState(() => _endlessNewBest = false);
|
||||
notifier.restart();
|
||||
},
|
||||
child: Text(l10n.playAgain),
|
||||
),
|
||||
],
|
||||
),
|
||||
(_, _) => (
|
||||
l10n.stageFailed,
|
||||
[
|
||||
@@ -426,7 +446,24 @@ class _GameScreenState extends ConsumerState<GameScreen>
|
||||
],
|
||||
),
|
||||
],
|
||||
if (view.phase == GamePhase.lost && view.objectiveProgress > 0) ...[
|
||||
if (view.phase == GamePhase.lost && view.endless) ...[
|
||||
const SizedBox(height: 10),
|
||||
Text('${view.score}',
|
||||
style: theme.textTheme.displaySmall
|
||||
?.copyWith(fontWeight: FontWeight.w900)),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
_endlessNewBest
|
||||
? l10n.newBest
|
||||
: l10n.bestScore(ref.read(endlessBestProvider)),
|
||||
style: TextStyle(
|
||||
color:
|
||||
_endlessNewBest ? Colors.amber : Colors.white60,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
],
|
||||
if (view.phase == GamePhase.lost && !view.endless && view.objectiveProgress > 0) ...[
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(
|
||||
width: 88,
|
||||
|
||||
@@ -16,7 +16,7 @@ class HudWidget extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
_movesChip(theme),
|
||||
view.endless ? const SizedBox(width: 48) : _movesChip(theme),
|
||||
AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
transitionBuilder: (child, anim) =>
|
||||
|
||||
Reference in New Issue
Block a user