使用SpriteKit以每秒9.8分钟的速度学习重力

当我们经常看到各种具有落物和碰撞检测等功能的游戏时,我们可能会自己想,将此功能打包到我们自己的应用程序中必须多么复杂。 但是,我正在写这篇文章,向您展示如果您了解SpriteKit的方法,它有多么简单。 如果您不这样做,请不要担心,只需遵循以下步骤。 我们将构建一个利用这两个功能的小型应用程序。 成品看起来像这样。

我将在此应用程序后面提供整个代码,因此请随时关注Xcode。 如果要这样做,您将想要找到一个带雨伞和雨滴的人的图像,并将其添加到资产文件夹中。 我将一路为您介绍有关重力或碰撞检测的任何代码。 首先,打开Xcode并选择New Project-> Game。 取消选中纵向模式,则该应用将仅横向运行。 完成此操作后,请转到GameScene.swift文件。 它附带了Apple已构建的默认应用程序,删除了GameScene类的整个主体。 完成后,您的班级应该看起来像下面的代码片段。

现在,让我们将以下空函数添加回该类。 在整个教程中,每个代码块都将填充有代码块。

创建一个名为RainDrop的新swift文件。 在初始化程序中,我们需要确定其生成位置,大小和图像。 我们还需要将PhysicalBody应用于该节点。 您将在下面的代码片段以及该类的其余部分中看到应用此主体的行。 让我们进一步讨论有关物理身体的路线。 我们向RainDrop类添加了SKPhysicsBody类的实例。 为此,我们需要定义物理物体将采取的形状。 在这种特定情况下,我们希望它是雨滴的大小和形状,这就是我在这里实现的。 不同的形状会改变您的对象在碰撞时与其他对象交互的方式,因此这是一个重要的决定。 SpriteKit还提供了多种默认形状,我们将在其中进一步实现其中之一。 将以下代码行添加到文件中。 您可能需要根据图像的大小调整雨滴的大小。 别忘了还要调整物理物体的大小。

现在,我们需要编写一种方法来产生雨滴,并在GameScene类的update方法期间调用它。 可以将以下代码放在GameScene类中,以实现此目的。 这将在每个更新间隔生成一个雨滴。 如果要减慢雨滴的速度,可以向此函数添加随机数生成器和if语句。

运行该应用程序,它应类似于以下内容。

现在,让我们添加一个不幸的人,他被雨淋住了。 我们还需要给他一个PhysicalBody,它看起来与我们在RainDrop类中所做的非常相似。 创建一个名为Person.swift的新文件,并为其提供以下代码。

上面的代码段还包含一种方法,该方法使我们可以在屏幕上拖动人员。 我们将需要在GameScene类的touchesBegan和touchesMoved方法下调用此方法,并创建Person类的实例。 下面的代码可以解决这个问题。

现在,让我们继续并再次运行该应用程序。 它看起来应如下图所示。

糟糕,现在我们已经为从屏幕上掉下的那个人添加了physicsBody。 让我们添加一个Floor类,以便他可以站立。 地板课也将需要一个PhysicalBody。 这次我们将使用SpriteKit提供的通用形状。 我们将需要在地板类上设置的另一个属性是’isDynamic’属性。 我们将其设置为false,这将使地板能够抵抗重力,这样在应用程序加载时它不会从屏幕上掉落。 可以将以下代码添加到地板类。

我们还需要将地板实例添加到GameScene类。 参见下面的代码。

现在运行您的应用程序,它应如下所示。

为了解决一个问题,我们创建了另一个问题。 该人现在可以站立了,但是雨点正在堆积! 在解决该问题之前,我建议转到GameViewController文件,并将以下行放到viewDidLoad方法的末尾。

这会将边界放置在任何PhysicalBody周围。 除了可以看到人和雨滴的轮廓外,还可以看到地板。 这些对象上的轮廓是我们附加到它们上的PhysicalBody。 在编写基于物理的应用程序时保持这一点非常有帮助。 如果您不在市场上,则不要忘记将其设置为false。 如果再次运行该应用程序,则会看到每个PhysicsBody。

现在,让我们修复屏幕上的一堆雨滴。 要解决此问题,我们创建另一个名为BitMaskCategories的文件,并将以下代码放入该文件中。

创建位掩码类别并将其分配给对象,以便从物理角度对对象进行分类以及检测接触和碰撞。 它们是使用十六进制值和移位运算符创建的。 要添加更多类别,只需增加移位运算符右侧的数字即可。 现在,让我们在每个类中实现这些类别。 将以下代码行放入相应的类中。

现在,我们编写了代码,以确定哪些对象能够相互接触和碰撞。 让我们逐行进一步分解。

physicsBody.categoryBitMask为该对象分配了一个类别,因此当另一个对象的框架与该对象相交时,它将知道该对象与哪种对象相交。

physicsBody.contactTestBitMask分配对象在与另一个对象相交时可以检测到接触的类别。 如果对象A的categoryBitMask为’A’并且contactBitMask为’B’,并且对象B的categoryBitMask为’B’和contactBitMask为’A’,则当对象A与对象B相交时,“联系人”将为公认的。

与上述类似,PhysicalBody.collisionBitMask分配对象在与另一个对象相交时将与之碰撞的类别。 如果对象A的categoryBitMask为“ A”,而冲突BitMask为“ B”,并且对象B的categoryBitMask为“ B”,而collisionBitMask为“ A”,则当对象A与对象B相交时,它们将相互碰撞。

碰撞和接触虽然听起来很相似,但实际上却有很大不同。 如果两个物体相互碰撞,这将改变一个或两个物体的轨迹,并迫使它们改变路径。

当两个对象彼此接触时,它们将不会改变轨迹,除非它们的collisionBitMask如此规定。 但是,可以使用接触来确定对象彼此相交时发生的功能。 例如,这可能会导致生命损失或一个或两个对象的颜色改变。 您可以编写代码块,确定当对象相互接触时会发生什么。 将以下代码放在GameScene类中。 这将处理雨滴与地面之间的接触。 本质上,当雨滴落到地板上时,它会从其父级上移开,然后从屏幕上消失。

还有另一件事要做。 为了使位掩码正常工作,GameScene类需要采用“ SKPhysicsContactDelegate”协议,并且我们还需要将GameScene设置为该委托。 下面是实现此目的的代码。

现在让我们构建并运行该应用程序。 如果您已经遵循了它,那么它应该看起来已经完成了。 您会注意到,由于位掩码类别及其在对象之间创建的关系,雨滴将碰撞并从伞上弹起,但是当雨滴落到地板上时便消失了。

雨滴似乎下降得很快,让我们放慢速度。 当他们打到雨伞时,我们还要增加一点反弹。 应用PhysicalBody之后,将以下两行代码添加到RainDrop初始化程序中。

现在,当您运行该程序时,它应该如下所示。 我将showPhysics属性设置为true,以便您查看物理体,以防您不与我一起编码。

恭喜你! 您刚刚使用重力和碰撞检测构建了一个应用程序!