持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 26 天,点击查看活动详情
前言
这是一套 张风捷特烈 出品的 Flutter&Flame 系列教程,发布于掘金社区。如果你在其他平台看到本文,可以根据对于链接移步到掘金中查看。因为文章可能会更新、修正,一切以掘金文章版本为准。本系列源码于 【toly_game】 ,如果本系列对你有所帮助,希望点赞支持,本系列文章一览:
- 【Flutter&Flame 游戏 - 壹】开启新世界的大门
- 【Flutter&Flame 游戏 - 贰】操纵杆与角色移动
- 【Flutter&Flame 游戏 - 叁】键盘事件与手势操作
- 【Flutter&Flame 游戏 - 肆】精灵图片加载方式
- 【Flutter&Flame 游戏 - 伍】Canvas 参上 | 角色的血条
- 【Flutter&Flame 游戏 - 陆】暴击 Dash | 文字构件的使用
- 【Flutter&Flame 游戏 - 柒】人随指动 | 动画点触与移动
- 【Flutter&Flame 游戏 - 捌】装弹完毕 | 角色武器发射
- 【Flutter&Flame 游戏 - 玖】探索构件 | Component 是什么
- 【Flutter&Flame 游戏 - 拾】探索构件 | Component 生命周期回调
- 【Flutter&Flame 游戏 - 拾壹】探索构件 | Component 使用细节
- 【Flutter&Flame 游戏 - 拾贰】探索构件 | 角色管理
- 【Flutter&Flame 游戏 - 拾叁】碰撞检测 | CollisionCallbacks
- 【Flutter&Flame 游戏 - 拾肆】碰撞检测 | 之前代码优化
- 【Flutter&Flame 游戏 - 拾伍】粒子系统 | ParticleSystemComponent
- 【Flutter&Flame 游戏 - 拾陆】粒子系统 | 粒子的种类
- 【Flutter&Flame 游戏 - 拾柒】构件特效 | 了解 Effect 体系
- 【Flutter&Flame 游戏 - 拾捌】构件特效 | ComponentEffect 一族
- 【Flutter&Flame 游戏 - 拾玖】构件特效 | 了解 EffectController 体系
- 【Flutter&Flame 游戏 - 贰拾】构件特效 | 其他 EffectControler
- 【Flutter&Flame 游戏 - 贰壹】视差组件 | ParallaxComponent
- 【Flutter&Flame 游戏 - 贰贰】菜单、字体和浮层
- 【Flutter&Flame 游戏 - 贰叁】 资源管理与国际化
- 【Flutter&Flame 游戏 - 贰肆】pinball 源码分析 - 项目结构介绍
- 【Flutter&Flame 游戏 - 贰伍】pinball 源码分析 - 资源加载与 Loading
- 【Flutter&Flame 游戏 - 贰陆】pinball 源码分析 - 游戏主菜单界面
- 【Flutter&Flame 游戏 - 贰柒】pinball 源码分析 - 角色选择与玩法面板
- 【Flutter&Flame 游戏 - 贰捌】pinball 源码分析 - 游戏主场景的构成
- 【Flutter&Flame 游戏 - 贰玖】pinball 源码分析 - 视口与相机
第一季完结,谢谢支持 ~
1. 加载界面在哪里
pinball 在游戏开始时,会显示资源加载的界面,是一个加载的进度条,如下所示。那问题来了,如何定位这个界面在源码中的位置。这样才能有机会分析资源加载的代码:
从一些外在表征去定位源码,是一个非常有用手段,比如在资源文件中可以看出 loading_game 的文件夹,其中包含着 io_pinball.png 的图片。这就说明只要找到什么地方使用了 io_pinball.png,就可以发现相关视图处理的代码逻辑
全局搜索一下,就不难发现,该图片名称在 lib/gen/assets.gen.dart 中被使用:
点进去可以看到该文件是通过工具自动生成的资源管理代码,ioPinball 代表这个图片资源:
然后 顺藤摸瓜 ,就可以找到图片资源使用的场景,这就像根据线索来探查真相。现在知道一开始加载的界面的代码在 lib/assets_manager/views/assets_loading_page.dart 中。这样我们就能通过源码来分析一下界面实现的逻辑,包括界面如何布局,进度如何变化等。
2. 加载界面 - 背景与图片
加载中的布局主要右四个部分组成,分别是 背景 、图片 、Loading 文字以及 进度条 :
在上面可以看出,图片本身背景是透明的,所以背景中的横线条纹在源码中一定有其出处:从界面组件 AssetsLoadingPage 的实现中可以看出,背景是通过 CrtBackground 装饰进行绘制的。其实这里的 Container 没有使用其他属性完全可以换成 DecoratedBox 组件,更加轻便:
这里的选择是自定义子类集成自 BoxDecoration,感觉并没有太大的必要性。直接使用 BoxDecoration 指定 gradient 参数就行了,不过也无伤大雅。
1 | dart复制代码class CrtBackground extends BoxDecoration { |
这里的图片组件是通过 ioPinball 对象调用 image() 方法获取的,其实这就是自动生成的代码给的一个形式语法糖。
1 | dart复制代码Padding( |
ioPinball 类型为 AssetGenImage ,是一个 ImageProvider ,也就是 Image 组件在需要传入的 image 参数类型。该类中的 image 方法,提供了构造 Image 所需的可选属性,返回 Image 组件。并将自身作为构造 Image 组件的 image 入参:
也就是说,下面的两种写法是等价的,只不过上面在的写法不需要嵌入在 Image 组件下而已。本质上没有什么区别,只是简化书写形式而已:
1 | dart复制代码Assets.images.loadingGame.ioPinball.image() |
3. 加载界面 - 加载中文字与指示器
如下所示: Loading 文字三个点会依次出现,是个循环动画。另外加载进度通过下面的指示器来显示,整个加载中界面的 业务逻辑 只有一个: 加载进度值的计算。
Loading... 的循环动画是通过 AnimatedEllipsisText 组件实现的,这个组件感觉挺实用。如果以后有需要,可以直接拷贝过去用,这就是 Flutter 组件化的好处。
简单瞄一眼源码,这里 ... 不断运动的动画,是通过 Timer.periodic 周期触发定时器实现的,每 500 ms 触发一次更新。由于这里是单独抽离的 AnimatedEllipsisText ,所以 setState 也只是局部的组件更新,不会影响触发外界组件的重新构建。
最后,是加载页最核心的业务逻辑,该项目是通过 flutter_bloc 来进行状态管理的。这里使用 AssetsManagerCubit 来维护加载资源的逻辑,其中状态数据是 AssetsManagerState ,该状态量可以获取加载的进度。这里通过 BlocBuilder 来监听状态的变化来构建组件。
从代码中可以看出,这个像素风格的进度条,通过 PinballLoadingIndicator 组件进行显示。构造中传入进度值,红色的区域就会占据相应的百分比。
从 PinballLoadingIndicator 组件的源码实现中可以看出,这个像素风格的进度条是通过六个 _InnerIndicator 组件进行显示的。仔细数一下上图,就会发现整体是由六个细条,从上到下排列的而构成的。
4. 资源加载的业务逻辑
上面我们知道,资源加载的核心逻辑以及过程中的进度状态数据,是由 AssetsManagerCubit 进行维护的。如下,在 lib/assets_manager 文件夹中管理着资源加载的 bloc 业务逻辑和 views 视图:
下面我们就进入 AssetsManagerCubit ,来看一下资源是如何加载的,以及进度状态的产出。AssetsManagerCubit 构造时需要传入如下两个对象,其中只有一个 load 异步方法,本身还是比较简单的。
这个 load 方法,会在 AssetsManagerCubit 构造时被立刻触发:
load 方法在有一个小细节,一开始延迟了一秒钟才开始真正加载,这是因为加载是个昂贵的操作,先给出 1s 的时间,让 UI 先展示出来,然后再真正进行加载资源。这里加载资源的异步任务通过 loadables 列表进行维护:
异步操加载资源的任务,被定义在个个模块中。比如 _game.preLoadAssets() 方法,会返回所有构件图片资源加载的异步方法,其他几个也是类似。当你看到源码的这么多资源加载的异步方法,就会明白为什么这个 load 会是昂贵的。
然后通过 _triggerLoad 局部函数对象,分三波依次触发这些异步任务。每次异步任务完成时,都会产出新的状态,让已加载的资源数加一。
这样状态数据中的进度值 progress 就会变化,整个加载的小体系就得以运转,从业务逻辑到视图更新展示,可以体会一下,bloc 在其中的角色,品味一下状态管理的价值。
到这里,pinball 首次进入时资源加载,以及进度的显示流程就介绍完毕了。那本文就到这里,明天见 ~
@张风捷特烈 2022.06.21 未允禁转我的 公众号: 编程之王我的 掘金主页: 张风捷特烈我的 B站主页: 张风捷特烈我的 github 主页: toly1994328
\
本文转载自: 掘金