Explorar el Código

feat(controller): complete game controller

zhaoyadi hace 9 meses
padre
commit
537f5a9813

+ 13 - 3
android/app/build.gradle

@@ -44,11 +44,21 @@ android {
         versionName = flutterVersionName
     }
 
+    signingConfigs {
+        release {
+            storeFile file("../key/zaojiao.jks")
+            storePassword "asdfg12345"
+            keyAlias "key0"
+            keyPassword "asdfg12345"
+
+            v1SigningEnabled true
+            v2SigningEnabled true
+        }
+    }
+
     buildTypes {
         release {
-            // TODO: Add your own signing config for the release build.
-            // Signing with the debug keys for now, so `flutter run --release` works.
-            signingConfig = signingConfigs.debug
+            signingConfig signingConfigs.release
         }
     }
 }

+ 4 - 0
android/key/key.txt

@@ -0,0 +1,4 @@
+jarsigner -verbose -keystore zaojiao.jks -signedjar signed.apk app-release-unsigned.apk key0
+
+
+asdfg12345

+ 2 - 1
lib/app/battle_app.dart

@@ -2,6 +2,7 @@ import 'package:battle/route.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
+import 'package:widget/widget.dart';
 
 class BattleApp extends StatefulWidget {
   const BattleApp({super.key});
@@ -22,7 +23,7 @@ class _BattleAppState extends State<BattleApp> {
         theme: ThemeData(
           useMaterial3: true,
           colorScheme: ColorScheme.fromSeed(
-            seedColor: Colors.blueAccent,
+            seedColor: kBoardForegroundColor,
           ),
         ),
       ),

+ 6 - 6
lib/button/button_color.dart

@@ -1,10 +1,10 @@
 import 'dart:ui';
 
 List<Color> buttonColors = <Color>[
-  const Color(0xFFFF0000),
-  const Color(0xFFFF7700),
-  const Color(0xFFFFFF00),
-  const Color(0xFF00FF00),
-  const Color(0xFF0000FF),
-  const Color(0xFFFF00FF),
+  const Color(0xFFE3442F),
+  const Color(0xFFF28F31),
+  const Color(0xFFFAE029),
+  const Color(0xFF109150),
+  const Color(0xFF2160AD),
+  const Color(0xFFAA70AD),
 ];

+ 125 - 42
lib/button/button_controller.dart

@@ -1,8 +1,9 @@
 import 'package:battle/button/button_color.dart';
 import 'package:battle/data/card.dart';
 import 'package:flutter/cupertino.dart';
-import 'package:widget/widget.dart';
+import 'package:flutter/material.dart';
 
+import '../page/game/status_notifier_mixin.dart';
 import '../utils/utils.dart';
 
 enum ButtonState { start, stop }
@@ -13,65 +14,100 @@ class ButtonInfo {
   int endIndex;
   double process;
 
-  /// 是否执行超出回退动画
-  bool overflow;
-
-  /// 是否执行卡住动画
-  bool pauseBottom;
-
-  bool pauseInline;
-
-  bool pauseRight;
-
-  List<PathOp> ops;
+  int pauseSecond;
 
   ButtonInfo({
     required this.color,
     required this.startIndex,
     required this.endIndex,
     this.process = 0,
-    this.overflow = false,
-    this.pauseBottom = false,
-    this.pauseInline = false,
-    this.pauseRight = false,
-    this.ops = const [],
+    this.pauseSecond = 0,
   });
 }
 
+enum GameStatus { wait, running, end }
+
 /// 四步完成随机性
 /// 1. 根据答案编排出按钮颜色的最终位置
 /// 2. 随机生成初始位置数组并赋值给按钮
 /// 3. 打乱按钮顺序即调整按钮的起始位置
 /// 4. 随机生成按钮出发顺序并赋值给动画
-class ButtonController with ChangeNotifier {
+class GameController with ChangeNotifier, StatusNotifierMixin<GameStatus> {
   final CardItem cardItem;
-  final TickerProvider vsync;
 
-  ButtonController(this.cardItem, {required this.vsync}) {
-    _animationController = AnimationController(
-      upperBound: 6.0,
-      vsync: vsync,
-      duration: const Duration(seconds: 30),
-    );
+  final TickerProvider vsync;
 
-    _randomButton();
+  GameController(this.cardItem, {required this.vsync}) {
+    _generator = ButtonGenerator(cardItem);
+    _animationController = AnimationController(upperBound: 6.0, vsync: vsync);
 
     _animationController.addListener(() {
-      int index = _animationController.value ~/ 1;
-      if (index == 6) return;
-      double process = _animationController.value % 1.0;
+      if (_animationController.value >= 6.0) {
+        _status = GameStatus.end;
+      } else {
+        _generator.move(_animationController.value);
+      }
 
-      buttonList[_moveIndex[index]].process = Curves.easeInOutQuint.transform(process);
-      notifyListeners();
+      notifyListeners(status: _status);
     });
   }
 
+  late ButtonGenerator _generator;
+
   late AnimationController _animationController;
+
+  GameStatus _status = GameStatus.wait;
+
+  GameStatus get status => _status;
+
+  List<ButtonInfo> get buttonList => _generator.buttonList;
+
+  int get count => (_animationController.value * _generator.totalDuration.inSeconds / 6).toInt();
+
+  bool get isRunning => _animationController.isAnimating;
+
+  int get score => _generator.score;
+
+  void stop(){
+    if (_animationController.isAnimating) {
+      _animationController.stop(canceled: false);
+    }
+  }
+
+  void startOrReset() {
+    if (_animationController.isAnimating) {
+      _animationController.reset();
+    }
+    _generator.randomButton();
+    _animationController.duration = _generator.totalDuration;
+    _status = GameStatus.running;
+    _animationController.forward(from: 0);
+  }
+
+  @override
+  void dispose() {
+    _animationController.dispose();
+    super.dispose();
+  }
+}
+
+class ButtonGenerator {
+  final CardItem cardItem;
+
+  ButtonGenerator(this.cardItem);
+
   late List<ButtonInfo> buttonList = [];
-  late List<int> _moveIndex = [];
+  final List<double> _progressList = List<double>.generate(6, (_) => 0.0);
+  int score = 60;
+
+  Duration get totalDuration {
+    Duration base = Duration(seconds: cardItem.baseTime * buttonList.length);
+    Duration extra = Duration(seconds: buttonList.fold(0, (p, e) => p + e.pauseSecond));
+
+    return base + extra;
+  }
 
-  void _randomButton() {
-    _moveIndex = generateIntList();
+  void randomButton() {
     List<int> startIndex = generateIntList();
 
     buttonList = List.generate(6, (index) {
@@ -81,20 +117,67 @@ class ButtonController with ChangeNotifier {
         color: buttonColors[answer],
         startIndex: startIndex[index],
         endIndex: index,
+        pauseSecond: generateExtraTime(cardItem.lowerTime, cardItem.upperTime),
       );
     });
-  }
 
-  bool get isRunning => _animationController.isAnimating;
+    buttonList.shuffle();
+    buttonList[5].pauseSecond = 0;
 
-  void startOrReset() {
-    if (_animationController.isAnimating) {
-      _randomButton();
+    var swap = checkNeedSwap();
+
+    if (swap.$1 && swap.$2 != swap.$3) {
+      int be1 = buttonList[swap.$2].endIndex;
+      int be2 = buttonList[swap.$3].endIndex;
+
+      buttonList[swap.$2].endIndex = be2;
+      buttonList[swap.$3].endIndex = be1;
+      score = 40;
+    } else {
+      score = 60;
     }
-    _animationController.forward(from: 0);
+
+    int totalSeconds = totalDuration.inSeconds;
+
+    for (int i = 0; i < 6; i++) {
+      _progressList[i] = 0;
+    }
+    print("-------------------------------------");
+
+    for (int i = 0; i < 6; i++) {
+      final button = buttonList[i];
+      double value = (button.pauseSecond + cardItem.baseTime) / totalSeconds * 6;
+
+      for (int j = i; j < 6; j++) {
+        _progressList[j] = (value + _progressList[j]);
+      }
+      print("progress:${_progressList.map((i) => i.toStringAsFixed(2))}");
+    }
+
+    print("-------------------------------------");
   }
 
-  void stop() {
-    _animationController.stop();
+  void move(final double progress) {
+    int index = 0;
+    double lastProgress = 0;
+
+    for (int i = 0; i < 6; i++) {
+      if (_progressList[i] > progress) {
+        index = i;
+        break;
+      }
+      lastProgress = _progressList[i];
+    }
+
+    final button = buttonList[index];
+    final pauseProgress = button.pauseSecond / (button.pauseSecond + cardItem.baseTime);
+
+    // print("${progress},${progress - lastProgress},${pauseProgress}");
+
+    if (progress - lastProgress >= pauseProgress) {
+      button.process =
+          ((progress - lastProgress - pauseProgress) / (_progressList[index] - lastProgress - pauseProgress))
+              .clamp(0.0, 1.0);
+    }
   }
 }

+ 2 - 2
lib/button/button_painter.dart

@@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
 import 'package:widget/widget.dart';
 
 class ButtonPainter extends CustomPainter {
-  final ButtonController controller;
+  final GameController controller;
 
   ButtonPainter({required this.controller}) : super(repaint: controller);
 
@@ -16,7 +16,7 @@ class ButtonPainter extends CustomPainter {
       ..strokeWidth = 4;
 
     for (var button in controller.buttonList) {
-      var path = fromBottomToCenter(size, button.startIndex, button.endIndex,button.ops);
+      var path = fromBottomToCenter(size, button.startIndex, button.endIndex);
       var pms = path.computeMetrics();
       for (var pm in pms) {
         Tangent? tangent = pm.getTangentForOffset(pm.length * button.process);

+ 34 - 0
lib/data/card.dart

@@ -3,10 +3,17 @@ class CardItem {
   final String assetPath;
   final List<int> answer;
 
+  final int baseTime;
+  final int lowerTime;
+  final int upperTime;
+
   CardItem({
     required this.cardName,
     required this.assetPath,
     required this.answer,
+    required this.baseTime,
+    required this.lowerTime,
+    required this.upperTime,
   });
 }
 
@@ -15,16 +22,25 @@ final List<CardItem> smallCardList = <CardItem>[
     cardName: '和大自然一起玩-2',
     assetPath: 'assets/cards/css2-2.jpg',
     answer: [4, 5, 3, 1, 2, 6],
+    baseTime: 2,
+    lowerTime: 3,
+    upperTime: 5,
   ),
   CardItem(
     cardName: '我会穿衣服-11',
     assetPath: 'assets/cards/css2-11.jpg',
     answer: [5, 4, 3, 1, 6, 2],
+    baseTime: 2,
+    lowerTime: 3,
+    upperTime: 5,
   ),
   CardItem(
     cardName: '美食总动员-13',
     assetPath: 'assets/cards/css2-13.jpg',
     answer: [2, 4, 1, 6, 3, 5],
+    baseTime: 2,
+    lowerTime: 3,
+    upperTime: 5,
   ),
 ];
 
@@ -33,16 +49,25 @@ final List<CardItem> middleCardList = <CardItem>[
     cardName: '一起捉迷藏-1',
     assetPath: 'assets/cards/cms2-1.jpg',
     answer: [2, 5, 1, 6, 4, 3],
+    baseTime: 2,
+    lowerTime: 3,
+    upperTime: 5,
   ),
   CardItem(
     cardName: '繁忙的交通-5',
     assetPath: 'assets/cards/cms2-5.jpg',
     answer: [3, 4, 5, 2, 1, 6],
+    baseTime: 2,
+    lowerTime: 3,
+    upperTime: 5,
   ),
   CardItem(
     cardName: '繁忙的交通-15',
     assetPath: 'assets/cards/cms2-15.jpg',
     answer: [4, 5, 3, 2, 6, 1],
+    baseTime: 2,
+    lowerTime: 3,
+    upperTime: 5,
   ),
 ];
 
@@ -51,15 +76,24 @@ final List<CardItem> seniorCardList = <CardItem>[
     cardName: '热闹的跳蚤市场-6',
     assetPath: 'assets/cards/chs2-6.jpg',
     answer: [1, 2, 6, 3, 5, 4],
+    baseTime: 2,
+    lowerTime: 6,
+    upperTime: 8,
   ),
   CardItem(
     cardName: '热闹的跳蚤市场-14',
     assetPath: 'assets/cards/chs2-14.jpg',
     answer: [6, 2, 4, 5, 1, 3],
+    baseTime: 2,
+    lowerTime: 6,
+    upperTime: 8,
   ),
   CardItem(
     cardName: '热闹的跳蚤市场-16',
     assetPath: 'assets/cards/chs2-16.jpg',
     answer: [1, 2, 4, 6, 3, 5],
+    baseTime: 2,
+    lowerTime: 6,
+    upperTime: 8,
   ),
 ];

+ 56 - 0
lib/page/game/count_second.dart

@@ -0,0 +1,56 @@
+import 'package:flutter/material.dart';
+
+class CountSecond extends StatelessWidget {
+  final int second;
+
+  const CountSecond({
+    super.key,
+    required this.second,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
+      decoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(40),
+        color: Theme.of(context).colorScheme.secondary,
+      ),
+      child: Row(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          const SizedBox(width: 8),
+          Column(
+            crossAxisAlignment: CrossAxisAlignment.end,
+            children: [
+              SizedBox(
+                width: 34,
+                child: Text(
+                  '$second',
+                  textAlign: TextAlign.end,
+                  style: Theme.of(context).textTheme.titleLarge?.copyWith(
+                        color: Theme.of(context).colorScheme.onSecondary,
+                        fontSize: 24,
+                        fontWeight: FontWeight.w600,
+                      ),
+                ),
+              ),
+              Text(
+                '秒',
+                style: Theme.of(context).textTheme.titleSmall?.copyWith(
+                      color: Theme.of(context).colorScheme.onSecondary,
+                    ),
+              ),
+            ],
+          ),
+          const SizedBox(width: 8),
+          Icon(
+            Icons.timer,
+            size: 48,
+            color: Theme.of(context).colorScheme.onSecondary,
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 21 - 0
lib/page/game/status_notifier_mixin.dart

@@ -0,0 +1,21 @@
+import 'package:flutter/foundation.dart';
+
+mixin StatusNotifierMixin<T> on ChangeNotifier {
+  ValueChanged<T>? _statusListener;
+
+  void addStatusListener(ValueChanged<T> listener) {
+    _statusListener = listener;
+  }
+
+  void clearStatusListener() {
+    _statusListener = null;
+  }
+
+  @override
+  void notifyListeners({T? status}) {
+    super.notifyListeners();
+    if (status != null) {
+      _statusListener?.call(status);
+    }
+  }
+}

+ 70 - 99
lib/page/game_page.dart

@@ -1,12 +1,11 @@
-import 'dart:async';
-
 import 'package:battle/button/button_controller.dart';
 import 'package:battle/data/card.dart';
 import 'package:flutter/material.dart';
 import 'package:widget/widget.dart';
 
 import '../button/button_painter.dart';
-import 'setting_page.dart';
+import 'game/count_second.dart';
+import 'summary_page.dart';
 import 'view/count_down_dialog.dart';
 
 class GamePage extends StatefulWidget {
@@ -22,26 +21,28 @@ class GamePage extends StatefulWidget {
 }
 
 class _GamePageState extends State<GamePage> with SingleTickerProviderStateMixin {
-  late ButtonController _controller;
-  Timer? _timer;
-
-  int _count = 0;
+  late GameController _controller;
 
   @override
   void initState() {
     super.initState();
-    _controller = ButtonController(widget.card, vsync: this);
+    _controller = GameController(widget.card, vsync: this);
+    _controller.addStatusListener(_listenStatus);
   }
 
-  void _createTimer() {
-    _timer?.cancel();
-    _timer = Timer.periodic(const Duration(milliseconds: 250), (count) {
+  void _listenStatus(GameStatus status) {
+    if (status == GameStatus.end) {
       if (mounted) {
-        setState(() {
-          _count = count.tick;
-        });
+        showScore(context, score: _controller.score, time: _controller.count);
       }
-    });
+    }
+  }
+
+  @override
+  void dispose() {
+    _controller.clearStatusListener();
+    _controller.dispose();
+    super.dispose();
   }
 
   @override
@@ -70,82 +71,64 @@ class _GamePageState extends State<GamePage> with SingleTickerProviderStateMixin
               top: true,
               bottom: true,
               child: Column(
+                mainAxisSize: MainAxisSize.min,
+                mainAxisAlignment: MainAxisAlignment.center,
                 children: [
-                  Expanded(
-                    child: Column(
-                      mainAxisSize: MainAxisSize.min,
-                      mainAxisAlignment: MainAxisAlignment.center,
-                      children: [
-                        Padding(
-                          padding: const EdgeInsets.symmetric(horizontal: 16),
-                          child: Align(
-                            alignment: Alignment.centerLeft,
-                            child: Container(
-                              padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
-                              decoration: BoxDecoration(
-                                borderRadius: BorderRadius.circular(40),
-                                color: Theme.of(context).colorScheme.primaryContainer,
-                              ),
-                              child: Row(
-                                mainAxisSize: MainAxisSize.min,
-                                children: [
-                                  const Icon(Icons.timer),
-                                  const SizedBox(width: 8),
-                                  Text(
-                                    '${Duration(milliseconds: _count * 250).inSeconds}秒',
-                                    style: Theme.of(context).textTheme.titleLarge,
-                                  ),
-                                  const SizedBox(width: 8),
-                                ],
-                              ),
-                            ),
+                  Padding(
+                    padding: const EdgeInsets.symmetric(horizontal: 16),
+                    child: Align(
+                      alignment: Alignment.centerRight,
+                      child: AnimatedBuilder(
+                        animation: _controller,
+                        builder: (_, value) {
+                          return CountSecond(second: Duration(seconds: _controller.count).inSeconds);
+                        },
+                      ),
+                    ),
+                  ),
+                  const SizedBox(height: 16),
+                  Padding(
+                    padding: const EdgeInsets.symmetric(horizontal: 40),
+                    child: BattleBoard(
+                      card: ClipRRect(
+                        borderRadius: BorderRadius.circular(8),
+                        child: Container(
+                          width: double.infinity,
+                          height: double.infinity,
+                          color: Colors.grey,
+                          child: Image.asset(
+                            widget.card.assetPath,
+                            fit: BoxFit.cover,
                           ),
                         ),
-                        const SizedBox(height: 16),
-                        Padding(
-                          padding: const EdgeInsets.symmetric(horizontal: 16),
-                          child: BattleBoard(
-                            card: ClipRRect(
-                              borderRadius: BorderRadius.circular(8),
-                              child: Container(
-                                width: double.infinity,
-                                height: double.infinity,
-                                color: Colors.grey,
-                                child: Image.asset(
-                                  widget.card.assetPath,
-                                  fit: BoxFit.cover,
-                                ),
-                              ),
-                            ),
-                            button: CustomPaint(
-                              painter: ButtonPainter(controller: _controller),
-                              child: const SizedBox.expand(),
-                            ),
+                      ),
+                      button: CustomPaint(
+                        painter: ButtonPainter(controller: _controller),
+                        child: const SizedBox.expand(),
+                      ),
+                    ),
+                  ),
+                  const SizedBox(height: 32),
+                  Padding(
+                    padding: const EdgeInsets.symmetric(horizontal: 16),
+                    child: ButtonBar(
+                      alignment: MainAxisAlignment.spaceAround,
+                      children: [
+                        FilledButton(
+                          style: const ButtonStyle(
+                            fixedSize: WidgetStatePropertyAll<Size>(Size(180, 66)),
                           ),
-                        ),
-                        const SizedBox(height: 32),
-                        Padding(
-                          padding: const EdgeInsets.symmetric(horizontal: 16),
-                          child: ButtonBar(
-                            alignment: MainAxisAlignment.spaceAround,
-                            children: [
-                              FilledButton(
-                                onPressed: () {
-                                  showCountDown(context).then((_) {
-                                    _createTimer();
-                                    _controller.startOrReset();
-                                  });
-                                },
-                                child: const Text('开始'),
-                              ),
-                              FilledButton(
-                                onPressed: () {
-                                  _controller.stop();
-                                  _timer?.cancel();
-                                },
-                                child: const Text('停止'),
-                              ),
-                            ],
+                          onPressed: () {
+                            _controller.stop();
+                            showCountDown(context).then((_) {
+                              _controller.startOrReset();
+                            });
+                          },
+                          child: const Text(
+                            '开始/重新开始',
+                            style: TextStyle(
+                              fontSize: 18,
+                            ),
                           ),
                         ),
                       ],
@@ -155,18 +138,6 @@ class _GamePageState extends State<GamePage> with SingleTickerProviderStateMixin
               ),
             ),
           ),
-          Positioned(
-            right: 16,
-            top: MediaQuery.of(context).padding.top + 16,
-            child: IconButton(
-              icon: const Icon(Icons.settings),
-              onPressed: () {
-                Navigator.push(context, MaterialPageRoute(builder: (_) {
-                  return const SettingPage();
-                }));
-              },
-            ),
-          ),
         ],
       ),
     );

+ 3 - 0
lib/page/home_page.dart

@@ -93,6 +93,9 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
         cardName: card.cardName,
         assetPath: card.assetPath,
         answer: card.answer,
+        baseTime: card.baseTime,
+        lowerTime: card.lowerTime,
+        upperTime: card.upperTime,
       ).push(context),
       child: Card(
         shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),

+ 184 - 0
lib/page/summary_page.dart

@@ -0,0 +1,184 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+
+Future<void> showScore(
+  BuildContext context, {
+  required final int score,
+  required final int time,
+}) {
+  return Navigator.push(
+      context,
+      RawDialogRoute(
+        barrierDismissible: false,
+        pageBuilder: (_, __, ___) {
+          return _ScoreContent(score: score, time: time);
+        },
+      ));
+}
+
+class _ScoreContent extends StatefulWidget {
+  final int score;
+  final int time;
+
+  const _ScoreContent({
+    super.key,
+    required this.score,
+    required this.time,
+  });
+
+  @override
+  State<_ScoreContent> createState() => _ScoreContentState();
+}
+
+class _ScoreContentState extends State<_ScoreContent> {
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      type: MaterialType.transparency,
+      child: Center(
+        child: Container(
+          constraints: const BoxConstraints(maxWidth: 320),
+          child: Container(
+            width: double.infinity,
+            height: 280,
+            alignment: Alignment.center,
+            decoration: BoxDecoration(
+              color: const Color(0xFFFFF3E2),
+              borderRadius: BorderRadius.circular(40),
+            ),
+            child: Stack(
+              children: [
+                Positioned.fill(
+                  child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      const SizedBox(height: 64),
+                      Center(
+                        child: Container(
+                          height: 80,
+                          width: double.infinity,
+                          margin: const EdgeInsets.symmetric(horizontal: 32),
+                          decoration: BoxDecoration(
+                            color: Color(0xFFF8DEC3),
+                            borderRadius: BorderRadius.circular(16),
+                          ),
+                          child: Row(
+                            children: [
+                              Expanded(
+                                child: Row(
+                                  children: [
+                                    SizedBox(width: 8),
+                                    Icon(
+                                      Icons.timer,
+                                      color: Color(0xFFA3C5FF),
+                                      size: 32,
+                                    ),
+                                    SizedBox(width: 8),
+                                    Expanded(
+                                      child: Column(
+                                        mainAxisAlignment: MainAxisAlignment.center,
+                                        crossAxisAlignment: CrossAxisAlignment.start,
+                                        children: [
+                                          Text(
+                                            '${widget.time}秒',
+                                            style: TextStyle(
+                                              fontSize: 18,
+                                              color: Theme.of(context).colorScheme.primary,
+                                            ),
+                                          ),
+                                          Text(
+                                            '本次用时',
+                                            style: TextStyle(
+                                              fontSize: 12,
+                                              color: Theme.of(context).colorScheme.secondary,
+                                            ),
+                                          ),
+                                        ],
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                              ),
+                              Expanded(
+                                child: Row(
+                                  children: [
+                                    SizedBox(width: 8),
+                                    Icon(
+                                      Icons.check_circle,
+                                      color: Color(0xFFF98170),
+                                      size: 32,
+                                    ),
+                                    SizedBox(width: 8),
+                                    Expanded(
+                                      child: Column(
+                                        mainAxisAlignment: MainAxisAlignment.center,
+                                        crossAxisAlignment: CrossAxisAlignment.start,
+                                        children: [
+                                          Text(
+                                            '${widget.score}分',
+                                            style: TextStyle(
+                                              fontSize: 18,
+                                              color: Theme.of(context).colorScheme.primary,
+                                            ),
+                                          ),
+                                          Text(
+                                            '本次得分',
+                                            style: TextStyle(
+                                              fontSize: 12,
+                                              color: Theme.of(context).colorScheme.secondary,
+                                            ),
+                                          ),
+                                        ],
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                              ),
+                            ],
+                          ),
+                        ),
+                      ),
+                      Expanded(
+                        child: Center(
+                          child: Text(
+                            '小朋友你的呢?',
+                            style: TextStyle(
+                              fontSize: 24,
+                              color: Theme.of(context).colorScheme.onPrimaryContainer,
+                            ),
+                          ),
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+                Positioned(
+                  top: 16,
+                  right: 16,
+                  child: GestureDetector(
+                    onTap: () {
+                      Navigator.pop(context);
+                    },
+                    child: Container(
+                      width: 32,
+                      height: 32,
+                      decoration: BoxDecoration(
+                        borderRadius: BorderRadius.circular(16),
+                        color: Color(0x7F666666),
+                      ),
+                      child: Icon(
+                        Icons.close_rounded,
+                        color: Colors.white,
+                      ),
+                    ),
+                  ),
+                ),
+              ],
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}

+ 2 - 2
lib/page/view/count_down_dialog.dart

@@ -61,13 +61,13 @@ class _CountDownContentState extends State<_CountDownContent> {
       type: MaterialType.transparency,
       child: Center(
         child: Container(
-          constraints: const BoxConstraints(maxWidth: 300),
+          constraints: const BoxConstraints(maxWidth: 240),
           child: Column(
             mainAxisSize: MainAxisSize.min,
             children: [
               Container(
                 width: double.infinity,
-                height: 300,
+                height: 240,
                 alignment: Alignment.center,
                 decoration: BoxDecoration(
                   color: Theme.of(context).colorScheme.primaryContainer,

+ 9 - 0
lib/route.dart

@@ -30,11 +30,17 @@ class GameRouter extends GoRouteData {
   final String cardName;
   final String assetPath;
   final List<int> answer;
+  final int baseTime;
+  final int lowerTime;
+  final int upperTime;
 
   GameRouter({
     required this.cardName,
     required this.assetPath,
     required this.answer,
+    required this.baseTime,
+    required this.lowerTime,
+    required this.upperTime,
   });
 
   @override
@@ -44,6 +50,9 @@ class GameRouter extends GoRouteData {
         cardName: cardName,
         assetPath: assetPath,
         answer: answer,
+        baseTime: baseTime,
+        lowerTime: lowerTime,
+        upperTime: upperTime,
       ),
     );
   }

+ 6 - 0
lib/route.g.dart

@@ -67,6 +67,9 @@ extension $GameRouterExtension on GameRouter {
         cardName: state.uri.queryParameters['card-name']!,
         assetPath: state.uri.queryParameters['asset-path']!,
         answer: state.uri.queryParametersAll['answer']!.map(int.parse).toList(),
+        baseTime: int.parse(state.uri.queryParameters['base-time']!),
+        lowerTime: int.parse(state.uri.queryParameters['lower-time']!),
+        upperTime: int.parse(state.uri.queryParameters['upper-time']!),
       );
 
   String get location => GoRouteData.$location(
@@ -75,6 +78,9 @@ extension $GameRouterExtension on GameRouter {
           'card-name': cardName,
           'asset-path': assetPath,
           'answer': answer.map((e) => e.toString()).toList(),
+          'base-time': baseTime.toString(),
+          'lower-time': lowerTime.toString(),
+          'upper-time': upperTime.toString(),
         },
       );
 

+ 15 - 0
lib/utils/utils.dart

@@ -15,3 +15,18 @@ List<int> generateIntList() {
 
   return list;
 }
+
+int generateExtraTime(int min, int max) {
+  var random = Random.secure();
+  return random.nextInt(max - min) + min;
+}
+
+(bool, int, int) checkNeedSwap() {
+  var random = Random.secure();
+
+  bool swap = random.nextInt(10) >= 8;
+  int a = random.nextInt(6);
+  int b = random.nextInt(6);
+
+  return (swap, a, b);
+}

+ 1 - 3
packages/widget/lib/src/battle_path.dart

@@ -5,7 +5,7 @@ import 'path_op.dart';
 
 ///本质是求五个点的位置,依次lineTo起来形成一条路径
 
-Path fromBottomToCenter(Size size, int start, int end, List<PathOp> opList) {
+Path fromBottomToCenter(Size size, int start, int end) {
   final path = Path();
 
   final double line = size.width * kButtonLineAspectRatio;
@@ -43,8 +43,6 @@ Path fromBottomToCenter(Size size, int start, int end, List<PathOp> opList) {
   path.moveTo(p1x, p1y);
   path.lineTo(p2x, p2y);
 
-  PauseOp().handlePath(path, size, start, end);
-
   path.lineTo(cr - line / 2, p2y);
   path.lineTo(p3x, cb + line / 2);
 

+ 1 - 0
packages/widget/lib/src/constant.dart

@@ -60,6 +60,7 @@ const double kRightButtonBottomAspectRatio = _kRightButtonBottom / _kTextureHeig
 const double kTopLogoAspectRatio = 10 / 95;
 const Color kBoardBackgroundColor = Color(0xFFDDD8BA);
 const Color kBoardForegroundColor = Color(0xFF252C74);
+const Color kBoardThemeColor = Color(0xFFFFF3E2);
 
 const double kBoardRadius = 8;
 const double kCardRadius = 4;

+ 1 - 0
packages/widget/lib/widget.dart

@@ -3,3 +3,4 @@ library widget;
 export 'src/battle_layout.dart';
 export 'src/battle_path.dart';
 export 'src/path_op.dart';
+export 'src/constant.dart' show kBoardForegroundColor,kBoardBackgroundColor,kBoardThemeColor;