2016-05-23 86 views
0

我想讓我的節點在屏幕上移動並在定時器上無限生成。我希望一次在屏幕上有多個節點。這是我迄今爲止的穩定代碼。我嘗試了多種凍結或崩潰的方法。swift繁殖節點infinietly

let bunnyTexture = SKTexture(imageNamed: "oval 1.png") 
    bunny = SKSpriteNode(texture: bunnyTexture) 
    bunny.position = CGPoint(x: (size.width/3), y: 750 + bunny.frame.height) 
    self.addChild(bunny) 
    bunny.physicsBody = SKPhysicsBody(circleOfRadius: bunnyTexture.size().height/2) 
    bunny.physicsBody!.dynamic = true 
    let spawnBunny = SKAction.moveByX(0, y: -self.frame.size.height, duration: 4) 
    let despawnBunny = SKAction.removeFromParent() 
    let spawnNdespawn2 = SKAction.sequence([spawnBunny, despawnBunny]) 
    bunny.runAction(spawnNdespawn2) 

    let gobblinTexture = SKTexture(imageNamed: "oval 2.png") 
    gobblin = SKSpriteNode(texture: gobblinTexture) 
    gobblin.position = CGPoint(x: 150 + gobblin.frame.width, y: (size.height/3)) 
    self.addChild(gobblin) 
    let randomGob = arc4random() % UInt32(self.frame.size.height/2) 
    let spawnGob = SKAction.moveByX(+self.frame.size.width, y: 0, duration: 4) 
    let despawnGob = SKAction.removeFromParent() 
    let spawnNdespawn = SKAction.sequence([spawnGob, despawnGob]) 
    gobblin.runAction(spawnNdespawn) 

    let ground = SKNode() 
    ground.position = CGPointMake(0, 0) 
    ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, -50)) 
    ground.physicsBody!.dynamic = false 
    self.addChild(ground) 

回答

0

您可以使用SKAction.waitForDuration(interval)創建循環定時器。

用新功能loopAction擴展SKNode。這需要SKActionNSTimeInterval() -> Bool函數。

SKAction是將在每個時間間隔執行的功能。 () -> Bool函數將用於停止否則無限循環。

請記住,這會捕獲SKNodeSKAction。在循環停止之前,它們都不會釋放。

它可能創建一個標誌對象(Bool)來保存所有這些信息,並設置標誌爲false時,它需要停止。我只是喜歡這種方式。

​​是如何實施loopAction的示例。 您需要一個SKNodeSKAction。您可以調用loopAction並調用區間和控制何時停止的函數,而不是在SKNode上調用runAction您可以將此代碼放置在有權訪問相關節點的某個位置。

功能停止,也可以實現爲trailing closure

將代碼粘貼到操場,看看它是如何工作的。

import UIKit 
import SpriteKit 
import XCPlayground 



extension SKNode { 

    func loopAction(action:SKAction,interval:NSTimeInterval,continueLoop:() -> Bool) { 

     guard continueLoop() else { return } 

     runAction(SKAction.waitForDuration(interval)) { 

      if continueLoop() { 
       self.runAction(action) 
       self.loopAction(action, interval: interval, continueLoop: continueLoop) 
      } 
     } 
    } 
} 

// example 
class LoopActionManager { 

    let node = SKSpriteNode(color: UIColor.whiteColor(), size: CGSize(width: 20, height: 20)) 
    let action = SKAction.moveBy(CGVector(dx: 10,dy: 0), duration: 0.5) 

    func continueMoveLoop() -> Bool { 
     return (node.position.x + node.size.width) < node.scene?.size.width 
    } 

    func start() { 
     node.loopAction(action, interval: 1, continueLoop: continueMoveLoop) 
    } 

} 

let view = SKView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) 
let scene = SKScene(size: view.frame.size) 
view.presentScene(scene) 

let example = LoopActionManager() 
scene.addChild(example.node) 
example.start() 



XCPlaygroundPage.currentPage.liveView = view 

由於在它下面的註釋中規定,也可以使用repeatAction。 您可以使用static func擴展SKAction以基於重複動作和間隔生成repeatAction。 與第一種解決方案相比,這更簡單,更符合SDK。您確實會丟失每個間隔的完成處理程序。

import UIKit 
import SpriteKit 
import XCPlayground 


extension SKAction { 

    static func repeatAction(action:SKAction,interval:NSTimeInterval) -> SKAction { 

     // diff between interval and action.duration will be the wait time. This makes interval the interval between action starts. Max of 0 and diff to make sure it isn't smaller than 0 
     let waitAction = SKAction.waitForDuration(max(0,interval - action.duration)) 
     let sequenceAction = SKAction.sequence([waitAction,action]) 
     let repeatAction = SKAction.repeatActionForever(sequenceAction) 

     return repeatAction 

    } 
} 


let view = SKView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) 
let scene = SKScene(size: view.frame.size) 
view.presentScene(scene) 

let node = SKSpriteNode(color: UIColor.whiteColor(), size: CGSize(width: 20, height: 20)) 
let action = SKAction.moveBy(CGVector(dx: 10,dy: 0), duration: 0.5) 

scene.addChild(node) 
node.runAction(SKAction.repeatAction(action, interval: 1.0)) 



XCPlaygroundPage.currentPage.liveView = view 
+0

這是爲什麼如此複雜?將2個動作(等待和移動)放在一個序列中,然後使用重複動作不會更容易嗎?同樣,如果繼續循環爲假,爲什麼還要等待 – Knight0fDragon

+0

@ Knight0fDragon'continueLoop()'可以/應該儘可能多次評估,在wait之前和之後都是有意義的。我之所以選擇「等待」是因爲它會在最後一個動作運行後進行評估。如果時機不同,這將不再是事實。看着'repeatAction' ... –

+0

@ Knight0fDragon你說得對,'repeatAction'確實提供了一個更清潔的解決方案。我將它添加到我的答案中。好決定! –