Created
April 24, 2022 16:17
-
-
Save yashlamba/7382e974f847b6361cf7159e6890a209 to your computer and use it in GitHub Desktop.
Snake Game Complete
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'dart:math'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/services.dart'; | |
void main() { | |
runApp(const SnakeGame()); | |
} | |
class SnakeGame extends StatelessWidget { | |
const SnakeGame({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return const MaterialApp( | |
title: "Snake Game", | |
home: Center( | |
child: Game(), | |
), | |
); | |
} | |
} | |
class Snake { | |
List<Point<int>> snake = [const Point(0, 0)]; | |
Point<int> direction = Constants.right; | |
Point<int> get head { | |
return snake[0]; | |
} | |
bool didBiteItself() { | |
for (int i = 1; i < snake.length; i++) { | |
if (snake[i] == head) { | |
return true; | |
} | |
} | |
return false; | |
} | |
bool pointOnSnake(Point<int> point) { | |
for (Point body in snake) { | |
if (body == point) { | |
return true; | |
} | |
} | |
return false; | |
} | |
void update() { | |
// For moving in a direction, move all body parts to the location of the | |
// part before them | |
for (int i = snake.length - 1; i > 0; --i) { | |
snake[i] = snake[i - 1]; | |
} | |
// Then update in the direction snake is moving | |
snake[0] = Point((head.x + direction.x) % 50, (head.y + direction.y) % 50); | |
} | |
void eatFood() { | |
// Since food is added to the end and snake would ultimately | |
// Update one position, save the last location and append it again. | |
var foodLoc = snake.last; | |
update(); | |
snake.add(foodLoc); | |
} | |
} | |
class Constants { | |
// Canvas | |
static const double canvasSize = 500; | |
static const double blockSize = 10; | |
// Directions | |
static const up = Point(0, -1); | |
static const down = Point(0, 1); | |
static const right = Point(1, 0); | |
static const left = Point(-1, 0); | |
} | |
class Game extends StatefulWidget { | |
const Game({Key? key}) : super(key: key); | |
@override | |
State<Game> createState() => _GameState(); | |
} | |
class _GameState extends State<Game> { | |
late Snake snake; | |
late Point<int> food; | |
Random random = Random(); | |
@override | |
void initState() { | |
initGame(); | |
Timer.periodic(const Duration(milliseconds: 50), (t) { | |
gameUpdate(); | |
}); | |
super.initState(); | |
} | |
initGame() { | |
snake = Snake(); | |
foodUpdate(); | |
} | |
void gameUpdate() { | |
// update this | |
if (food == snake.head) { | |
snake.eatFood(); | |
foodUpdate(); | |
} else { | |
snake.update(); | |
} | |
if (snake.didBiteItself()) { | |
initGame(); | |
} | |
setState(() {}); | |
} | |
void foodUpdate() { | |
do { | |
food = Point(random.nextInt(Constants.canvasSize ~/ Constants.blockSize), | |
random.nextInt(Constants.canvasSize ~/ Constants.blockSize)); | |
} while (snake.pointOnSnake(food)); | |
} | |
void keyHandler(RawKeyEvent event) { | |
if (event.logicalKey == LogicalKeyboardKey.arrowDown) { | |
if (snake.direction != Constants.up) { | |
snake.direction = Constants.down; | |
} | |
} else if (event.logicalKey == LogicalKeyboardKey.arrowUp) { | |
if (snake.direction != Constants.down) { | |
snake.direction = Constants.up; | |
} | |
} else if (event.logicalKey == LogicalKeyboardKey.arrowRight) { | |
if (snake.direction != Constants.left) { | |
snake.direction = Constants.right; | |
} | |
} else if (event.logicalKey == LogicalKeyboardKey.arrowLeft) { | |
if (snake.direction != Constants.right) { | |
snake.direction = Constants.left; | |
} | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return RawKeyboardListener( | |
focusNode: FocusNode(), | |
onKey: keyHandler, | |
autofocus: true, | |
child: Container( | |
width: Constants.canvasSize, | |
height: Constants.canvasSize, | |
color: Colors.black, | |
child: Stack( | |
children: snake.snake // Update This | |
.map((e) => Positioned( | |
top: Constants.blockSize * e.y, | |
left: Constants.blockSize * e.x, | |
child: Container( | |
height: Constants.blockSize, | |
width: Constants.blockSize, | |
color: Colors.green, | |
), | |
)) | |
.toList() + | |
[ | |
Positioned( | |
top: Constants.blockSize * food.y, | |
left: Constants.blockSize * food.x, | |
child: Container( | |
height: Constants.blockSize, | |
width: Constants.blockSize, | |
color: Colors.red, | |
), | |
) | |
], | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment