将DuckHunt与ARKit结合使用? -第2课:增强应用程序的体系结构

故事作者: nomtek的 iOS开发人员 Wojciech Trzasko

您可能还记得,最近我们从事了一个将经典NES游戏与我们的现实结合起来的小项目……哦,您不记得了吗? 没问题,这是一个偷偷摸摸的小故事,可以刷新您的记忆:

你还不记得吗 请查阅上一课,其中定义了Entity-Component-System模式和VIPER体系结构的基础。

目前,我们已经掌握了使用ECS模式为实时应用程序设计架构的知识,这与ARKit的经验非常吻合。 我们还了解了称为VIPER的广泛使用的iOS应用程序体系结构的基础。 因此,现在我们需要弄清楚如何连接这两个不同的世界。

为什么这两个有很大不同?
一方面,我们将ECS与ARKit相结合,该技术处理图像数据并基于结果提供实时信息。 在另一端,我们将使用以UIKit和VIPER架构为代表的基于事件的经典基础架构。

现在,该是最难的部分了。 如果有AR经验,我们将处理实时信息,而不是基于事件的基础结构。 现在,如果我们看一下经典的VIPER层,则演示者和交互者不太合适。

你是对的! 我们将尝试用ECS设计模式替换这些层。 为此,我们需要将用户的交互和对update方法的调用传递给ECS,但是由于ARKit和SceneKit的性质,此任务有些棘手。 要构建基于SceneKit的体验,您需要使用实现SCNSceneRenderer协议的对象。 对于AR场景,Apple提供了默认的AR渲染器实现,称为ARSCNView ,该渲染器将游戏逻辑和增强现实回调(例如updateAtTimedidSimulatePhysicsAtTimedidAddNodeForAnchor )返回给其委托。 因此,对于我们的ECS实施至关重要的所有回调,都将由严格连接到视图层的对象返回。 这是一个很大的障碍,如果我们不想实现自己的渲染器,则需要弄清楚如何处理它。

使它起作用的最简单方法是,从其大部分职责中裁剪视图图层并使其尽可能简单。 在我们的DuckHunt演示中,我们仅使用视图控制器对象来收集用户输入和所有逻辑回调,然后将它们传递给两个附加层: SceneGameplay 。 他们俩甚至都不知道视图的存在。 所有通信都通过这些层共享的接口进行。

那么,这两个新层的职责是什么?

Scene是从SCNScene继承的类。 它加载并保存放置在世界上的3D对象图。 而且,它允许通过将动态对象公开来操纵它们。 游戏性是发生所有魔术的地方。 在这里,我们将介绍我们的ECS实施。 通常,它引用了我们的场景,并处理了世界上对象之间的所有交互。

让我们来看看DuckHunt游戏中的hunt模块。 HuntScenescene.scn文件加载将在玩家周围显示的世界。 然后通过其公共界面共享鸭子生成点列表和一个其他节点。 我们允许HuntGameplay使用此节点为新生成的鸭子实体添加几何。 然后,我们将管理和确定系统顺序的逻辑从ECS模式转移到称为EntityManager的单独类。 因此,在他的最终形式中, HuntGameplay通过从EntityManager调用update来从View获取更新回调并将其传递给实体,然后根据需要生成新的Duck。 最后,它检查获胜条件。 如果满足,则要求线框移至下一个场景。

因此,如果您更深入地研究新层,您会发现与经典VIPER方法有些相似之处。 就像VIPER的视图等待演示者提供要显示的内容一样, 场景也等待游戏过程来确定世界上对象的新位置。 主要区别在于我们允许我们的游戏玩法向场景添加新的几何体。 这可能是我们可以进行进一步改进的第一个地方。 与其为每个生成的鸭子实体添加新的几何图形,我们只能创建一个几何图形并尝试重用它。 通过向世界添加一个空飞机,然后通过“ 场景”界面使其可用,可以轻松实现这一点。

它绝对可以使我们达到更高的抽象水平,但是在丰富的游戏玩法中仍然可能会出现问题。 例如,假设在下一个发行版中,我们的客户希望生成更多的敌人类型。 对每种类型重复使用相同的几何图形可能是一项艰巨的任务,或者需要添加一些更高级的算法。 因此,由您决定采用哪个版本,哪个版本更有效地满足您的要求。

老实说,是的!

为了感谢您的耐心,我们提供了该项目的开源版本的链接。 您可以从这里获取它:https://github.com/nomtek/DuckHuntAR

因此,我们向您展示了为基于ARKit的体验准备架构的第一个实验。 完美吗? 一定不行!

这个主题还有很大的改进空间。 也许您已经知道要更改什么? 在评论中分享您的经验!

伙计们,让我们保持联系!