参考にしたサイトはこちら
→https://meganeprog.com/flutter-reversi/
かなり雑な記事です。見る際は注意!!
更新とともに充実させていくつもりではあります。
まずはGameWidget.dartの理解から。
GPT先生の力を全面的に借りてます。
ひとまずの目標
-
アニメーションはなくす。シミュレーターには邪魔でしかない。
-
オセロニアのバトルを実際に再現しながら、ダメージ量を確かめられるようなものを目指す。
-
ゲームのUI
class GameWidget extends StatefulWidget { const GameWidget(this._gameLogic, {super.key}); @override State<GameWidget> createState() => _GameWidgetState(_gameLogic); final GameLogicInterface _gameLogic; })
-
ゲームUIのステート
class _GameWidgetState extends State<GameWidget> with TickerProviderStateMixin { _GameWidgetState(this._gameLogic); @override initState() { super.initState(); _gameLogic.init();
-
石を裏返すためのコントローラーを生成
_stoneFlipControllers = List.generate( _gameLogic.boardRows, (int index) => List.generate( _gameLogic.boardColumns, (int index) => FlipCardController()));
-
ターンをあらわすカードのアニメーション
_turnCardAnimationController = AnimationController( duration: const Duration(milliseconds: 1000), vsync: this, );
-
ターンをあらわすカードのアニメーション(続き)
_turnCardAnimation = TweenSequence<double>([ TweenSequenceItem<double>( tween: Tween(begin: 0.0, end: 0.5).chain(CurveTween(curve: Curves.ease)), weight: 15, ), TweenSequenceItem<double>( tween: ConstantTween<double>(0.5), weight: 70, ), TweenSequenceItem<double>( tween: Tween(begin: 0.5, end: 1.0).chain(CurveTween(curve: Curves.ease)), weight: 15, ),
-
ターンをあらわすカードのアニメーション(続き)
]).animate(_turnCardAnimationController) ..addListener(() { setState(() {}); })
-
ターンをあらわすカードのアニメーション(続き)
..addStatusListener((status) { if (status == AnimationStatus.completed) { _animationPlaying = false; _gameLogic.hint(); } });
-
終了アニメーション
_finishCardAnimationController = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, );
-
終了アニメーション(続き)
_finishCardAnimation = TweenSequence<double>([ TweenSequenceItem<double>( tween: Tween(begin: 0.0, end: 0.5).chain(CurveTween(curve: Curves.easeIn)), weight: 60, ), TweenSequenceItem<double>( tween: Tween(begin: 0.5, end: 0.4) .chain(CurveTween(curve: Curves.easeOut)), weight: 20, ), TweenSequenceItem<double>( tween: Tween(begin: 0.4, end: 0.5).chain(CurveTween(curve: Curves.easeIn)), weight: 20, ),
-
どこかで見たような構図なので省略しようかとも思いましたが、簡単に出力できたため多めの出力です。
-
終了アニメーション(続き)
]).animate(_finishCardAnimationController) ..addListener(() { setState(() {}); });
-
これもどこかで見たような構図…
-
紙吹雪のコントローラーの初期化
_confettiController = ConfettiController( duration: const Duration(milliseconds: 500), );
-
最初のターンの通知
_animationPlaying = true; Future.delayed(const Duration(seconds: 1), () { _turnCardAnimationController.forward(); }); }
-
めんどくさくなったので「GPT先生の見解」省略!!
-
最初のターンの通知(続き)
@override void dispose() { _turnCardAnimationController.dispose(); _finishCardAnimationController.dispose(); _confettiController.dispose(); super.dispose(); }
-
最初のターンの通知(続き)
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Reversi'), ), body: Stack( children: <Widget>[ Center( child: _buildBoard(context), ), _buildTurnCard(context), _buildFinishCard(context), _buildConfetti(context), ], ), ); }
-
最初のターンの通知(続き)
Future<void> _putStone(int row, int column) async { if (_animationPlaying) { return; } List<Position> reversePositions = _gameLogic.getReversePositions(row, column, _gameLogic.turn); if (reversePositions.isNotEmpty) { _animationPlaying = true; setState(() { _gameLogic.clearHint(); _gameLogic.putStone(row, column, _gameLogic.turn); }); await Future.delayed(const Duration(milliseconds: 200)); for (Position position in reversePositions) { _stoneFlipControllers[position.row][position.column].toggleCard(); await Future.delayed(const Duration(milliseconds: 250)); setState(() { _gameLogic.reverseStone(position.row, position.column); _stoneFlipControllers[position.row][position.column] .toggleCardWithoutAnimation(); }); } await Future.delayed(const Duration(milliseconds: 200)); setState(() { if (_gameLogic.changeTurn()) { _turnCardAnimationController.reset(); _turnCardAnimationController.forward(); } else { // ゲームオーバー _finishCardAnimationController.forward(); if (_gameLogic.numberOfStone(Stone.white) != _gameLogic.numberOfStone(Stone.black)) { _confettiController.play(); } } }); } }