game_page.dart 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import 'dart:async';
  2. import 'package:battle/button/button_controller.dart';
  3. import 'package:battle/data/card.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:widget/widget.dart';
  6. import '../button/button_painter.dart';
  7. import 'setting_page.dart';
  8. class GamePage extends StatefulWidget {
  9. final CardItem card;
  10. const GamePage({
  11. super.key,
  12. required this.card,
  13. });
  14. @override
  15. State<GamePage> createState() => _GamePageState();
  16. }
  17. class _GamePageState extends State<GamePage> with SingleTickerProviderStateMixin {
  18. late ButtonController _controller;
  19. Timer? _timer;
  20. int _count = 0;
  21. @override
  22. void initState() {
  23. super.initState();
  24. _controller = ButtonController(widget.card, vsync: this);
  25. }
  26. void _createTimer() {
  27. _timer?.cancel();
  28. _timer = Timer.periodic(const Duration(milliseconds: 250), (count) {
  29. if (mounted) {
  30. setState(() {
  31. _count = count.tick;
  32. });
  33. }
  34. });
  35. }
  36. @override
  37. Widget build(BuildContext context) {
  38. return Scaffold(
  39. body: Stack(
  40. children: [
  41. Positioned.fill(
  42. child: ColorFiltered(
  43. colorFilter: const ColorFilter.matrix(<double>[
  44. 0.299, 0.587, 0.114, 0, 0, //r
  45. 0.299, 0.587, 0.114, 0, 0, //g
  46. 0.299, 0.587, 0.114, 0, 0, //b
  47. 0, 0, 0, 0.1, 0, //a
  48. ]),
  49. child: Image.asset(
  50. 'assets/images/background.png',
  51. repeat: ImageRepeat.repeat,
  52. cacheWidth: 182,
  53. cacheHeight: 52,
  54. ),
  55. ),
  56. ),
  57. Positioned.fill(
  58. child: SafeArea(
  59. top: true,
  60. bottom: true,
  61. child: Column(
  62. children: [
  63. Expanded(
  64. child: Column(
  65. mainAxisSize: MainAxisSize.min,
  66. mainAxisAlignment: MainAxisAlignment.center,
  67. children: [
  68. Padding(
  69. padding: const EdgeInsets.symmetric(horizontal: 16),
  70. child: Align(
  71. alignment: Alignment.centerLeft,
  72. child: Container(
  73. padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
  74. decoration: BoxDecoration(
  75. borderRadius: BorderRadius.circular(40),
  76. color: Theme.of(context).colorScheme.primaryContainer,
  77. ),
  78. child: Row(
  79. mainAxisSize: MainAxisSize.min,
  80. children: [
  81. const Icon(Icons.timer),
  82. const SizedBox(width: 8),
  83. Text(
  84. '${Duration(milliseconds: _count * 250).inSeconds}秒',
  85. style: Theme.of(context).textTheme.titleLarge,
  86. ),
  87. const SizedBox(width: 8),
  88. ],
  89. ),
  90. ),
  91. ),
  92. ),
  93. const SizedBox(height: 16),
  94. Padding(
  95. padding: const EdgeInsets.symmetric(horizontal: 16),
  96. child: BattleBoard(
  97. card: ClipRRect(
  98. borderRadius: BorderRadius.circular(8),
  99. child: Container(
  100. width: double.infinity,
  101. height: double.infinity,
  102. color: Colors.grey,
  103. child: Image.asset(
  104. widget.card.assetPath,
  105. fit: BoxFit.cover,
  106. ),
  107. ),
  108. ),
  109. button: CustomPaint(
  110. painter: ButtonPainter(controller: _controller),
  111. child: const SizedBox.expand(),
  112. ),
  113. ),
  114. ),
  115. SizedBox(height: 32),
  116. Padding(
  117. padding: const EdgeInsets.symmetric(horizontal: 16),
  118. child: ButtonBar(
  119. alignment: MainAxisAlignment.spaceAround,
  120. children: [
  121. FilledButton(
  122. onPressed: () {
  123. _createTimer();
  124. _controller.startOrReset();
  125. },
  126. child: const Text('开始'),
  127. ),
  128. FilledButton(
  129. onPressed: () {
  130. _controller.stop();
  131. _timer?.cancel();
  132. },
  133. child: const Text('停止'),
  134. ),
  135. ],
  136. ),
  137. ),
  138. ],
  139. ),
  140. ),
  141. ],
  142. ),
  143. ),
  144. ),
  145. Positioned(
  146. right: 16,
  147. top: MediaQuery.of(context).padding.top + 16,
  148. child: IconButton(
  149. icon: const Icon(Icons.settings),
  150. onPressed: () {
  151. Navigator.push(context, MaterialPageRoute(builder: (_) {
  152. return const SettingPage();
  153. }));
  154. },
  155. ),
  156. ),
  157. ],
  158. ),
  159. );
  160. }
  161. }