0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ド素人がFlutterでオセロニアシミュレーター作ってみる

Last updated at Posted at 2023-10-06

参考にしたサイトはこちら
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;
    }) 
    
  • GPT先生の見解1-8

  • GPT先生の見解1-2

  • GPT先生の見解4-5

  • GPT先生の見解7

  • ゲームUIのステート

    class _GameWidgetState extends State<GameWidget> with TickerProviderStateMixin {
      _GameWidgetState(this._gameLogic);
    
      @override
      initState() {
        super.initState();
    
        _gameLogic.init();
    
  • GPT先生の見解1-8

  • GPT先生の見解1

  • GPT先生の見解1-2

  • GPT先生の見解5-8

  • 石を裏返すためのコントローラーを生成

        _stoneFlipControllers = List.generate(
            _gameLogic.boardRows,
            (int index) => List.generate(
                _gameLogic.boardColumns, (int index) => FlipCardController()));
    
  • GPT先生の見解1-4

  • GPT先生の見解1-2

  • GPT先生の見解3-4

  • GPT先生の見解4

  • ターンをあらわすカードのアニメーション

        _turnCardAnimationController = AnimationController(
          duration: const Duration(milliseconds: 1000),
          vsync: this,
        );
    
  • GPT先生の見解1-4

  • GPT先生の見解一部

  • ターンをあらわすカードのアニメーション(続き)

        _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,
          ),
    
  • GPT先生の見解1-15

  • GPT先生の見解1-6

  • GPT先生の見解7-10

  • GPT先生の見解11-15

  • ターンをあらわすカードのアニメーション(続き)

        ]).animate(_turnCardAnimationController)
          ..addListener(() {
            setState(() {});
          })
    
  • GPT先生の見解1-4

  • ターンをあらわすカードのアニメーション(続き)

          ..addStatusListener((status) {
            if (status == AnimationStatus.completed) {
              _animationPlaying = false;
              _gameLogic.hint();
            }
          });
    
  • GPT先生の見解1-6

  • 終了アニメーション

        _finishCardAnimationController = AnimationController(
          duration: const Duration(milliseconds: 500),
          vsync: this,
        );
    
  • GPT先生の見解1-4

  • 終了アニメーション(続き)

        _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,
          ),
    
  • GPT先生の見解1-15

  • GPT先生の見解1-6

  • GPT先生の見解7-11

  • GPT先生の見解12-15

  • どこかで見たような構図なので省略しようかとも思いましたが、簡単に出力できたため多めの出力です。

  • 終了アニメーション(続き)

        ]).animate(_finishCardAnimationController)
          ..addListener(() {
            setState(() {});
          });
    
  • GPT先生の見解1-4

  • これもどこかで見たような構図…

  • 紙吹雪のコントローラーの初期化

        _confettiController = ConfettiController(
          duration: const Duration(milliseconds: 500),
        );
    
  • GPT先生の見解1-3

  • 最初のターンの通知

        _animationPlaying = true;
        Future.delayed(const Duration(seconds: 1), () {
          _turnCardAnimationController.forward();
        });
      }
    
  • 1-5

  • めんどくさくなったので「GPT先生の見解」省略!!

  • 最初のターンの通知(続き)

      @override
      void dispose() {
        _turnCardAnimationController.dispose();
        _finishCardAnimationController.dispose();
        _confettiController.dispose();
        super.dispose();
      }
    
  • 1-7

  • 最初のターンの通知(続き)

      @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),
            ],
          ),
        );
      }
    
  • 1-18

  • 1-4

  • 5-8

  • 9-14

  • 最初のターンの通知(続き)

      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();
              }
            }
          });
        }
      }
    
    
  • 1-39

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?