Flutter 贪吃蛇小游戏(要用上下左右控制的。。。没键盘的不行哦)245行

Posted 安果移不动

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 贪吃蛇小游戏(要用上下左右控制的。。。没键盘的不行哦)245行相关的知识,希望对你有一定的参考价值。

贪吃蛇小游戏。

 

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: '贪吃蛇'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

//球的位置
Offset _ball = Offset.zero;
//每个快宽度固定的
const double _size = 20;
//贪吃蛇的位置
List<Offset> _snakeList = [Offset(_size * 2, 0), Offset(_size * 3, 0)];

//贪吃蛇的方向
enum Direction { Up, Down, Left, Right }
enum GameStatus { Over, Start }

Direction _direction = Direction.Up;
GameStatus _gameStatus = GameStatus.Start;

late Timer _timer;

class _MyHomePageState extends State<MyHomePage> {
  //每次build之前被调用
  @override
  void didChangeDependencies() {
    reSetGame();
    super.didChangeDependencies();
  }

  void reSetGame() {
    var period = Duration(milliseconds: 200);
    double maxWidth = MediaQuery.of(context).size.width;
    double maxHeight = MediaQuery.of(context).size.height;
    double widthPad = maxWidth % _size;
    double heightPad = maxHeight % _size;
    maxWidth = maxWidth - widthPad;
    maxHeight -= heightPad;
    _ball = randomPosition(maxWidth, maxHeight);
    _timer = Timer.periodic(period, (timer) {
      //更新蛇的位置
      List<Offset> newSnakeList = List.generate(_snakeList.length, (index) {
        if (index > 0) {
          return _snakeList[index - 1];
        } else {
          final snakeHead = _snakeList[0];

          switch (_direction) {
            case Direction.Up:
              return Offset(
                  snakeHead.dx, (snakeHead.dy - _size + maxHeight) % maxHeight);
            case Direction.Down:
              return Offset(snakeHead.dx, (snakeHead.dy + _size) % maxHeight);
            case Direction.Left:
              return Offset(
                  (snakeHead.dx - _size + maxWidth) % maxWidth, snakeHead.dy);
            case Direction.Right:
              return Offset((snakeHead.dx + _size) % maxWidth, snakeHead.dy);
          }
        }
      });
      //贪吃蛇吃到块
      if (newSnakeList[0] == _ball) {
        //吧贪吃蛇加一个
        newSnakeList..add(_snakeList[_snakeList.length - 1]);
        setState(() {
          _ball = randomPosition(maxWidth, maxHeight);
        });
      }
      //贪吃蛇迟到自己
      List<Offset> judgeSnakeList = List.from(newSnakeList);
      judgeSnakeList.removeAt(0);
      if (judgeSnakeList.contains(newSnakeList[0])) {
        setState(() {
          _gameStatus = GameStatus.Over;
          _timer.cancel();
        });
      }
      setState(() {
        _snakeList = newSnakeList;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
        body: RawKeyboardListener(
      focusNode: FocusNode(),
      autofocus: true,
      onKey: (event) {
        if (event.runtimeType == RawKeyDownEvent) {
          Direction newDirection = Direction.Left;

          switch (event.logicalKey.keyLabel) {
            case "Arrow Up":
              // 处理对立面
              if (_direction == Direction.Down) {
                return;
              }
              newDirection = Direction.Up;
              break;
            case "Arrow Down":
              // 处理对立面
              if (_direction == Direction.Up) {
                return;
              }
              newDirection = Direction.Down;
              break;
            case "Arrow Left":
              // 处理对立面
              if (_direction == Direction.Right) {
                return;
              }
              newDirection = Direction.Left;
              break;
            case "Arrow Right":
              // 处理对立面
              if (_direction == Direction.Left) {
                return;
              }
              newDirection = Direction.Right;
              break;
          }
          setState(() {
            _direction = newDirection;
          });
        }
      },
      child: _gameStatus == GameStatus.Start
          ? _buildGameStart()
          : _buildGameOver(),
    )
        // This trailing comma makes auto-formatting nicer for build methods.
        );
  }

  GestureDetector _buildGameOver() {
    return GestureDetector(
      onTap: () {},
      child: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextButton(
              child: Text("点击继续游戏(假装有广告其实没有)"),
              onPressed: () {
                setState(() {
                  _gameStatus = GameStatus.Start;
                  reSetGame();
                });
              },
            ),
            TextButton(
              child: Text("点击重新游戏(假装有广告其实没有)"),
              onPressed: () {
                setState(() {
                  _gameStatus = GameStatus.Start;
                  _direction = Direction.Up;
                  _snakeList = [Offset(_size * 2, 0), Offset(_size * 3, 0)];
                  reSetGame();
                });
              },
            )
          ],
        ),
      ),
    );
  }

  _buildGameStart() {
    return Stack(
      children: _snakeList
          .map((snake) => Positioned.fromRect(
              rect: Rect.fromCenter(
                  center: adjust(snake), width: _size, height: _size),
              child: Container(
                margin: EdgeInsets.all(1),
                color: Colors.black,
              )))
          .toList()
            //蛇
            ..add(Positioned.fromRect(
                rect: Rect.fromCenter(
                    center: adjust(_ball), width: _size, height: _size),
                child: Container(
                  margin: EdgeInsets.all(1),
                  color: Colors.orange,
                ))),
    );
  }

  Offset adjust(Offset offset) {
    return Offset(offset.dx + (_size / 2), offset.dy + (_size / 2));
  }

  Offset randomPosition(double widthRange, double heightRange) {
    var rng = Random();

    int intWidthRange = widthRange.toInt();
    int intHeightRange = heightRange.toInt();

    int finalWdith = rng.nextInt(intWidthRange);
    int finalHeight = rng.nextInt(intHeightRange);
    double widthPad = finalWdith % _size;
    double heightPad = finalHeight % _size;

    double actualWidth = finalWdith - widthPad;
    double actualHeight = finalHeight - heightPad;
    return Offset(actualWidth, actualHeight);
  }
}

以上是关于Flutter 贪吃蛇小游戏(要用上下左右控制的。。。没键盘的不行哦)245行的主要内容,如果未能解决你的问题,请参考以下文章

结对编程—贪吃蛇游戏—需求分析

C语言课程设计,贪吃蛇应该怎么做?

结对-贪吃蛇游戏-结对项目总结

课后作业-结对编程项目总结

课后作业-结对编程项目总结

用C语言编写贪吃蛇小游戏