feat: staggered star reveal and near-miss progress ring

Stars on win now appear sequentially with elastic-bounce via
TweenAnimationBuilder (400/650/900 ms). Lost overlay shows a
CircularProgressIndicator ring with "87% complete!" (l10n:
almostThere) when objectiveProgress > 0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 22:20:29 +09:00
parent f1b8052f77
commit 677a09f8cb
3 changed files with 46 additions and 7 deletions
+8
View File
@@ -20,5 +20,13 @@
"type": "int"
}
}
},
"almostThere": "{percent}% complete!",
"@almostThere": {
"placeholders": {
"percent": {
"type": "int"
}
}
}
}
+2 -1
View File
@@ -13,5 +13,6 @@
"giveUp": "포기하기",
"playAgain": "다시 하기",
"nextStage": "다음 스테이지",
"streakMilestone": "{days}일 연속 플레이! 대단해요!"
"streakMilestone": "{days}일 연속 플레이! 대단해요!",
"almostThere": "{percent}% 달성!"
}
+35 -5
View File
@@ -344,16 +344,46 @@ class _GameScreenState extends ConsumerState<GameScreen>
mainAxisSize: MainAxisSize.min,
children: [
for (var i = 0; i < 3; i++)
Icon(
TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: 1),
duration: Duration(milliseconds: 400 + i * 250),
curve: Interval(i * 0.22, 1, curve: Curves.elasticOut),
builder: (context, v, child) =>
Transform.scale(scale: v, child: child),
child: Icon(
Icons.star,
size: 40,
color: i < view.starsEarned
? Colors.amber
: Colors.white24,
size: 44,
color: i < view.starsEarned ? Colors.amber : Colors.white24,
),
),
],
),
],
if (view.phase == GamePhase.lost && view.objectiveProgress > 0) ...[
const SizedBox(height: 16),
SizedBox(
width: 88,
height: 88,
child: Stack(
fit: StackFit.expand,
children: [
CircularProgressIndicator(
value: view.objectiveProgress,
strokeWidth: 7,
backgroundColor: Colors.white12,
color: Colors.amber,
),
Center(
child: Text(
l10n.almostThere((view.objectiveProgress * 100).round()),
textAlign: TextAlign.center,
style: theme.textTheme.labelSmall,
),
),
],
),
),
],
const SizedBox(height: 20),
...actions,
],