SpriteKit遊戲開發 Challenge 2: An invincible zombie 問題的另一種解決方案
該挑戰的目的是殭屍碰到敵人時,將其設定為無敵模式,具體要求如下:
1 You should create a variable property to track whether or not the zombie is invincible.
2 If the zombie is invincible, you shouldn’t bother enumerating the scene’s cat ladies.
3 If the zombie collides with a cat lady, don’t remove the cat lady from the scene. Instead, set the zombie as invincible. Next, run a sequence of actions that first makes the zombie blink 10 times over three seconds, then runs the block of code described below.
4 Theblockofcodeshouldsethiddentofalseonthezombie,makingsurehe’s visible at the end no matter what, and set the zombie as no longer invincible.
書上的實現如下:
func zombieHitEnemy(enemy: SKSpriteNode) { enemy.removeFromParent() runAction(enemyCollisionSound) invincible = true let blinkTimes = 10.0 let duration = 3.0 let blinkAction = SKAction.customActionWithDuration(duration) { node, elapsedTime in let slice = duration / blinkTimes let remainder = Double(elapsedTime) % slice node.hidden = remainder > slice / 2 } let setHidden = SKAction.runBlock() { self.zombie.hidden = false self.invincible = false } zombie.runAction(SKAction.sequence([blinkAction, setHidden])) }func checkCollisions(){ if invincible { return } var hitEnemies: [SKSpriteNode] = [] enumerateChildNodesWithName("enemy") { node, _ in let enemy = node as! SKSpriteNode if CGRectIntersectsRect( CGRectInset(node.frame, 20, 20), self.zombie.frame) { hitEnemies.append(enemy) } } for enemy in hitEnemies { zombieHitEnemy(enemy) }}
我覺得有幾點可以完善的地方:
每次都需要建立blinkAction,有點浪費.可以使用共用Action 殭屍變為無敵後,如果敵人出現夠快還是會刪除其他敵人
我把blinkAction設定為lazy的計算屬性,然後直接在情境子節點枚舉中處理與敵人的碰撞,然後直接跳出遍曆,這可以保證只會刪除第一個碰撞的敵人:
lazy var blinkAction:SKAction = { let blinkTimes = 10.0 let duration = 3.0 let blinkAction = SKAction.customActionWithDuration(duration){node,elapsedTime in let slice = duration/blinkTimes let remainder = Double(elapsedTime) % slice node.hidden = remainder > slice / 2 } return blinkAction }()func checkCollisions(){ if zombieInvincible{ return } var hitEnemies:[SKSpriteNode] = [] enumerateChildNodesWithName("enemy"){node,stop in let enemy = node as! SKSpriteNode if CGRectIntersectsRect(CGRectInset(enemy.frame, 20, 20), self.zombie.frame){ hitEnemies.append(enemy) self.zombieInvincible = true let seq = SKAction.sequence([self.blinkAction,SKAction.runBlock(){ self.zombie.hidden = false self.zombieInvincible = false }]) self.zombie.runAction(seq) stop.memory = true } } for enemy in hitEnemies{ zombieHitEnemy(enemy) } }