flutter能开发游戏吗_Flutter开发游戏初体验,喜大普奔
前面给大家介绍了Flutter 以及Flutter Web,接下来给大家带来一个更劲爆的知识点—— Flutter开发游戏。是的,没错,Flutter也可以用来开发游戏了。有人会问不懂Unity或者Cocos2d也能用Flutter开发游戏吗???是的,你没看错,Flutter就是这么666。我在pub.dev上面找到了一些有关游戏的第三方开源库,使用它们你就可以轻而易举的实现你的游戏梦(你要说开
前面给大家介绍了Flutter 以及Flutter Web,接下来给大家带来一个更劲爆的知识点—— Flutter开发游戏。是的,没错,Flutter也可以用来开发游戏了。有人会问不懂Unity或者Cocos2d也能用Flutter开发游戏吗???是的,你没看错,Flutter就是这么666。
我在pub.dev上面找到了一些有关游戏的第三方开源库,使用它们你就可以轻而易举的实现你的游戏梦(你要说开发王者荣耀、吃鸡那种大型游戏的话就当我前面的话没说)。下面开始今天的干货分享。
作者写文章不容易,觉得好看的话,点个赞,支持一下吧,谢谢大家。另外我的专栏【Flutter&Dart】专门发布Flutter干货,欢迎大家关注:Flutter&Dartzhuanlan.zhihu.com
一、添加依赖包
首先在pubspec.yaml 里面添加依赖包,如下所示:
dependencies:flutter:sdk:flutterflame:^0.17.2box2d_flame:^0.4.4sensors:^0.4.1+1
二、在main.dart中添加相关设置要素
1 import'dart:async';
2 import'package:flame/util.dart';
3 import'package:flutter/material.dart';
4 import'package:flutter/services.dart';
5 import'game.dart';
6
7 void main() async {
8 // 启动游戏前要先设置flame的相关属性 9 await setupFlame();
10 var game = new FlutterGame();
11 runApp(game.widget);
12 }
13
14 /// 构建Flame所需要的属性设置15 Future setupFlame() async {
16 // 创建 Util对象17 var flameUtil = Util();
18 // 设置全屏19 await flameUtil.fullScreen();
20 // 固定为纵向位置,不允许旋转21 await flameUtil.setOrientation(DeviceOrientation.portraitUp);
22 }
首先解释一下每个包的作用:
// MD组件import 'package:flutter/material.dart';
// 我们需要Flame构建游戏import 'package:flame/util.dart';
// setupFlame() 方法中需要用到import 'package:flutter/services.dart';
// 异步支持import 'dart:async';
// 具体的游戏界面import'FlutterGame.dart';
main()函数用了一个async表示异步,因为这涉及到里面的“setupFlame()”函数。setupFlame()函数是一个异步的,它里面主要是构建Flame所需要的属性设置,我们在启动游戏前要先设置flame的相关属性。
setupFlame()函数里面做了3件事:
● 创建 Util对象
● 设置全屏
● 固定为纵向位置,不允许旋转
三、游戏部分的代码
接下来看看game.dart里面的代码,如下所示:
1 import'dart:ui';
2
3 import'package:box2d_flame/box2d.dart';
4 import'package:flame/flame.dart';
5 import'package:flame/game.dart';
6
7 class FlutterGame extends Game{
8 staticconstint WORLD_POOL_SIZE = 100;
9 staticconstint WORLD_POOL_CONTAINER_SIZE = 10;
10
11 World world;
12
13 final Vector2 _gravity = Vector2.zero();
14
15 FlutterGame() {
16 world = new World.withPool(
17 _gravity,
18 DefaultWorldPool(WORLD_POOL_SIZE, WORLD_POOL_CONTAINER_SIZE),
19 );
20 initialize();
21 }
22
23 Future initialize() async {
24 resize(await Flame.util.initialDimensions());
25 }
26
27 void resize(Size size){
28 super.resize(size);
29 }
30
31 @override
32 void render(Canvas canvas){
33 }
34
35 @override
36 void update(double t){
37 }
38 }
解释一下上面的代码的意思:
FlutterGame类是具体游戏功能的实现,继承了Flame提供的Game类,所以可以放心大胆的写我们自己的功能,比如游戏循环或者调整大小事件等。Box2D将负责我们所有与物理相关的操作,这包括处理碰撞,加速/减速物体/质量以及模拟我们游戏中的不同形状/材料。
World是主要物理对象。
gravity 设置向量为0 表示无重力(gravity),Vector2你可以把它看做是平面二维坐标系统内的一个点,每个Vector2都有一个X和一个Y值。我们的gravity向量坐标值为(0,0)手机坐标系统左上角为(0,0),上部水平向右x轴正方向,左侧垂直向下位y轴正方向重力设置位(0,1)表示元素从屏幕顶部掉落到底部。
Box2D 需要用到 这两个常量值,这里面定义了两个,分别是:WORLD_POOL_SIZE和WORLD_POOL_CONTAINER_SIZE。
然后使用World.withPool创建World对象。
接下来调用initialize()方法,初始化我们所有需要的东西,包括:需要调整大小和不需要调整大小的东西。然后它的返回值调用Flame的初始化的方法,一旦Flutter准备就绪,立即调用resize()方法检查显示尺寸。
接下来看看几个函数的说明:
● render:在画布上绘制元素。
● update: 目标是60fps的速度进行,这意味着在一秒内将调用该函数60次。由于并不一直是60fps的速度,time参数会告诉你自上次调用以来经过了多少时间。
四、开启引擎,绘制元素
如果你按照以上步骤都都设置好了,这时候运行程序到你的设备,你会发现是一片黑色或空白的,因为我们还没有绘制任何元素在我们的界面上面。
接下来可以试着画一点东西上去。
新增代码如下所示:
Paint paint;
Size screenSize;
Rect _screenRect;
final int scale = 5;
void resize(Size size) {
paint = Paint();
paint.color = Color(0xffffffff);
screenSize = size;
_screenRect = Rect.fromLTWH(0, 0, screenSize.width, screenSize.height);
super.resize(size);
}
void render(Canvas canvas) {
if (screenSize == null) {
return;
}
canvas.save();
canvas.scale(screenSize.width / scale);
canvas.translate(_screenRect.width/2, _screenRect.height/2);
canvas.drawCircle(Offset(0, 0), .1, paint);
canvas.restore();
}
}
这里发生的事情如下:
首先声明一个Paint对象,它是画笔,需要它来画一些东西。
screenSize和screenRect分别用于保存屏幕大小和相关的矩形以供以后使用。在resize()方法中,通过调用Flame的相关API,获得了size和Rect,然后再分别赋值给全局变量screenSize和screenRect。
定义一个比例因子(scale)这个变量来增加我们的应用程序中的元素。后面我们在物理交互中需要用到它。
render()函数内部主要是绘制的过程:
设置screenSize属性,确保我们准备好绘制了。然后保存画布。
调用scale()方法,设置缩放。使用屏幕的宽度除以比例因子,screenSize.width / scale,然后作为参数传入scale()方法。
使用translate()方法将画布的(0,0)点移动到屏幕中心位置。
使用drawCircle()方法,我们使用画图对象在(0,0)处绘制半径为0.1的圆
调用restore()方法将完成我们的渲染循环,仅显示一帧。
立即启动应用程序,应在屏幕中心附近绘制一个小圆圈,如下图所示:
最后我们把绘制部分的代码修改一下,加上重力传感器的代码,最终效果是这样的(具体的请进入Github查看源码),如下图所示:
五、源码及总结
最后来一点我的一些个人总结和说明:当然前面这些看似比较基础,但是只要你用心学习,多看看相关API介绍,也可以用它做其它的复杂的的游戏或其他功能,比如:连连看、俄罗斯方块、是男人就下100层、超级玛丽、愤怒的小鸟、接方块、摩拜单车APP的贴纸功能等。当然具体的业务逻辑需要你自己的思考,所有的具体业务功能点都是在核心API的基础之上不断完善的,这里只是给出一些可以研究的相关的方向,感兴趣的朋友们可以试着做一下,这里就不逐个列举了。
本文由我首发在公众号【Flutter那些事】,未经允许,严禁转载。更多干货,欢迎关注。
更多推荐
所有评论(0)