基于Android Flutter編寫貪吃蛇游戲
前言
放假期間,小T打算回顧一下經(jīng)典,想用Flutter做一下小游戲,做什么好呢,從打飛機到坦克大戰(zhàn),最后還是想做一款貪吃蛇,依稀還記得,小時候第一次玩游戲是在父母的小靈通上玩貪吃蛇哈哈,但是光光一個貪吃蛇太單調(diào)了,我們就加一個陀螺儀吧~
話不多說,先上效果圖,有圖有真相!?。ㄍ勇輧x好難操控)!

開發(fā)步驟:
非常簡單,就是玩起來有點費手~
github倉庫還沒有搭建,大家可以先看一下文末通知!
1.定義蛇和豆子
2.讓蛇動起來
3.使用陀螺儀來控制蛇
4.讓蛇吃掉豆子
5.吃掉豆子隨機生成一個豆子
1.定義蛇和豆子
///蛇的每一塊的大小 const double size = 10; Offset ball = Offset.zero;//豆子 List<Offset> snakeList = [Offset(50, 0), Offset(60, 0)];//蛇的長度
顯示豆子和蛇:
使用Stack是因為豆子在被蛇吃的時候會重疊
使用Positioned來進行定位
body: Stack(
children: snakeList
.map((snake) => Positioned.fromRect(
rect: Rect.fromCenter(
center: adjust(snake), width: size, height: size),
child: Container(margin:const EdgeInsets.all(1),color: Colors.black)))//加個外邊距使每一塊更清晰
.toList()
..add(Positioned.fromRect(
rect: Rect.fromCenter(
center: adjust(ball), width: size, height: size),
child: Container(color: Colors.orange))),
)Offset adjust(Offset offset) {
return Offset(offset.dx + size / 2, offset.dy + size / 2); //使每一塊更好的展示出來
}2.讓蛇動起來
在這里我們要先給蛇來一個狀態(tài)定義:
///控制蛇的狀態(tài)
enum Direction { Up, Down, Left, Right }因為蛇要一直動,所以給一個周期函數(shù):
1.定義200毫秒動一次
2.處理更新蛇的長度
3.求余的好處在于優(yōu)化吃豆子,因為隨機生成豆子時,可能是個不會被整除的。
Direction direction = Direction.Left; //給蛇設(shè)置一個狀態(tài),默認(rèn)向左移動
///周期函數(shù)
void didChangeDependencies() {
///兩百毫秒的周期函數(shù)
var period = Duration(milliseconds: 200);
///對蛇的長度進行優(yōu)化
double maxWidth = MediaQuery.of(context).size.width;
double widthPad = maxWidth % size;
maxWidth -= widthPad;
double maxHeight = MediaQuery.of(context).size.height;
double heigthPad = maxHeight % size; //這里除于是為了更好的游戲體驗
maxHeight -= heigthPad;
///周期調(diào)用
///用于貪吃蛇的自己移動,以及碰撞檢測
Timer.periodic(period, (timer) {
final snakeHead = snakeList[0];
List<Offset> newSnakeList = List.generate(snakeList.length, (index) {
if (index > 0) {
return snakeList[index - 1];
} else {
///移動處理
switch (direction) {
case Direction.Up:
return Offset(snakeHead.dx,
(snakeHead.dy - size + maxHeight) % maxHeight); //求余是保證不會超標(biāo)
case Direction.Down:
return Offset(
snakeHead.dx, (snakeHead.dy + size + maxHeight) % maxHeight);
case Direction.Left:
return Offset(
(snakeHead.dx - size + maxWidth) % maxWidth, snakeHead.dy);
case Direction.Right:
return Offset(
(snakeHead.dx + size + maxWidth) % maxWidth, snakeHead.dy);
}
}
});
setState(() {
snakeList = newSnakeList; //更新蛇的狀態(tài)
});
});
super.didChangeDependencies();
}3.使用陀螺儀來控制蛇
Flutter使用陀螺儀需要借助一個庫:sensors 或者sensors_plus,兩者沒有太大的區(qū)別
這個demo使用:
sensors: any
官方給的例子:
import 'package:sensors/sensors.dart';
?
accelerometerEvents.listen((AccelerometerEvent event) {
print(event);
});
// [AccelerometerEvent (x: 0.0, y: 9.8, z: 0.0)] 加速度
?
userAccelerometerEvents.listen((UserAccelerometerEvent event) {
print(event);
});
// [UserAccelerometerEvent (x: 0.0, y: 0.0, z: 0.0)]
?
gyroscopeEvents.listen((GyroscopeEvent event) {
print(event);
});
// [GyroscopeEvent (x: 0.0, y: 0.0, z: 0.0)] 陀螺儀我們在initState對陀螺儀進行監(jiān)聽:
這里有x,y,z的三個參數(shù),也可以自己優(yōu)化調(diào)試,5.0是當(dāng)手機傾斜>=45°
@override
void initState() {
super.initState();
accelerometerEvents.listen((AccelerometerEvent event) {
setState(() {
_accelerometerValues = <double>[event.x, event.y, event.z];
if(_accelerometerValues[0] >= 5.0){
direction = Direction.Left;
}else if(_accelerometerValues[1] >= 5.0){
direction = Direction.Down;
}else if(_accelerometerValues[0] <= -5.0){
direction = Direction.Right;
}else if(_accelerometerValues[1] <= -5.0){
direction = Direction.Up;
}
});
});
}4.讓蛇吃掉豆子
還是在剛剛的周期函數(shù)里添加:
當(dāng)蛇頭碰到豆子時,給蛇加一格
if(newSnakeList[0] == ball){
newSnakeList..add(snakeList[snakeList.length - 1]);
setState(() {
ball = randoowPositon(maxWidth, maxHeight); //隨機生成一個豆子,randoowPositon方法在后面
});
}5.吃掉豆子隨機生成一個豆子
對豆子的生成也需要優(yōu)化一下 (之前生成有點問題,現(xiàn)在優(yōu)化一下)
Offset randoowPositon(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(rng.nextInt(widthRange.toInt()).toDouble(),
rng.nextInt(heightRange.toInt()).toDouble());
}到此這篇關(guān)于基于Android Flutter編寫貪吃蛇游戲的文章就介紹到這了,更多相關(guān)Flutter貪吃蛇內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android編程連接MongoDB及增刪改查等基本操作示例
這篇文章主要介紹了Android編程連接MongoDB及增刪改查等基本操作,簡單介紹了MongoDB功能、概念、使用方法及Android操作MongoDB數(shù)據(jù)庫的基本技巧,需要的朋友可以參考下2017-07-07
Android開發(fā)之BroadcastReceiver用法實例分析
這篇文章主要介紹了Android開發(fā)之BroadcastReceiver用法,實例分析了Android中廣播的相關(guān)使用技巧,需要的朋友可以參考下2015-05-05
Android RecyclerView item選中放大被遮擋問題詳解
這篇文章主要介紹了Android RecyclerView item選中放大被遮擋問題詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04
Android筆記之:App應(yīng)用之啟動界面SplashActivity的使用
當(dāng)前比較成熟一點的應(yīng)用基本上都會在進入應(yīng)用之顯示一個啟動界面.這個啟動界面或簡單,或復(fù)雜,或簡陋,或華麗,用意不同,風(fēng)格也不同2013-04-04
Android中自定義PopupWindow實現(xiàn)彈出框并帶有動畫效果
這篇文章主要介紹了Android中自定義PopupWindow實現(xiàn)彈出框并帶有動畫效果的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09
Android Handler主線程和一般線程通信的應(yīng)用分析
本篇文章小編為大家介紹,Android Handler主線程和一般線程通信的應(yīng)用分析。需要的朋友參考下2013-04-04
Android 利用反射+try catch實現(xiàn)sdk按需引入依賴庫的方法
這篇文章主要介紹了Android 利用反射+try catch來實現(xiàn)sdk按需引入依賴庫,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11

