rajath_pai

Flutter Snake Game

Jul 25th, 2021
976
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import 'dart:async';
  2. import 'dart:math';
  3.  
  4. import 'package:flutter/material.dart';
  5.  
  6. void main() {
  7.   runApp(SnakeGame());
  8. }
  9.  
  10. class SnakeGame extends StatelessWidget {
  11.   const SnakeGame({Key, key}) : super(key: key);
  12.  
  13.   @override
  14.   Widget build(BuildContext context) {
  15.     return MaterialApp(
  16.       debugShowCheckedModeBanner: false,
  17.       home: GameField(),
  18.     );
  19.   }
  20. }
  21.  
  22. class GameField extends StatefulWidget {
  23.   const GameField({Key, key}) : super(key: key);
  24.  
  25.   @override
  26.   _GameFieldState createState() => _GameFieldState();
  27. }
  28.  
  29. enum Direction { up, down, left, right }
  30.  
  31. class _GameFieldState extends State<GameField> {
  32. //TODO 3: initialization of variable
  33.   bool _isAlive = true;
  34.   int length = 1;
  35.   Direction _direction = Direction.up;
  36.   List<Offset> _positions = [];
  37.   double? height;
  38.   double? width;
  39.   Timer? timer;
  40.   double speed = 4;
  41.   int _score = 0;
  42.   Offset? foodPosition;
  43.   Widget food = Container();
  44. //TODO: 1 build method
  45.   @override
  46.   Widget build(BuildContext context) {
  47.     changeSpeed();
  48.  
  49.     height = MediaQuery.of(context).size.height;
  50.     width = MediaQuery.of(context).size.width;
  51.     return Scaffold(
  52.         backgroundColor: Color(000000),
  53.         body: _isAlive
  54.             ? Stack(
  55.                 children: [
  56.                   Stack(
  57.                     children: snakePieces(),
  58.                   ),
  59.                   score(),
  60.                   food,
  61.                   gamePad(),
  62.                 ],
  63.               )
  64.             : onEnd());
  65.   }
  66.  
  67. //TODO on End
  68.   Widget onEnd() {
  69.     return SizedBox(
  70.       width: width,
  71.       child: Column(
  72.         mainAxisSize: MainAxisSize.max,
  73.         children: [
  74.           Spacer(
  75.             flex: 4,
  76.           ),
  77.           Text(
  78.             "Game Over",
  79.             style: TextStyle(
  80.                 color: Color(0xFF692765),
  81.                 fontSize: 24,
  82.                 fontWeight: FontWeight.bold),
  83.           ),
  84.           Spacer(
  85.             flex: 1,
  86.           ),
  87.           Text("Your Score is $_score",
  88.               style: TextStyle(
  89.                   color: Color(0xFF0a5369),
  90.                   fontSize: 20,
  91.                   fontWeight: FontWeight.bold)),
  92.           Spacer(
  93.             flex: 2,
  94.           ),
  95.           TextButton(
  96.             child: Text("Restart Game",
  97.                 style: TextStyle(
  98.                     color: Color(0xFF7d581b),
  99.                     fontSize: 22,
  100.                     fontWeight: FontWeight.bold)),
  101.             onPressed: () {
  102.               setState(() {
  103.                 _score = 0;
  104.                 speed = 4;
  105.                 length = 1;
  106.                 _positions = [];
  107.                 _isAlive = true;
  108.               });
  109.             },
  110.           ),
  111.           Spacer(
  112.             flex: 4,
  113.           ),
  114.         ],
  115.       ),
  116.     );
  117.   }
  118.  
  119. //check Alive
  120.   checkAlive() {
  121.     for (int i = 1; i < _positions.length; i++) {
  122.       if (_positions[i] == _positions[0]) {
  123.         _isAlive = false;
  124.       }
  125.     }
  126.   }
  127.  
  128. //TODO gamePAd
  129.   Widget gamePad() {
  130.     return Align(
  131.       alignment: Alignment.bottomCenter,
  132.       child: SizedBox(
  133.         height: width! / 2,
  134.         width: width! / 2,
  135.         child: Stack(
  136.           children: [
  137.             Align(
  138.               alignment: Alignment.bottomCenter,
  139.               child: IconButton(
  140.                   onPressed: () {
  141.                     if (_direction != Direction.up) _direction = Direction.down;
  142.                   },
  143.                   icon: Icon(
  144.                     Icons.keyboard_arrow_down,
  145.                     size: 35,
  146.                   )),
  147.             ),
  148.             Align(
  149.               alignment: Alignment.topCenter,
  150.               child: IconButton(
  151.                   onPressed: () {
  152.                     if (_direction != Direction.down) _direction = Direction.up;
  153.                   },
  154.                   icon: Icon(
  155.                     Icons.keyboard_arrow_up,
  156.                     size: 35,
  157.                   )),
  158.             ),
  159.             Align(
  160.               alignment: Alignment.centerRight,
  161.               child: IconButton(
  162.                   onPressed: () {
  163.                     if (_direction != Direction.left)
  164.                       _direction = Direction.right;
  165.                   },
  166.                   icon: Icon(
  167.                     Icons.keyboard_arrow_right,
  168.                     size: 35,
  169.                   )),
  170.             ),
  171.             Align(
  172.               alignment: Alignment.centerLeft,
  173.               child: IconButton(
  174.                   onPressed: () {
  175.                     if (_direction != Direction.right)
  176.                       _direction = Direction.left;
  177.                   },
  178.                   icon: Icon(
  179.                     Icons.keyboard_arrow_left,
  180.                     size: 35,
  181.                   )),
  182.             ),
  183.           ],
  184.         ),
  185.       ),
  186.     );
  187.   }
  188.  
  189. //TODO score
  190.   Positioned score() => Positioned(
  191.       top: 50,
  192.       right: 50,
  193.       child:
  194.           Text("$_score", style: TextStyle(color: Colors.red, fontSize: 22)));
  195.  
  196. //TODO speed
  197.   changeSpeed() {
  198.     if (timer != null) if (timer!.isActive) timer!.cancel();
  199.     timer = Timer.periodic(Duration(milliseconds: 500 ~/ speed), (timer) {
  200.       setState(() {});
  201.     });
  202.   }
  203.  
  204. //TODO snakePieces
  205.   List<Piece> snakePieces() {
  206.     List<Piece> pieces = [];
  207.     if (_isAlive) {
  208.       setState(() {
  209.         draw();
  210.         foodDraw();
  211.       });
  212.     }
  213.     for (int i = 0; i < _positions.length; i++) {
  214.       pieces.add(Piece(
  215.           size: 15,
  216.           posX: _positions[i].dx,
  217.           posY: _positions[i].dy,
  218.           color: Colors.blue));
  219.     }
  220.     checkAlive();
  221.     return pieces;
  222.   }
  223.  
  224. // TODO foodDraw
  225.   foodDraw() {
  226.     if (foodPosition == null) foodPosition = getRandomPositionWithinScreen();
  227.     food = Piece(
  228.         color: Colors.orange,
  229.         posX: foodPosition!.dx,
  230.         posY: foodPosition!.dy,
  231.         size: 15);
  232.     if (foodPosition! <= (_positions[0] + Offset(10, 10)) &&
  233.         foodPosition! >= (_positions[0] - Offset(10, 10))) {
  234.       _score += 5;
  235.       length += 1;
  236.       foodPosition = getRandomPositionWithinScreen();
  237.       speed += 0.15;
  238.     }
  239.   }
  240.  
  241. // TODO draw()
  242.   draw() {
  243.     if (_positions.length == 0) {
  244.       _positions.add(getRandomPositionWithinScreen());
  245.     }
  246.     while (length > _positions.length) {
  247.       _positions.add(_positions[_positions.length - 1]);
  248.     }
  249.     for (int i = _positions.length - 1; i > 0; i--) {
  250.       _positions[i] = _positions[i - 1];
  251.     }
  252.     _positions[0] = checkBorder(_positions[0]);
  253.     _positions[0] = getNextPosition(_positions[0]);
  254.   }
  255.  
  256. //TODO getNextPosition
  257.   Offset getNextPosition(Offset position) {
  258.     Offset nextPosition = Offset(5, 6);
  259.     if (_direction == Direction.up) nextPosition = position - Offset(0, 15);
  260.     if (_direction == Direction.down) nextPosition = position + Offset(0, 15);
  261.     if (_direction == Direction.right) nextPosition = position + Offset(15, 0);
  262.     if (_direction == Direction.left) nextPosition = position - Offset(15, 0);
  263.  
  264.     return nextPosition;
  265.   }
  266.  
  267. //TODO chck border
  268.   checkBorder(Offset position) {
  269.     if (position.dy > height!) position = Offset(position.dx, 0);
  270.     if (position.dy < 0) position = Offset(position.dx, height!);
  271.     if (position.dx > width!) position = Offset(0, position.dy);
  272.     if (position.dx < 0) position = Offset(width!, position.dy);
  273.     return position;
  274.   }
  275.  
  276. //TODO getRandomPosition
  277.   Offset getRandomPositionWithinScreen() {
  278.     Random rand = Random();
  279.     double x = rand.nextInt(width!.toInt()).toDouble();
  280.     double y = rand.nextInt(height!.toInt()).toDouble();
  281.     return Offset(x, y) - Offset(15, 15);
  282.   }
  283. }
  284.  
  285. // TODO 2 Piece
  286. class Piece extends StatelessWidget {
  287.   double size;
  288.   double posX;
  289.   double posY;
  290.   Color color;
  291.   Piece(
  292.       {Key, key,
  293.       required this.size,
  294.       required this.posX,
  295.       required this.posY,
  296.       required this.color})
  297.       : super(key: key);
  298.  
  299.   @override
  300.   Widget build(BuildContext context) {
  301.     return Positioned(
  302.       top: posY,
  303.       left: posX,
  304.       child: Container(
  305.         height: size,
  306.         width: size,
  307.         decoration: BoxDecoration(color: color, shape: BoxShape.circle),
  308.       ),
  309.     );
  310.   }
  311. }
RAW Paste Data