知识点
- 通过颜色和尺寸生成精灵node
- 若隐若现亮光动画
- parentNode添加subNode,position布局
- 捕捉两物理碰撞检测等
开始干
代码很简单,如下:
import SpriteKit
// 建议用位移来设置,当碰撞node很多时,设置的时候用|运算来支持多种选择
let categoryRock: UInt32 = 0x1 << 1
let categoryShip: UInt32 = 0x1 << 2
class HelloShipSceneNew: SKScene {
override func didMove(to view: SKView) {
backgroundColor = .black
scaleMode = .aspectFit
addChild(shipNode())
generateRock()
}
func shipNode() -> SKSpriteNode {
// 通过颜色和尺寸创建node
let shipNode = SKSpriteNode(color: .green, size: CGSize(width: 100, height: 50))
shipNode.position = view!.center
shipNode.physicsBody = SKPhysicsBody(rectangleOf: shipNode.size)
shipNode.physicsBody?.categoryBitMask = categoryShip
shipNode.physicsBody?.isDynamic = false
shipNode.name = "ship"
addShipLights(shipNode)
return shipNode
}
// 给飞船山下添加 白光
func addShipLights(_ shipNode: SKSpriteNode) {
let shipLightTop = SKSpriteNode(color: .white, size: CGSize(width: 50, height: 2))
// shipNode父节点上布局shipLightTop子节点
shipLightTop.position = CGPoint(x: 0, y: 30)
shipNode.addChild(shipLightTop)
let shipLightBottom = SKSpriteNode(color: .white, size: CGSize(width: 50, height: 2))
shipLightBottom.position = CGPoint(x: 0, y: -30)
shipNode.addChild(shipLightBottom)
// 若隐若现动画
let fadeInAction = SKAction.fadeIn(withDuration: 0.15)
let fadeOutAction = SKAction.fadeOut(withDuration: 0.15)
let waitAction = SKAction.wait(forDuration: 0.1)
shipLightTop.run(SKAction.sequence([fadeInAction, waitAction, fadeOutAction]))
shipLightBottom.run(SKAction.sequence([fadeInAction, waitAction, fadeOutAction]))
}
func rockNode() {
let rockNode = SKSpriteNode(color: .white, size: CGSize(width: 20, height: 20))
let randomX = CGFloat(arc4random_uniform(UInt32(frame.width*0.8)))
rockNode.position = CGPoint(x: randomX, y: frame.height)
rockNode.physicsBody = SKPhysicsBody(rectangleOf: rockNode.size)
rockNode.physicsBody?.usesPreciseCollisionDetection = true
rockNode.physicsBody?.categoryBitMask = categoryRock
rockNode.name = "rock"
addChild(rockNode)
}
// 重复不断产生rock
func generateRock() {
let generateAction = SKAction.run{
self.rockNode()
}
let waitAction = SKAction.wait(forDuration: 0.15)
run(SKAction.repeatForever(SKAction.sequence([generateAction,waitAction])))
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// 移动飞船
guard let touch = touches.first else {
return
}
if let ship = childNode(withName: "ship") {
let moveAction = SKAction.move(to: touch.location(in: self), duration: 0.5)
ship.run(moveAction)
}
}
override func didSimulatePhysics() {
// 当rock掉到屏幕外,将其移除。
enumerateChildNodes(withName: "rock") { (node, _) in
if node.position.y < 0 {
node.removeFromParent()
}
}
}
}
// 碰撞检测回调
extension HelloShipScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
let bodyA: SKPhysicsBody
let bodyB: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
bodyA = contact.bodyA
bodyB = contact.bodyB
}else {
bodyA = contact.bodyB
bodyB = contact.bodyA
}
if bodyA.categoryBitMask == categoryRock && bodyB.categoryBitMask == categoryShip {
print("石头和飞船碰撞💥")
}
}
}
此时运行效果:
两问题:飞船上下两条白色的亮光呢? 而且控制台也没打印
石头和飞船碰撞💥
?好吧,继续看看,哪里出问题了。
- 问题一
既然没看见亮光,要么node没加上,要么是动画有问题,再仔细看代码,确实动画有问题。就执行了一次,那么短怎么看的到。而且已经有消失和出现切换 没必要再加个wait动画了。addShipLights
方法里休改成如下代码即可。
// 若隐若现动画
let fadeInAction = SKAction.fadeIn(withDuration: 0.25)
let fadeOutAction = SKAction.fadeOut(withDuration: 0.25)
// let waitAction = SKAction.wait(forDuration: 0.1)
shipLightTop.run(SKAction.repeatForever((SKAction.sequence([fadeInAction, fadeOutAction]))))
shipLightBottom.run(SKAction.repeatForever((SKAction.sequence([fadeInAction, fadeOutAction]))))
- 问题二
问题二很简单,shipNode都禁用物理体属性啦,当与其它物理体碰撞时肯定是不会走回调的,改成true即可,但我们这里先不改
shipNode.physicsBody?.isDynamic = true
最终效果
改后来看下最终效果,是不是有亮亮的光了。