SpriteKit物理

在我以前关于SpriteKit的文章中,我介绍了框架的基础知识,即SKSceneSKNodeSKAction 。 我特意忽略了SpriteKit的一个关键组件:物理

SKPhysics身体

在SpriteKit中,每个节点都有一个名为physicsBody的属性,这是一个SKPhysicsBody? (请注意? ,它使SKPhysicsBody可选,这意味着连接到该节点的物理主体可能不存在,即nil )。 一旦将节点的physicsBody分配给physicsBody的实例,主体便会附加到该节点。

物理物体可以是以下两种之一:基于体积的物体或基于边缘的物体。 基于体积的物体具有质量和体积,而基于边缘的物体则没有。

在上图中,基于体积的主体是一个圆形,但是, SKPhysicsBody可以采用任何形状:使用初始化程序init(circleOfRadius: CGFloat) CGPath的圆形,矩形,多边形,甚至是图像(使用SKTextureinit(circleOfRadius: CGFloat)init(rectOf: CGSize)init(polygonFrom: CGPath)init(texture: SKTexture, size: CGSize) 。 虽然可以使用这些选项中的任何一个来创建基于体积的物理物体,但是使用更复杂的形状会产生成本。

上图显示了一个精灵节点,上面附加了不同的物理实体:(1)圆形,(2)矩形,(3)多边形和(4)基于纹理的实体。 确定复杂多边形的碰撞比计算圆形要难得多。 在实践中,除非场景中有大量物理物体,否则这可能不会有太大的不同,但这是需要注意的。

另一方面,基于边缘的物理物体是无质量的路径,实际上它们是非固体的。 这些物体不会被物理引擎移动,但是会与基于体积的物体发生碰撞。 例如,您可能想要其他物理物体无法穿过的场景边界。 有一个方便的初始化器可以创建这些主体: init(edgeLoopFrom: CGRect) 。 如果将场景框架传递给它,例如SKPhysicsBody(edgeLoopFrom: scene.frame) ,则可以在场景周围创建不可逾越的边界。

默认情况下,每个物理实体都将与其他所有物理实体进行交互。 要更改此行为,我们在每个物理物体上设置属性categoryBitMaskcollisionBitMask contactTestBitMaskcontactTestBitMask 。 类别位掩码告诉碰撞引擎主体属于哪个类别。 使用上面的示例,您将拥有一个球类别( b0001 )和一个边缘类别( b0010 )。 由于我们希望球与边缘碰撞,因此我们将为场景中的每个球和边缘分配碰撞和接触测试位掩码。

  let ballCategory:UInt32 = b0001 
让edgeCategory:UInt32 = b0010
 让球= SKShapeNode(circleOfRadius:10) 
ball.physicsBody = SKPhysicsBody(circleOfRadius:10)
ball.physicsBody?.categoryBitMask = ballCategory
ball.physicsBody?.contactTestBitMask = ballCategory | edgeCategory
ball.physicsBody?.collisionBitMask = ballCategory | edgeCategory
  let edge = SKPhysicsBody(edgeLoopF​​rom:scene.frame) 
edge.categoryBitMask = edgeCategory
edge.contactTestBitMask = ballCategory
edge.collisionBitMask = ballCategory

现在,每个球都将与边缘以及其他所有球碰撞,因为我们在两个球和边缘类别上使用了按位OR运算符( | )。

力量

为了使物理物体在场景中移动,我们使用力。 SKPhysicsBody类具有允许您为其赋予力矢量并将其应用到身体的方法。 方法applyForce(CGVector)完成此任务。

  ball.applyForce(CGVector(dx:-20,dy:30)) 

可以认为这是推球放手。 该力将使球朝赋予applyForce方法的向量方向加速。 如果物理物体上的friction属性大于0 ,则球将由于摩擦而失去速度。 身体物理学的另一个特性是restitution ,它将告诉物理学引擎,当它与其他物体碰撞时,它将损失多少速度。 在现实生活中,当您将弹力球扔到地面上时,您会看到这种情况:由于重力和撞击地面的动量损失,该球会弹回您的身体,但高度会降低。

说到重力:每个SKScene都具有physicsWorld属性,您可以在其中定义世界中的物理学如何工作。 物理世界中的重力默认为CGVector(dx: 0, dy: -9.8) ,这是地球上的重力加速度。 您可以将该属性更改为任何所需的属性。 如果希望节点落到右侧,则可以将重力设置为CGVector(dx: 5, dy: 0) 。 假设您有一个游戏,玩家会倾斜设备以使物体在场景中移动。 您可以使用加速度计数据更新重力矢量,这将在设备倾斜的方向上施加重力。

这应该使您从基础入手,但是SpriteKit物理功能不只是物理实体和简单的作用力,所以请随时在评论中向我提问,在Twitter上鸣叫或PM我,或查看Apple在SKPhysicsBody上的文档。有关更多信息:https://developer.apple.com/reference/spritekit/skphysicsbody

如果您想观看使用SpriteKit的游戏,请在App Store上查看Blueshift!

Blueshift Tiles:在App Store上的内容
阅读评论,比较客户评价,查看屏幕截图,并了解有关Blueshift Tiles的更多信息。 下载Blueshift Tiles… appsto.re