之前寫了一個打飛機的遊戲,在飛機子彈的問題上,走過很多坑。下面就簡單介紹幾種方案:
1.需要時生成。做一個action序列,間隔一定時間發射一個或者一組子彈,發射的時候用紋理初始化成精靈節點,然後附加到一個子彈組的sknode上。超出邊界的時候,自動把自己從父節點移除。這是我最開始採用的方案,但是因為子彈需要設定的屬性很多,包括物理邊界、碰撞檢測等,所以當間隔時間小於0.15秒左右時,很可能導致crash。這種方法適合生成敵人,或者一些間隔時間長的物件。
虛擬碼:
bullets.runAction(SKAction.repeatActionForever(SKAction.sequence[SKAction.waitForDuration(0.5),SKAction.runBlock({
var bullet = SKSpriteNode(...)
...
self.bullets.addChild(bullet)
})]))
2.需要時拷貝。看了幾個別人寫的demo和git上的專案,發現這樣寫的不多,做iOS兩年經驗的同學也不贊成這種方式。不過還是有人這樣寫,於是我就嘗試了一下,先建立一個標準的bullet作為樣板,然後每次需要新子彈,就呼叫bullet模板的copy函式,拷貝一份。我試驗了一下,速度快了很多,如果沒記錯的話,大概間隔可以縮小到0.1秒以內了,0.05左右還是可以的。但是還是伴隨著大量的初始化和銷燬操作,實在不是太好的解決方式。
虛擬碼:
var bullet = SKSpriteNode()SKSpriteNode
...
bullets.runAction(SKAction.repeatActionForever(SKAction.sequence[SKAction.waitForDuration(0.5),SKAction.runBlock({
self.bullets.addChild(bullet.copy() as SKSpriteNode)
})]))
SKSpriteNode
3.也就是我的最終方案了,預先生成一定數量的子彈,然後複用。我在場景初始化時,就生成好了30個子彈放在bulletGroup這個陣列裡,然後逐個add到bullets這個SKNode節點下,子彈超出邊界時,remove掉,但是因為有bulletGroup陣列的引用,子彈並不會消失,可以進入下一次複用。add的時候,只需要調整一下子彈的position就可以了,連子彈飛行的action都不需要改動。這個目前我沒有測試到子彈間隔時間的極限,0.01秒應該是毫無問題的。
抱歉,涉及程式碼比較多,就不附加虛擬碼了,思路很清楚,很好實現。不過歸根結底,用哪種方案還是要看是哪種需求。