前面给大家介绍了Flutter 以及Flutter Web,接下来给大家带来一个更劲爆的知识点—— Flutter开发游戏。是的,没错,Flutter也可以用来开发游戏了。有人会问不懂Unity或者Cocos2d也能用Flutter开发游戏吗???是的,你没看错,Flutter就是这么666。

我在pub.dev上面找到了一些有关游戏的第三方开源库,使用它们你就可以轻而易举的实现你的游戏梦(你要说开发王者荣耀、吃鸡那种大型游戏的话就当我前面的话没说)。下面开始今天的干货分享。

作者写文章不容易,觉得好看的话,点个赞,支持一下吧,谢谢大家。另外我的专栏【Flutter&Dart】专门发布Flutter干货,欢迎大家关注:Flutter&Dart​zhuanlan.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那些事】,未经允许,严禁转载。更多干货,欢迎关注。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐