Flutter使用Flame游戏引擎开发实现(-)

再说一次,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 刘海屏适配:

参考:Flutter 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。

参考:Flutter Tips - MediaQuery;

使用MediaQueryData.fromWindow(window)获取window的信息,这样来获取上下边界信息。

topPadding = MediaQueryData.fromWindow(window).padding.top;

bottomPadding = MediaQueryData.fromWindow(window).padding.bottom;

你可能感兴趣的:(Flutter使用Flame游戏引擎开发实现(-))