前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter&Flame 游戏 - 贰柒】pinball 源码分析 - 角色选择与玩法面板

【Flutter&Flame 游戏 - 贰柒】pinball 源码分析 - 角色选择与玩法面板

作者头像
张风捷特烈
发布2022-09-09 10:23:03
9770
发布2022-09-09 10:23:03
举报
文章被收录于专栏:Android知识点总结

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


前言

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


1. 选择角色介绍

上一篇介绍了主界面布局结构的源码实现,本篇继续来看。在点击 Play 按钮之后,背景的游戏界面会有一个移动和缩放的特效,让游戏主题面板填充屏幕。并且会展示角色选择的面板,效果如下:

*注* :为了减少 gif 的大小,生成时采用 6fps ,所以实际效果要你下图流畅很多。


在选择对应的角色图标时,背景会进行对应的变化。很明显,在两个不同界面中的数据需要共享,很自然就会想到使用 状态管理


通过查看资源图片的位置,不难发现,这里四种角色主题是在 pinball_theme 中提供的。也就是说,pinball 项目中,对这个小模块进行了分包处理。可以思考一下:这个模块是相对独立的,而且有一定的拓展需求,比如增加其他的角色,可以在该包在进行处理。而不是全部塞在主项目中,这样有利于对项目结构的划分,也能让读者更容易理解。

不过仔细看一下这个包,会发现其中只是定义主题的数据,被抽象为 CharacterTheme,四种主题便是 CharacterTheme 的实现类。


比如下面的 AndroidTheme 继承自 CharacterTheme ,实现相关资源的 get 方法,其他的主题也是类似。也就是说,如果需要增加一个主题角色,可以自定义 CharacterTheme 的实现类。


2. 角色选择的业务逻辑

从上面可以看出,pinball_theme 包中,只是定义主题的数据类型,并未涉及业务逻辑视图变化 。跟随 CharacterTheme 这条显示,很容易可以定位到它的使用场景。如下,在主项目的 select_character 文件夹下,盛放着角色选择的相关文件。cubit 是业务逻辑的处理,view 是视图的呈现。

可以看出 CharacterThemeCubit 非常简单,维护着 CharacterThemeState 状态数据,只有一个 characterSelected 事件,根据入参选择的角色,产出新的状态数据。其中 CharacterThemeState 状态数据也非常简单,只维护了一个 CharacterTheme 成员和四个 get 方法方便获取激活的主题。


默认情况是 DashTheme ,想要知道角色主题是何时切换的,也非常简单。因为使用了Bloc ,业务逻辑封装了,使用统一的事件接口触发。这里只需看一下何时触发 characterSelected 方法即可。这就是业务分层所带来的的好处之一。


3.角色选择的视图变化

如下,在 _Character 组件点击时,是唯一触发 characterSelected 的场景。这里的 _Character 组件就是右边可点击的圆形角色头像,其中需要传入 CharacterTheme 对象和 isSelected 是否被选中。从 build 逻辑中可以看出:选中时,透明度是 1 ,否则是 0.4 ,这和实际操作是吻合的。


角色选择的界面主体内容是中间的 Row ,包含 _CharacterPreview_CharacterGrid 组件,且平分水平方向空间。


_CharacterPreview 组件是角色的预览,它会随着右侧角色的选择而发生变化。所以这里通过 BlocBuilder 让组件跟随 CharacterThemeState 的变化而重新构建。这里对 SelectedCharacter 组件进行抽离,因为其内部需要进行动画,封装之后独立性较好,表意也更明确。


这里通过 SelectedCharacter 组件进行展示某个角色,主要就是一个 Column 的上下结构。下方不断运动的序列帧通过 SpriteAnimationWidget 进行展示。这样选择角色的界面和处理逻辑就介绍地差不多了,至于背景的贴图如何变化的,在后面分析主场景再进行介绍。

其实如果不创建 _CharacterPreview ,直接在 SelectedCharacter 中使用 BlocBuilder ,或直接在 定义一个方法 返回 _CharacterPreview 中组件,在功能上是没有什么区别的。好处是少了一个类,坏处是看起来代码比较杂糅,表意性不是太好。这也没有什么定式,大家根据自己的喜好,斟酌选择即可。

程序的最终目的是实现需求,像先迈左脚,还是右脚;用袋子装鸡蛋,还是用篮子装鸡蛋;喝可乐开还喝绿茶;这并不会影响最终的目的。结合场景和个人的喜好即可,并没有必要强制必须如何如何。没必要画个圈,或让别人给你画个圈,把自己的行动范围定死,这点思考和选择的能力还是要有的。


4. 玩法介绍面板

在选择完角色之后,会弹出 How to Play 的面板,介绍玩法。可以看出这个对话框的整体结构和上面角色选择是一致的,这个对话框是源码中的 PinballDialog 组件。


玩法介绍地面板,是的 HowToPlayDialog 组件呈现的,他是一个 StatefulWidget 。因为其中有一个自动消失的需求,如红框所示,通过 closeTimer 开启一个 3 s 的延迟任务,来让对话框消失。


对话框界面的构建逻辑如下,显示的主体是 PinballDialog 对话框,对话框的内容会根据 是否是移动端 进行适配。原因很简单,移动端通过点击屏幕,桌面端通过按键触发事件 ,玩法是有区别的。


代码中对界面的分层处理是很值得借鉴的,而不是把所有的构建逻辑写在一块。抽离组件可以让整体结构更加清晰,比如下面的红框中,代码的组件和界面的呈现,两者的对应关系非常清晰。源码中的处理方式,特别是官方提供的源码,是非常值得学习和借鉴的。能将这些思想消化吸收,应用到实际开发中,是有益的。


最后,来看一下 HowToPlayDialog 是如何显示出来的,也就是触发的时机。查看一些 HowToPlayDialog 组件的使用情况,很容易可以定位到 start_game_listener.dart 中。

_onHowToPlay 私有方法中,进行展示 HowToPlayDialog 对话框。所以关键就是该方法的触发时机:


StartGameListener 中,会监听 StartGameState 状态的变化,如果是 howToPlay 状态,则会触发 _onHowToPlay 方法,显示玩法对话框。从这里可以看出 Bloc 处理可以根据状态来构建组件,也可以监听状态的变化,进行逻辑处理。


StartGameBloc 中,CharacterSelected 事件会将状态值变为 howToPlay 。另外在选中角色后,会触发 CharacterSelected 事件,这就是HowToPlayDialog 对话框显示的整体逻辑。


本文介绍了 pinball 游戏的角色选择玩法介绍 两个模块。从中可以看出 bloc 在状态数据共享,以及状态变化监听中的价值。下一篇,我们将进入最重要的游戏主界面,那本文就到这里,明天见 ~

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. 选择角色介绍
  • 2. 角色选择的业务逻辑
  • 3.角色选择的视图变化
  • 4. 玩法介绍面板
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档