GameplayKit:超越游戏

苹果公司将GameplayKit宣传为“为构建游戏提供基础工具和技术的框架” ,这是一个出色的框架。 但是这里有很多解决方案,在构建任何其他应用程序时都可以完美使用。 我想描述一下那些在Bikemap中广泛使用的方法: 空间分区,状态机,规则系统和随机化。

四叉树的空间分区

四叉树用于组织二维空间中的空间数据。 在四叉树中,每个级别的每个节点都分为四个象限,如下所示。 当一个象限包含多个对象时,该树将该区域细分为四个较小的象限,从而在树上添加一个级别。

Bikemap应用程序可处理自行车路线,并且每个路线都有数百甚至数千个坐标。 当用户导航到轨道的最近点时,或者当显示或调出导航指令时,业务逻辑严重依赖于四叉树。

所有路线坐标,指令,POI都添加到树中,并且随着状态机的每次更新(请参见下文),都在树中查询要显示的项目和用户周围的项目。 例如,如果路线很长,则仅渲染屏幕上可见的多边形。 此外,如果用户在某个POI或曲目的结尾附近,则可以添加通知。

四叉树非常非常快。 在具有100,000个对象的树中查找最近的元素大约需要0.022秒。

尽管Apple有自己的实现,但其使用受到限制(例如,不搜索最近的元素)。

因此,我们最终实现了自己的四叉树。

它带有:

  • 可自定义的像元大小和最大深度,
  • 最近元素搜索,
  • 过滤特定类型的对象并
  • 使用CoreLocation,MapKit和Mapbox的几种便利方法。

状态机

GKStateMachine是一个有限状态机,是状态对象的集合,每个状态对象定义了应用程序或屏幕的特定状态以及在这些状态之间进行转换的规则的逻辑。

对于游戏而言,很容易举一个例子:平台游戏的主要角色具有不同的状态,例如奔跑,跳跃,摔倒等。所有这些状态均具有不同的视觉效果,身体动作,声音等。 对于健身应用而言,事实证明,它有很多可能的用途。

Bikemap导航屏幕是一个非常复杂的屏幕。 有不同的导航模式,包括暂停,记录等,并且有一组严格的条件可以指示何时显示哪个UI元素和顺序。 用“ if-else”和“ switch”在视图控制器中完成所有工作将是一场噩梦。

取而代之的是,为每个状态定义不同的GKState,并在其中分别管理UI元素和其他业务逻辑:计划,搜索,导航,暂停,完成巡回等。

视图控制器保存状态机,并且在该机器中定义的每个状态都具有对视图控制器的引用,因此可以访问所有视图组件。 控制器保持清洁,因为所有逻辑和特定功能(例如语音合成器)都外包给了该州。

状态机需要不断的更新,因此每2秒钟或在有新的位置数据可用时,将使用计时器对其进行更新。

在状态内,可以指定进入状态时和退出状态之前要运行的逻辑。 这些方法可用于设置,修改UI并为将其移交给下一个状态做准备。

最终,这是关于组织代码并使同一屏幕的所有不同版本(状态)在独立文件中作为独立逻辑。

规则系统

大多数应用程序的组件具有如此特殊和复杂的逻辑,以至于实现变成了else-if-guard-return-switch地狱。

例如,在“ Bikemap路线详细信息”屏幕上:仅当用户在线或离线但为高级用户且路线在一定距离内时,才会显示“导航”按钮; 并且该距离也取决于可到达性,并且如果离线,则必须先下载该路线,当然,如果其中没有足够的坐标,则可能无法导航。

规则系统在这里使死亡变得简单。 在规则系统中,有两个事实: navigableRouteofflineNavigableRoute 。 然后将上述条件(规则)添加到系统中,以断言撤消这些事实。 如果用户离线,则将navigableRoute撤回(到0),如果用户也高级, 则将offlineNavigableRoute断言(到1)。

将所有规则添加到系统后,将对其进行评估。 每条规则都运行,最后得出两个事实的等级: 01 。 然后,在控制器中,所有要做的就是将成绩读为布尔值并相应地修改UI。

最好的是,使用规则系统可以创建模糊逻辑。 等级可以是0到1之间的任何值。因此,例如,如果有80%的机会满足其条件,则可以显示某些内容。

+1随机化

使用GameplayKit生成随机数非常简洁,非常方便。

这是有关GKRandom潜力的精彩文章。