再说一次,Flutter非常的牛,数年前用IOS原生想要写一款蚂蚁攻防的二维游戏,但是复杂的Object-C开发到一半,觉得逻辑混乱复杂,画面也不自然。于是不得不放弃。
当最近认识了Flutter以及跨平台的开发时,不禁萌生了再次使用Flutter来完成这款游戏的想法,先后了解了Flame和SpriteWidget游戏引擎,由于Flame相对多一点说明,因此决定采用Flame进行开发,关于SpriteWidget也是可以实现的,貌似功能更丰富,但是好像没有再更新了。
Flame开发游戏可以参考以下说明和Demo:
1. Create a Mobile Game with Flutter and Flame – Beginner Tutorial
2. 中文翻译(有空继续)- Flame开发Flutter游戏 (二)
3. Github Demo - japalekhin/langaw
4. Github Demo - flame-engine/trex-flame
如果仅仅制作一个类似于langaw的小型游戏,参考Tutorial和langaw就够了,但是稍微复杂一些的游戏,就不能够使用Game类,需要使用BaseGame类,使用Components,相对来讲,位置的相对计算,render,components.add, 以及update的使用,就需要搞清楚相互的关系。然后Flame说明比较简单,能找到的资料也非常有限。
通过在开发中遇到的问题,记录一下Flame的一些游戏中用到的场景如何实现,绝对原创,目前绝无仅有,全互联网唯一。
(-)旋转的物体
参考Flame Issue #90给出了完整的旋转一个方块的方法,注意prepareCanvas(c);原理是为旋转目标准备canvas,尺寸大小为目标大小,然后update改变目标的angle,当然角度改变按照anchor来进行。
Square(double size, this.rotate) {
width = height = size;
anchor = Anchor.center;
}
@override
void render(Canvas c) {
prepareCanvas(c);
c.drawRect(Rect.fromLTWH(0, 0, width, height), Palette.white.paint);
c.drawRect(Rect.fromLTWH(0, 0, 3, 3), Palette.red.paint);
c.drawRect(Rect.fromLTWH(width / 2, height / 2, 3, 3), Palette.blue.paint);
}
定义对象时,定义一个width = height = size;然后在render方法中从(0, 0, width, height)绘制对象,这样改变angle就可以进行旋转,如果不是这样,会按照你定义的整个对象类尺寸进行旋转。
这样就有几个问题,1,如何将这个类变成PositionComponent?;2, 如果对象是Sprite或者动画AnimationComponent,又如何旋转?3, 如果添加多个对象在一起,如何旋转?
下面就是我的心得体会,当然中间也踩了很多坑,做了很多测试。
(待续)
Flame的生命周期:
参考Flame Issue#16 ,可以在对于BaseGame或者Game通过设备App的lifeCycle进行控制:
@override
void lifecycleStateChange(AppLifecycleState state) {
if (state != AppLifecycleState.resumed) {
// pause your updates
// pause all audio players
} else {
// resume your updates
// resume all audio players
}
}
The Game class has a listener for changes in the app lifecycle, which can hook to resume and paused. You can also stop your update logic with a flag variable as well, so that your game doesn't update while on background.
Game类有一个app的lifecycle的监听,可以用来处理resume/paused的状态转换。你可以使用一个标签参数来停止你的upate逻辑,这样你的游戏就不会在后台继续更新。
IphoneX 刘海屏适配:
final double topPadding = MediaQuery.of(context).padding.top;
final double bottomPadding = MediaQuery.of(context).padding.bottom;
如果使用的是自定义布局的话, Flutter 提供了媒体查询的接口, 可与获取到上边距和下边距的值。
上边距在 iPhoneX 上的值是 44, 在其他设备上的值是 20, 是包含了电池条的高度的。
下边距在iPhoneX 上的值是34,在其他设备上的值是 0。
现在Flutter出了一个新的Widget,叫做 SafeArea , 直接在外面包一层这个Widget, 就可以让子Widget 不会被刘海覆盖了。
MediaQuery可以建立widget查询解析给定的子树。但是对于Flame,不是简单的widget,上面方法使用时无法输入context。
使用MediaQueryData.fromWindow(window)获取window的信息,这样来获取上下边界信息。
topPadding = MediaQueryData.fromWindow(window).padding.top;
bottomPadding = MediaQueryData.fromWindow(window).padding.bottom;
网友评论