按照上一篇的步骤,我们已经完成前两步了,接下来是第三步:添加物理效果。
在didMove方法中添加代码:
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame) self.physicsWorld.contactDelegate = self
依文档来看physicsWorld和physicsBody属性的设置是为了开启模拟真实世界的模式,contactDelegate代理中有一个物理世界中的元素只要碰撞就会触发的didBegin方法,待会儿要用。现在给子弹和飞碟添加上物理属性:
bullet.physicsBody = SKPhysicsBody(edgeLoopFrom: CGRect(x: 0, y: 0, width: bullet.size.width, height: bullet.size.height)) bullet.physicsBody?.categoryBitMask = 2 bullet.physicsBody?.contactTestBitMask = 1
barrier.physicsBody = SKPhysicsBody(rectangleOf: barrier.frame.size) barrier.physicsBody?.categoryBitMask = 1 barrier.physicsBody?.affectedByGravity = false barrier.physicsBody?.contactTestBitMask = 2
注意categoryBitMask和contactTestBitMask属性,
categoryBitMask:A mask that defines which categories this physics body belongs to.
contactTestBitMask:A mask that defines which categories of bodies cause intersection notifications with this physics body.
文档解释categoryBitMask定义了这个物理体属于哪一类的,而contactTestBitMask定义了哪一类的物理体能跟当前物理体产生交叉事件的通知。既然是热狗打飞碟那么这两个值就是相互设置,然后添加碰撞检测的方法:
//MARK:配置场景的物理体代理 extension GameScene { func didBegin(_ contact: SKPhysicsContact) { //为方便我们判断碰撞的bodyA和bodyB的cateBitMask哪个小,小的则将它保存在新建的变脸bodyA里,大的则保存到新建d变量bodyB里 var bodyA:SKPhysicsBody var bodyB:SKPhysicsBody if contact.bodyA.categoryBitMask > contact.bodyB.categoryBitMask { bodyA = contact.bodyA bodyB = contact.bodyB } else { bodyA = contact.bodyB bodyB = contact.bodyA } //判断bodyA是否为子弹,bodyB是否为飞碟,如果是则调用爆炸方法 if (bodyA.categoryBitMask == 2 && bodyB.categoryBitMask == 1) { print("热狗打到了飞碟") } } }
最后一步,添加爆炸效果。
找一个效果不错的爆炸gif图,分解成单张图片,新建一个文件夹,后缀必须为.atlas,把爆炸图片素材拉进去,然后拖进项目中
爆炸发生在热狗跟飞碟接触的地方,可以确定爆炸的位置,下一个方法,传入爆炸位置:
//MARK:爆炸效果 func explode(point:CGPoint) { //提取atlas文件中的素材 let explodeAtlas = SKTextureAtlas.init(named: "exploded") let allTextureArray = NSMutableArray.init(capacity: 16) for i in 0..<explodeAtlas.textureNames.count { let textureName = String(format: "%[email protected]", arguments: [i+1]) let texture = explodeAtlas.textureNamed(textureName) allTextureArray.add(texture) } let bombNode = SKSpriteNode(texture: allTextureArray[0] as? SKTexture) bombNode.position = point bombNode.name = "bomb" bombNode.size = CGSize(width: 50, height: 50) bombNode.zPosition = 2.0 self.addChild(bombNode) //爆炸效果动画 let animationAction = SKAction.animate(with: allTextureArray as! [SKTexture], timePerFrame: 0.05) bombNode.run(animationAction) { //爆炸结束后移除 bombNode.removeFromParent() } }
在碰撞代理方法中"热狗打到了飞碟"那里添加:
//在飞碟的位置爆炸 explode(point: (bodyB.node?.position)!) //爆炸结束后,热狗和飞碟都消失 bodyB.node?.removeFromParent() bodyA.node?.removeFromParent()
运行看效果: