MoodCanvas/lib/screens/puzzle/puzzle_complete_screen.dart
fengshengxiong 91b7eebbf2 接入TopON
2026-01-22 16:34:55 +08:00

406 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:aesthetica_wallpaper/models/puzzle_game_interface.dart';
import 'package:confetti/confetti.dart';
/// 拼图完成页面
class PuzzleCompleteScreen extends StatefulWidget {
final IPuzzleGame game;
const PuzzleCompleteScreen({super.key, required this.game});
@override
State<PuzzleCompleteScreen> createState() => _PuzzleCompleteScreenState();
}
class _PuzzleCompleteScreenState extends State<PuzzleCompleteScreen>
with SingleTickerProviderStateMixin {
late ConfettiController _confettiController;
late AnimationController _animationController;
late Animation<double> _scaleAnimation;
late Animation<double> _fadeAnimation;
@override
void initState() {
super.initState();
_confettiController = ConfettiController(
duration: const Duration(seconds: 3),
);
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 800),
);
_scaleAnimation = CurvedAnimation(
parent: _animationController,
curve: Curves.elasticOut,
);
_fadeAnimation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeIn,
);
// 启动动画和彩带
_animationController.forward();
_confettiController.play();
}
@override
void dispose() {
_confettiController.dispose();
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final stars = widget.game.getStarRating();
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.purple.shade400, Colors.blue.shade400],
),
),
child: SafeArea(
child: Stack(
children: [
// 彩带效果
Align(
alignment: Alignment.topCenter,
child: ConfettiWidget(
confettiController: _confettiController,
blastDirectionality: BlastDirectionality.explosive,
particleDrag: 0.05,
emissionFrequency: 0.05,
numberOfParticles: 50,
gravity: 0.1,
shouldLoop: false,
colors: const [
Colors.green,
Colors.blue,
Colors.pink,
Colors.orange,
Colors.purple,
],
),
),
// 主要内容
Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 完成图标
ScaleTransition(
scale: _scaleAnimation,
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.2),
blurRadius: 20,
offset: const Offset(0, 10),
),
],
),
child: const Icon(
Icons.check_circle,
size: 80,
color: Colors.green,
),
),
),
const SizedBox(height: 32),
// 标题
FadeTransition(
opacity: _fadeAnimation,
child: const Text(
'🎉 Congratulations!',
style: TextStyle(
fontSize: 36,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
const SizedBox(height: 24),
// 星级评分
_buildStarRating(stars),
const SizedBox(height: 32),
// 成绩卡片
_buildScoreCard(),
const SizedBox(height: 32),
// 奖励信息
_buildRewards(),
const SizedBox(height: 32),
// 操作按钮
_buildActionButtons(),
],
),
),
),
],
),
),
),
);
}
Widget _buildStarRating(int stars) {
return FadeTransition(
opacity: _fadeAnimation,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(3, (index) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Icon(
index < stars ? Icons.star : Icons.star_border,
size: 48,
color: Colors.amber,
),
);
}),
),
);
}
Widget _buildScoreCard() {
return FadeTransition(
opacity: _fadeAnimation,
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 20,
offset: const Offset(0, 10),
),
],
),
child: Column(
children: [
const Text(
'Game Stats',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildScoreItem(
Icons.timer,
'Time',
_formatDuration(widget.game.elapsedTime),
Colors.blue,
),
_buildScoreItem(
Icons.directions_walk,
'Moves',
'${widget.game.moves}',
Colors.orange,
),
],
),
const SizedBox(height: 16),
const Divider(),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildScoreItem(
Icons.grid_4x4,
'Difficulty',
widget.game.difficultyLabel,
Colors.purple,
),
_buildScoreItem(
Icons.emoji_events,
'Best Record',
'--:--',
Colors.green,
),
],
),
],
),
),
);
}
Widget _buildScoreItem(
IconData icon,
String label,
String value,
Color color,
) {
return Column(
children: [
Icon(icon, color: color, size: 32),
const SizedBox(height: 8),
Text(
value,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: color,
),
),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(fontSize: 12, color: Colors.grey.shade600),
),
],
);
}
Widget _buildRewards() {
return FadeTransition(
opacity: _fadeAnimation,
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: Colors.white.withValues(alpha: 0.3),
width: 2,
),
),
child: Column(
children: [
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.card_giftcard, color: Colors.white),
SizedBox(width: 8),
Text(
'Rewards',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
const SizedBox(height: 16),
_buildRewardItem(Icons.stars, '+ 50 Points'),
const SizedBox(height: 8),
_buildRewardItem(
Icons.wallpaper,
'Unlocked "${widget.game.difficultyLabel} Challenge" Wallpaper',
),
if (widget.game.getStarRating() == 3) ...[
const SizedBox(height: 8),
_buildRewardItem(Icons.emoji_events, '3-Star Achievement!'),
],
],
),
),
);
}
Widget _buildRewardItem(IconData icon, String text) {
return Row(
children: [
Icon(icon, color: Colors.amber, size: 20),
const SizedBox(width: 8),
Expanded(
child: Text(
text,
style: const TextStyle(color: Colors.white, fontSize: 14),
),
),
],
);
}
Widget _buildActionButtons() {
return FadeTransition(
opacity: _fadeAnimation,
child: Column(
children: [
// 再玩一次
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.pop(context); // 返回游戏页面
Navigator.pop(context); // 返回菜单页面
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.purple,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.refresh),
SizedBox(width: 8),
Text(
'Play Again',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
],
),
),
),
const SizedBox(height: 12),
// 返回首页
TextButton(
onPressed: () {
Navigator.popUntil(context, (route) => route.isFirst);
},
child: const Text(
'Back to Home',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
],
),
);
}
String _formatDuration(Duration duration) {
final minutes = duration.inMinutes.toString().padLeft(2, '0');
final seconds = (duration.inSeconds % 60).toString().padLeft(2, '0');
return '$minutes:$seconds';
}
}