【Flutter&Flame 游戏 - 贰捌】pinball 源码分析 - 游戏主场景的构成

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


前言

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


1. 游戏主界面的构成

通过前面四篇,我们分析了 pinball 项目的整体结构,以及资源加载、主菜单、角色选择和玩法介绍等面板。最后剩下最重要的一块,就是游戏的主界面,主要包括六个部分:背景发射器轨道小球碰撞得分物 以及底部 摆动挡板 ,其中最复杂的是各种碰撞体角色。


上面提及的游戏主界面构件,基本上都定义在 pinball_components 中。这也是 pinball 项目中文件最多,结构最复杂的包。

对游戏主界面的构成分析,也就是看这些构件以什么类型,如何分布在游戏场景中。下面我们就来一一介绍场景中的几个部分。


2.背景构件

主界面最吸引人的是表面有一定的 透视感深度感 ,这样就形成了一个视觉上的立体空间。其实看到资源图片就会知道,这只是图片本身的效果,并非真正的 3D 模型。


如下是背景图片资源,可以看出,图片本身就是带有透视效果的。另外背景图片的边缘是比较随意的,因为它只是一个背景,在其周围会有相关的覆盖物。

扫描二维码关注公众号,回复: 14315021 查看本文章

对资源进行定位,很容易知道背景图的使用场景,如下是资源管理工具会生成 boardBackground 方法应用获取背景图片:

接下来继续追踪,可以看到在 board_background_sprite_component 文件中使用到了背景资源。在分析代码时,根据细微的线索去追踪有价值信息,是一件非常有趣的事。我们面对复杂的源码体系,寻找合适的切入点非常重要,没有必要一开始就硬啃核心代码处理逻辑。从周边入手,一层层剥离外围,找出线索,逐步深入,是一个很好的研究方式。


如下,就定位到了背景所对应的构件 BoardBackgroundSpriteComponent 。其中在 onLoad 方法中通过背景图片资源,为 sprite 成员赋值,并且尺寸是原图的十分之一。


紧接着,可以继续追踪 BoardBackgroundSpriteComponent 的使用场景。如下,它在 PinballGameonLoad 方法中被加入到场景中:


2. 地板构件和小球构件

在背景的底层,可以看到有个 ArcadeBackground 组件,它对应的就是最底层的地板。我们上一篇说过,这个地板会随着选择的角色而变化,这里就来看一下其中的原因。

另外有一个小细节,在移动端是没有地板的,整个视口都是游戏面板。毕竟移动端是竖屏的,没有空间显示更多内容。


如下所示,主要显示的内容由 ArcadeBackgroundSpriteComponent 觉得,他会监听 ArcadeBackgroundState 的变化。在新状态产出时,会更新 sprite 成员对应的图像。

可以看出,这里的地板的图片资源是定义在 CharacterTheme 中的,每个实现类都有相关的资源图片。比如下面是 android 对应的资源,这样就不难理解为什么角色的变化,会让地板图片产生变化。


接下来,最后一个问题,选择角色主题的逻辑是由 CharacterThemeCubit 完成的,产出的是 CharacterThemeState。而这里源码是监听的是 ArcadeBackgroundState 状态,对应的是 ArcadeBackgroundCubit ,这显然是两个不同的 Bloc 。那这两者是如何产生关联的呢?也就是说选择角色时,CharacterThemeState 的变化如何通知到 ArcadeBackgroundCubit

ArcadeBackgroundCubit#onCharacterSelected 事件为线索,不难定位到:在 CharacterSelectionBehavior 中,会监听 CharacterThemeState 的变化,来触发 ArcadeBackgroundCubit 的事件,产出新的 ArcadeBackgroundState ,从而促使地板进行切换图片资,这个逻辑搭建可以梳理一下。


另外,从上面代码可以发现,小球 Ball 构件,也会受到角色主题的影响。仔细观察也不难发现,不同的角色主题,对应的小球颜色是不同的:

dash android sparky

通过查看 BallSpriteComponent 中逻辑的,可以知道小球构件会监听 BallState 的状态,来更新图片资源,而该资源就是定义在主题类中的。

比如 dash 主题对应的是小蓝球:

当用户选择某个角色主题,在 CharacterSelectionBehavior 中触发 onNewState 。如下红框在会寻找 Ball 对应的 BallCubit 来触发 onCharacterSelected 事件,产出新状态。从而更新小球的图片资源,这和地板的资源变化是一个道理。


3. 边界构件: Boundaries

在背景的上面是 Boundaries 构件:

从构件的定义中,很容易看出三个部分分别对应 boundary 文件夹中的三个图片。可以发现 pinall 项目无论是对 Flutter 中的组件,还是 Flame 中的构件,抽离分层的处理还是很细致和到位的。


通过图片资源可以看出,Boundaries 就是对背景之上的边界进行处理。比如左图的外框,中间是镂空的透明色,将背景图叠在其下,就可以遮住上面背景四周的部位。这样在视觉上就能营造出一种立体效果。


4.发射台构件:Launcher

Launcher 构件主要包括三个部分:发射杆发射台轨道 。如下是三个部分的示意:

从资源中可以看出,发射台轨道挡板 这些都是独立的资源。通过在主界面上拼接,进行组合,呈现的整体视觉效果。

如下 Launcher 构件在有四个子构件, LaunchRamp 是轨道、Plunger 是发射杆、RocketSpriteComponent 是发射台。另外 Flapper 构件用于处理边界,限制小球在外壁之内,试了一下,如果把下面的 Flapper 注释掉,小球就会飞出边界之外。 对于可以运行的代码,当我们不提明白一处的作用,可以将其屏蔽掉,看一下前后的差异,从而认识某个模块的作用。


5. 碰撞体

另外还有很多小的障碍物,用于碰撞后得分,这里就不一一细看了。在处理上都比较类似,可以根据资源中的图片来定位到相关的构件。


比如右侧中间的小恐龙,在游戏中会一直动,这对应的资源是 dino/animatronic 下的序列帧:


可以根据资源名称,追踪到 DashAnimatronic 构件,它是一个 SpriteAnimationComponent 。其中序列帧的资源使用的就是上面的图片:


底部可以摆动的两个挡板资源图片在 flipper 文件夹下,对应的构件是 BottomGroup ,包含左右两个_BottomGroupSide 构件。

整个游戏主界面的结构就介绍到这里,另外关于小球碰撞的相关处理,pinball 中使用的是 flame_forge2d ,我目前还没有研究,就先不分析了。下一篇,我们来看一下 Flame 中视口和相机的概念,并结合 pinball 中对相机的使用来实际体会相机的作用。那本文就到这里,明天见 ~

\

猜你喜欢

转载自juejin.im/post/7112666683658993701
今日推荐