前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter&Flame游戏 - 玖】探索构件 | Component 是什么

【Flutter&Flame游戏 - 玖】探索构件 | Component 是什么

作者头像
张风捷特烈
发布2022-06-19 16:13:44
5610
发布2022-06-19 16:13:44
举报

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 10 天,点击查看活动详情


前言

这是一套 张风捷特烈 出品的 Flutter&Flame 系列教程,发布于掘金社区。如果你在其他平台看到本文,可以根据对于链接移步到掘金中查看。因为文章可能会更新、修正,一切以掘金文章版本为准。本系列文章一览:


1. Component 的树形结构

通过前面八篇的尝鲜,或说预热,我们可以感知到无论是主角、怪兽、文字、子弹、触点都是 Component 。它是游戏的基本构建模块,可以表示任何需要被渲染、更新的内容。


下面是 Component 类的部分结构,可以看出 Component 是一个普通类。其本身会持有父级构件,以及子级构件集合。也就是说 Component 本身是一个树形结构的节点类,认识到这一点至关重要。


正是由于树形结构的特点,Component 类有添加移除 构件的能力。如下所示,可以通过 add 方法添加子级构件,也可以通过 addToParent 方法,将自身添加到父级构件中。


前面介绍过子弹、怪物消失,使用的是 removeFromParent 方法。如下源码中可以看出,是调用父级构件 _parent 的移除方法,把当前构件对象从父级节点上移除:

代码语言:javascript
复制
---->[Component#removeFromParent]----
/// Remove the component from its parent in the next tick.
void removeFromParent() {
  _parent?.remove(this);
}
复制代码

2. Component 生命周期状态

Component 中有一个 _state 属性,其类型为 LifecycleState 枚举,用于表示构件的状态:

其中有如下 6 种状态,初始状态是 uninitialized ,表示未初始化,也就是构件实例化时的默认状态。前面知道构件中有个 onLoad 的异步方法用于加载资源,在执行异步方法的前一刻就是 loading 状态。该状态会持续到异步方法执行完毕,变成 loaded 状态。

代码语言:javascript
复制
enum LifecycleState {
  uninitialized,
  loading,
  loaded,
  mounted,
  removing,
  removed,
}
复制代码

Component 是树形结构的节点,当某个 Component 添加到父节点上后,就会变成 mounted 状态。相关代码如下所示:


另外当父级执行 remove 方法时,入参的子构件非 removing 状态时,会被加入到 lifecycle._removals 列表中,等待下帧触发时移除。此时该子构件的状态为 removing 。当构件被从父节点上移除后,其状态为 removed ,就变成了孤魂野鬼,等待被 GC 回收。

如下图是六种状态的转换示意图,其实还是比较清晰的。了解这六种状态,在下篇介绍 Component 生命周期方法时,就会更好理解。


另外 Component 中关于生命周期状态有三个 get 方法,这里介绍一下:

  • isLoaded:非 uninitialized 且非 loading 状态,表示异步加载任务是否已经完成。
  • isMounted: mountedremoving 状态,表示构件依然在树上。
  • shouldRemove: removing 状态,表示构件已被收集到移除列表中,将在下一帧中被移除。
代码语言:javascript
复制
---->[Component]----
bool get isLoaded {
  return (_state != LifecycleState.uninitialized) &&
      (_state != LifecycleState.loading);
}

bool get isMounted {
  return (_state == LifecycleState.mounted) ||
      (_state == LifecycleState.removing);
}

bool get shouldRemove => _state == LifecycleState.removing;
复制代码

3. Component 的衍生类

Flamecomponents 包中的文件,是对 Component 的衍生。其中一些 mixin ,比如 DraggableHoverableTappable 等都是依赖于 Component ,情理上来说也算是 Component 的衍生产物。


Component 大致可分为三大类,支持定位和变换的 PositionComponent 、附加效果的 Effect 、以及直接继承自 Component 的少数构建。

其中群体最庞大的是 PositionComponent ,这一族引入了 尺寸锚点位置旋转缩放 等属性,决定了该族构件将非常实用:

我们之前用的 SpriteComponentTextComponentSpriteAnimationComponent 等都是 PositionComponent 一族的。另外,自定义的子弹、主角、怪兽,也都是 PositionComponent


另外,Effect 一族定义在 effects 包中,我们在前面用到的 MoveEffect 就是这类的构件。在之后的学习中我们再深入认识其他的效果,或者自定义 Effects


4. 自定义 Component

前面的案例中我们也尝试过自定义 Component ,比如 AdventurerMonsterTouchIndicator 等。其实自定义 ComponentFlutter 中自定义 Widget 的功效类似,都是为了把一些通用的构成逻辑进行封装,以便复用和管理。

比如通过下面的 Monster 类,可以生成多个怪兽对象:可以定义不同的帧序列和生命值,它们对于玩家来说就是两个不同的怪兽。对于编程者而言它们都是通过 Monster 构建类实例化的对象,本质没有什么区别。代码详见 【09/01】

https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/543581e81c244a9e9166f019da6665ab~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?

代码语言:javascript
复制
class Monster extends SpriteAnimationComponent with Liveable {
  final double life;
  Monster({
    required SpriteAnimation animation,
    required Vector2 size,
    required Vector2 position,
    this.life = 4000,
  }) : super(
          animation: animation,
          size: size,
          position: position,
          anchor: Anchor.center,
        );

  @override
  void onDied() {
    removeFromParent();
  }

  @override
  Future<void> onLoad() async {
    initPaint(lifePoint: life);
  }

  void move(Vector2 ds) {
    position.add(ds);
  }
}
复制代码

另外,通过自定义构件类,可以覆写 Component 的相关回调方法,监听相关状态,处理逻辑。这里先对 Component 认识到这里,下一章我们将信息探讨一下 Component 的生命周期回调。那时你就会对 Component 有一个更深的认知,那么本文就到这里,明天见 ~

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. Component 的树形结构
  • 2. Component 生命周期状态
  • 3. Component 的衍生类
  • 4. 自定义 Component
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档