歡迎加入QQ討論群258996829
來自星星的你 頭像
蘋果3袋
3
來自星星的你

Swift開發(fā)Sprite Kit游戲?qū)嵺`

發(fā)布時(shí)間:2015-05-28 18:47  回復(fù):0  查看:4223   最后回復(fù):2015-05-28 18:47  

本文作者Ajay Venkat是一名年僅13歲的iOS開發(fā)者,他非常喜歡用蘋果的Sprite Kit 2D游戲框架來開發(fā)iOS游戲,在了解到很多同齡孩子也對(duì)學(xué)習(xí)如何使用Sprite Kit來開發(fā)iOS游戲非常感興趣之后,他以自己用Swift語言所開發(fā)的一款名為“Space Monkey”的游戲?yàn)槔赗ay Wenderlich上寫下了這篇指南,以下為譯文: 

快速入門

首先要安裝蘋果的iOS和Mac應(yīng)用免費(fèi)開發(fā)工具——Xcode。如果還沒有安裝Xcode,可以從App Store上下載;如果已經(jīng)安裝好,須確保自己使用的是最新版本。安裝好Xcode后,下載并解壓starter project,雙擊SpaceMonkey.xcodeproj,文件就會(huì)在Xcode中打開。單擊“Play”,接著你會(huì)看到一整片黑屏:

 

starter project給了一個(gè)好的起步,接下來就是著手開發(fā)自己的游戲了。我已經(jīng)在project中添加了art(藝術(shù)效果)和sounds(音效),放在文件夾Sounds 和 sprites.atlas里。art能派上大用場(chǎng),不妨用“Space Monkey”牛刀小試一下吧!

添加monkey

用Sprite Kit為游戲添加圖片(比如space monkey)有三步:


  1. 創(chuàng)建sprite。第一步用SKSpriteNode 類創(chuàng)建一個(gè)sprite。sprite是圖片的副本,可在游戲里隨意移動(dòng)。
  2. 定位sprite。第二步在屏幕上定位sprite,讓space monkey從屏幕左邊出場(chǎng),逐漸移動(dòng)到中間。
  3. 將sprite添加到場(chǎng)景中。創(chuàng)建sprite還不夠,要展示sprite,需要把它添加到場(chǎng)景中。


一步一步來,打開GameScene.swift,將代碼換成如下所示:

import SpriteKit 
class GameScene: SKScene {
  // 1 - Create the sprite
  let player = SKSpriteNode(imageNamed:"spacemonkey_fly02") 
  override func didMoveToView(view: SKView) {
    // 2 - Position the sprite
    player.position = CGPoint(x:frame.size.width * 0.1, y: frame.size.height * 0.5)
    // 3 - Add the sprite to the scene
    addChild(player)
    // 4 - Set scene background color to black
    backgroundColor = SKColor.blackColor()
  }
}

再回顧一下上述步驟:


  1. 用Art文件夾里的monkey圖片通過SKSpriteNode(imageNamed:)創(chuàng)建SKSpriteNode 。注意:這一步將sprite存儲(chǔ)在了類的一個(gè)property 里,方便開發(fā)者回頭查看。
  2. 場(chǎng)景首次呈現(xiàn)時(shí)調(diào)用的是didMoveToView(_:),這里適合添加初始設(shè)置代碼。這一步在屏幕的左邊設(shè)定sprite的position 。
  3. 用sprite的名稱調(diào)用 addChild(),再添加到場(chǎng)景里。
  4. 游戲場(chǎng)景的背景色設(shè)為黑色,貼合monkey在太空飛行的設(shè)定。


編寫完成后運(yùn)行,就能看見monkey飛翔在太空之中了:

 

接下來添加monkey的敵人!

添加敵人

monkey只有一個(gè),而敵人有很多個(gè),而且可能出現(xiàn)在屏幕的不同位置。

首先需要一些method(method)創(chuàng)建隨機(jī)數(shù)字。將這些新method添加至GameScene.swift,放在 didMoveToView(_:)后(大括號(hào)之前):

func random() -> CGFloat {
  return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(#min: CGFloat, max: CGFloat) -> CGFloat {
  return random() * (max - min) + min
}

random()返回一個(gè)介于0到1之間的十進(jìn)制值。random(min:max:)返回一個(gè)固定范圍的隨機(jī)值。指南不詳述這些步驟的原理,讀者只需用好這些method就夠了。

接下來,將這個(gè)新的method直接添加在 random(min:max:)之后:

// 1
func spawnEnemy() {
  // 2
  let enemy = SKSpriteNode(imageNamed: "boss_ship")
  // 3
  enemy.name = "enemy"
  // 4
  enemy.position = CGPoint(x: frame.size.width, y: frame.size.height * random(min: 0, max: 1))
  // 5
  addChild(enemy)
}

再回顧一下上述步驟:


  1. 創(chuàng)建一個(gè)method,命名為spawnEnemy()。
  2. 跟添加monkey差不多,通過調(diào)用SKSpriteNode(imageNamed:)和添加圖片名稱創(chuàng)建一個(gè)sprite。
  3. 為sprite添加名稱,方便以后辨認(rèn)。
  4. 在屏幕右邊設(shè)定敵人在X軸位置,而Y軸位置用random()設(shè)定一個(gè)隨機(jī)值。
  5. 最后只要用addChild()把sprite添加到parent/場(chǎng)景中。

剩下的就是多次調(diào)用這個(gè)method了!調(diào)用前先創(chuàng)建actions的序列,使敵人以固定時(shí)間間隔出現(xiàn)在屏幕上。將這一行添加到didMoveToView(_:)末尾:

runAction(SKAction.repeatActionForever( SKAction.sequence([ SKAction.runBlock(spawnEnemy),
        SKAction.waitForDuration(1.0)])))
這里調(diào)用spawnEnemy(),用不斷重復(fù)的序列創(chuàng)建一個(gè)action,等待時(shí)長(zhǎng)為1秒,即敵人出現(xiàn)的間隔。


這時(shí)代碼看起來如下所示:

import SpriteKit
class GameScene: SKScene {
  let player = SKSpriteNode(imageNamed:"spacemonkey_fly02")
  override func didMoveToView(view: SKView) {
    player.position = CGPoint(x:frame.size.width * 0.1, y: frame.size.height * 0.5)
    addChild(player)
    backgroundColor = SKColor.blackColor()
    runAction(SKAction.repeatActionForever(
      SKAction.sequence([
        SKAction.runBlock(spawnEnemy),
        SKAction.waitForDuration(1.0)])))
  }
  func random() -> CGFloat {
    return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
  }
  func random(#min: CGFloat, max: CGFloat) -> CGFloat {
    return random() * (max - min) + min
  } 
  func spawnEnemy() {
    let enemy = SKSpriteNode(imageNamed: "boss_ship")
    enemy.name = "enemy"
    enemy.position = CGPoint(x: frame.size.width, y: frame.size.height * random(min: 0, max: 1))
    addChild(enemy)
  }
}

編寫完成后運(yùn)行,敵人就出現(xiàn)在屏幕右邊的隨機(jī)位置上了:

 

讓敵人們動(dòng)起來

先對(duì)“敵人”的代碼進(jìn)行微調(diào),使它們?cè)诔霈F(xiàn)之前,完全隱藏在屏幕后(而非僅僅隱藏一半)。從天而降的設(shè)定為游戲增加了難度,也增添了樂趣。

那么首先要做的就是更新spawnEnemy()那一行代碼,敵人sprite的position編寫如下:

enemy.position = CGPoint(x: frame.size.width + enemy.size.width/2, 
  y: frame.size.height * random(min: 0, max: 1))

現(xiàn)在,用更多action讓敵人從屏幕一端移動(dòng)到另一端,游戲變得更有趣了。

將這一行代碼添加到spawnEnemy()末尾:

enemy.runAction(
  SKAction.moveByX(-size.width - enemy.size.width, y: 0.0, 
    duration: NSTimeInterval(random(min: 1, max: 2))))

此處稍作解釋:


  1. 敵人sprite運(yùn)行一個(gè)SKAction。
  2. SKAction包含一個(gè)moveByX() method,用于控制敵人在X軸上移動(dòng)的固定距離。將整個(gè)屏幕畫面設(shè)置為左移(-size.width),還要設(shè)置完整尺寸的sprite (-enemy.size.width)。
  3. SKAction有個(gè)規(guī)定sprite移動(dòng)速度的時(shí)間參數(shù);此處設(shè)定SKAction后,每1-2秒就改變一個(gè)隨機(jī)值,加快了敵人的移動(dòng)速度。


編寫完成后運(yùn)行,結(jié)果應(yīng)該是敵人移動(dòng)到了屏幕另一端,然后完全消失。如下所示:

物理移動(dòng)sprite

游戲的設(shè)定是:不點(diǎn)擊屏幕時(shí),monkey會(huì)落下來;點(diǎn)擊時(shí),monkey會(huì)跳起。

這里用SKAction移動(dòng)monkey,就像之前移動(dòng)敵人一樣。推薦用Sprite Kit內(nèi)置的物理引擎,更加簡(jiǎn)單。

好,現(xiàn)在來試試看。還是GameScene.swift,在didMoveToView(_:)后添加如下代碼:

player.physicsBody = SKPhysicsBody(circleOfRadius:player.frame.size.width * 0.3)
player.physicsBody?.allowsRotation = false

第一行為monkey創(chuàng)建了一個(gè)physics body,在物理引擎的作用下,monkey因引力和其他外力而落下”。

注意:physics body(物理實(shí)體)的形狀是圓的,僅跟monkey的形狀近似而已。無需做到精確,只要湊效就好。同時(shí)將physics body設(shè)定為不旋轉(zhuǎn)。

編寫完成后運(yùn)行,就能看到monkey在屏幕上時(shí)而落下,時(shí)而消失,很酷吧?

物理推力

為了避免monkey“落下”,需要用物理推力讓它重新跳起來。

這時(shí)要在spawnEnemy()后添加一個(gè)新的method:

func jumpPlayer() {
  // 1
  let impulse =  CGVector(dx: 0, dy: 75)
  // 2
  player.physicsBody?.applyImpulse(impulse)
}

再回顧一下上述步驟:


  1. 首先創(chuàng)建一個(gè)固定數(shù)值推動(dòng)力的CGVector,規(guī)定monkey跳起的距離。我也是嘗試了多次才總結(jié)出具體數(shù)值的。
  2. 用applyImpulse()制造推力,再轉(zhuǎn)化為線速度和角速度推力。理論上,monkey在穿行太空的時(shí)候還會(huì)旋轉(zhuǎn),所以剛剛才要將physics body設(shè)定為不旋轉(zhuǎn)。


代碼在被調(diào)用之前,monkey是不能跳起來的;要使monkey跳起來,就要重寫點(diǎn)擊屏幕時(shí)調(diào)用的那個(gè)method。在jumpPlayer()底下復(fù)制這些代碼:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
  jumpPlayer()
}

點(diǎn)擊屏幕時(shí),自動(dòng)調(diào)用這些method。

現(xiàn)在就差一步了——在 didMoveToView(_:)后添加如下代碼:

// 1
let collisionFrame = CGRectInset(frame, 0, -self.size.height * 0.2)
// 2
physicsBody = SKPhysicsBody(edgeLoopFromRect: collisionFrame)

代碼會(huì)在屏幕邊緣產(chǎn)生一個(gè)特殊的physics body,避免monkey飛出或者墜落在太空中?,F(xiàn)在回顧一下上述代碼:


  1. 首先創(chuàng)造一個(gè)可通過CGRectInset()擴(kuò)大或縮小至多20%的矩形,即monkey的活動(dòng)范圍。monkey的輪廓可以稍微消失在屏幕外,但不能完全消失不見。
  2. 然后設(shè)定場(chǎng)景本身的physics body。剛剛創(chuàng)建的physics body是圓的,此處將它變?yōu)橐粋€(gè)循環(huán)邊,即“矩形的邊緣”,不過聽上去更簡(jiǎn)潔些。


編寫完成后運(yùn)行,就能看到如下場(chǎng)景:

 

一只蹦蹦跳跳的小monkey出現(xiàn)啦!

碰撞檢測(cè)

到目前為止,如果monkey遇到敵人,可以跳過去;但是跟敵人相撞的話,什么效果都沒有,所以需要在游戲中添加碰撞檢測(cè)(collision detection),有如下幾步:


  1. 為所有sprite創(chuàng)建physics body:現(xiàn)在monkey已經(jīng)有了一個(gè)physics body,但是敵人還沒有,所以先完成這一步。
  2. 為每個(gè)physics body設(shè)定category(類別)和contact(接觸點(diǎn)):這一步為sprite分類,比如為monkey和敵人設(shè)定不同的類別;同樣可以在特定的physics body和其他類別的physics body之間設(shè)定“contact(接觸點(diǎn))”。
  3. 設(shè)置Contact Delegate:設(shè)定兩個(gè)physics body何時(shí)接觸。要搞清不同的physics body屬于哪個(gè)類別,是敵人還是monkey。大功告成!


還記得怎么給monkey添加physics body嗎?現(xiàn)在輪到為敵人的sprite添加physics body了,來制造碰撞效果。

首先將如下所示添加至GameScene.swift最頂端:

enum BodyType: UInt32 {
  case player = 1
  case enemy = 2
  case ground = 4
}

這里要做的就是為每個(gè)sprite創(chuàng)建類別。ground number不是針對(duì)sprite,而是針對(duì)應(yīng)用邊框設(shè)定的,所以當(dāng)monkey碰到屏幕邊緣時(shí)會(huì)彈起,而不是落到屏幕之外!

接下來,執(zhí)行SKPhysicsContactDelegate協(xié)定,標(biāo)記GameScene(游戲場(chǎng)景):

class GameScene: SKScene, SKPhysicsContactDelegate {
協(xié)議的作用是保證代碼執(zhí)行特定的method。此處執(zhí)行針對(duì)兩個(gè)physics body相撞的method。然后調(diào)整contactDelegate的值,將如下代碼添加到didMoveToView(_:)末尾:

physicsWorld.contactDelegate = self

完成后,兩個(gè)physics body碰撞時(shí),物理世界就會(huì)自動(dòng)調(diào)用代碼中的method。

在spawnEnemy()末尾添加如下代碼:

// 1
enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.size.width/4)
// 2
enemy.physicsBody?.dynamic = false
// 3
enemy.physicsBody?.affectedByGravity = false
// 4
enemy.physicsBody?.allowsRotation = false
// 5
enemy.physicsBody?.categoryBitMask = BodyType.enemy.rawValue
// 6
enemy.physicsBody?.contactTestBitMask = BodyType.player.rawValue
// 7
enemy.physicsBody?.collisionBitMask = 0

此處稍稍解釋一下:


  1. 為敵人創(chuàng)建physics body。physics body不一定要跟sprite的形狀完全吻合,近似就好。這里用的是圓形,半徑設(shè)為sprite的1/4,免得碰撞效果太猛。
  2. 把dynamic關(guān)掉,實(shí)現(xiàn)物理控制sprite。
  3. 防止引力對(duì)sprite的影響。這一步不言自明,主要讓敵人的sprite避免物理引力的干擾。
  4. 這一步是為了避免sprite在physics body碰撞時(shí)旋轉(zhuǎn)。
  5. 將類別位掩碼設(shè)為之前設(shè)置過的敵人類別。
  6. 敵人和monkey接觸時(shí),Sprite Kit發(fā)出提醒。
  7. 為monkey設(shè)置 collisionBitMask后,當(dāng)接觸到敵人時(shí),兩者會(huì)互相彈開;如果不想要這種效果,將值設(shè)為0。


將如下所示添加到didMoveToView(_:)的后面:

physicsBody?.categoryBitMask = BodyType.ground.rawValue
 
player.physicsBody?.categoryBitMask = BodyType.player.rawValue
player.physicsBody?.contactTestBitMask = BodyType.enemy.rawValue
player.physicsBody?.collisionBitMask = BodyType.ground.rawValue

這里為monkey和ground設(shè)置類別和碰撞位掩碼,讓兩者彼此碰撞;在monkey和敵人之間設(shè)置“contact(接觸點(diǎn))”。

現(xiàn)在到了最重要的一步,完善碰撞檢測(cè),執(zhí)行之前提到的method來處理“contacts”:

func didBeginContact(contact: SKPhysicsContact) {
  let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
  switch(contactMask) {
  case BodyType.player.rawValue | BodyType.enemy.rawValue:
    let secondNode = contact.bodyB.node
    secondNode?.removeFromParent()
    let firstNode = contact.bodyA.node
    firstNode?.removeFromParent()
  default:
    return
  }
}

因?yàn)橹耙褜?chǎng)景設(shè)置為物理世界的contactDelegate,兩個(gè)physics body碰撞時(shí)會(huì)自動(dòng)調(diào)用這個(gè)method。

它將兩個(gè)位掩碼結(jié)合成一個(gè)單個(gè)的接觸點(diǎn)掩碼,檢驗(yàn)是否是monkey和敵人相撞,如果是,就將兩者從屏幕上移除。

編寫完成后運(yùn)行,效果如下:

Game Over!

如果monkey跟敵人相撞,或落出屏幕的話,就會(huì)顯示”Game Over“,接著出現(xiàn)重新點(diǎn)擊開始游戲的畫面。

首先將以下所有變量添加到GameScene頂端,在 let player = SKSpriteNode(imageNamed:"spacemonkey_fly02")之后:

// 1 var gameOver = false // 2 let endLabel = SKLabelNode(text: "Game
            Over") let endLabel2 = SKLabelNode(text: "Tap to restart!") let touchToBeginLabel
            = SKLabelNode(text: "Touch to begin!") let points = SKLabelNode(text: "0")
            // 3 var numPoints = 0 // 4 let explosionSound = SKAction.playSoundFileNamed("explosion.mp3",
            waitForCompletion: true) let coinSound = SKAction.playSoundFileNamed("coin.wav",
            waitForCompletion: false)
再回顧一下上述步驟:



  1. 首先創(chuàng)建一個(gè)gameOver布爾變量,不論游戲是否結(jié)束,都進(jìn)行跟蹤記錄。
  2. 創(chuàng)建一些label node,好在Sprite Kit中設(shè)置屏幕上顯示的字幕。
  3. 創(chuàng)建integer儲(chǔ)存分?jǐn)?shù)。注意,用var來標(biāo)記 integer,不是let,方便之后進(jìn)行修改。
  4. 最后創(chuàng)建一些action,隨后制造音效。


下一步創(chuàng)建名為setupLabels()的新方法:

func setupLabels() {
  // 1
  touchToBeginLabel.position = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
  touchToBeginLabel.fontColor = UIColor.whiteColor()
  touchToBeginLabel.fontSize = 50
  addChild(touchToBeginLabel)
 
  // 2  
  points.position = CGPoint(x: frame.size.width/2, y: frame.size.height * 0.1)
  points.fontColor = UIColor.whiteColor()
  points.fontSize = 100
  addChild(points)
}

再回顧一下上述步驟:


  1. 將“touch to begin(點(diǎn)擊開始)”標(biāo)簽放在屏幕中央,字體白色,大小50pt。
  2. 將position label設(shè)在屏幕底端,白色,大小100。


現(xiàn)在在didMoveToView(_:)里調(diào)用setupLabels():

setupLabels()
再刪掉touchesBegan(_:withEvent:),添加如下代碼:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
  // 1
  if (!gameOver) {
    if player.physicsBody?.dynamic == false {
      player.physicsBody?.dynamic = true
      touchToBeginLabel.hidden = true
      backgroundColor = SKColor.blackColor()
 
      runAction(SKAction.repeatActionForever(
        SKAction.sequence([
          SKAction.runBlock(spawnEnemy),
          SKAction.waitForDuration(1.0)])))
    }
    // 2
    jumpPlayer()
 
  }
  // 3
  else if (gameOver) {
    let newScene = GameScene(size: size)
    newScene.scaleMode = scaleMode
    let reveal = SKTransition.flipHorizontalWithDuration(0.5)
    view?.presentScene(newScene, transition: reveal)
  }
}

回顧一下:


  1. 如果游戲還沒結(jié)束,monkey還處于非動(dòng)態(tài)(受物理引擎控制),同樣說明新游戲還沒開始。這時(shí)將dynamic設(shè)置為true,隱藏label,大批敵人開始出現(xiàn)在屏幕上。
  2. 不管怎樣都要調(diào)用 jumpPlayer ,因?yàn)橹挥衐ynamic 設(shè)置為true的時(shí)候,它才能被調(diào)用。
  3. 如果游戲結(jié)束了,要重新開始,那么創(chuàng)建一個(gè)新的GameScene ,顯示在屏幕上。


接下來在代碼中添加如下方法:

override func update(currentTime: CFTimeInterval) {
  //1
  if !gameOver {
    //2
    if player.position.y <= 0 {
      endGame()
    }
    //3
    enumerateChildNodesWithName("enemy") {
      enemy, _ in
      //4
      if enemy.position.x <= 0 {
        //5
        self.updateEnemy(enemy)
      }
    }
  }
}

回顧一下:


  1. 如果gameOver 為false的話,看看monkey是否消失了,如果是,調(diào)用endGame——這個(gè)隨后再添加。
  2. 用enumerateChildNodesWithName 查看場(chǎng)景中的帶有“enemy(敵人)“的對(duì)象。每當(dāng)一個(gè)敵人消失,就會(huì)調(diào)用updateEnemy()——這個(gè)也是隨后再添加。


現(xiàn)在添加名為updateEnemy()的method,在框架渲染前調(diào)用——產(chǎn)生的效果是:每當(dāng)一個(gè)敵人消失,玩家就會(huì)得1分:

func updateEnemy(enemy: SKNode) { //1 if enemy.position.x < 0 { //2
                    enemy.removeFromParent() //3 runAction(coinSound) //4 numPoints++ //5 points.text
                    = "\(numPoints)" } }

再回顧一下上述步驟:


  1. 看一下敵人是否在在屏幕外的x軸上。
  2. 如果是,把敵人從parent上移除(從游戲中移除)。
  3. 將玩家分?jǐn)?shù)儲(chǔ)存在numPoints里。
  4. 將分?jǐn)?shù)轉(zhuǎn)化為分?jǐn)?shù)條,再將分?jǐn)?shù)條插入分?jǐn)?shù)label。


現(xiàn)在需要稍稍改變下didBeginContact(_:)了。從parent移除第一個(gè)節(jié)點(diǎn)之后,添加這行代碼:

endGame()
現(xiàn)在終于可以用endGamemethod了,久等了:

func endGame() {
  // 1
  gameOver = true
  // 2
  removeAllActions()
  // 3
  runAction(explosionSound)
 
  // 4
  endLabel.position = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
  endLabel.fontColor = UIColor.whiteColor()
  endLabel.fontSize = 50
  endLabel2.position = CGPoint(x: frame.size.width/2, y: frame.size.height/2 + endLabel.fontSize)
  endLabel2.fontColor = UIColor.whiteColor()
  endLabel2.fontSize = 20
  points.fontColor = UIColor.whiteColor()
  addChild(endLabel)
  addChild(endLabel2)
}

現(xiàn)在來回顧一下:


  1. 將gameOver設(shè)置為true。
  2. 移除場(chǎng)景中的所有action,終止所有動(dòng)畫效果。
  3. 運(yùn)行爆炸聲效。
  4. 定位,再為場(chǎng)景添加endLabel。


現(xiàn)在用didMoveToView(_:)移除這個(gè)代碼塊:

backgroundColor = SKColor.blackColor()
 
runAction(SKAction.repeatActionForever(
  SKAction.sequence([
    SKAction.runBlock(spawnEnemy),
    SKAction.waitForDuration(1.0)])))
最后添加一行:

player.physicsBody?.dynamic = false

這樣設(shè)置之后,點(diǎn)擊屏幕后游戲才會(huì)開始,否則monkey是不會(huì)移動(dòng)的。

編寫完成后運(yùn)行,游戲大功告成了!

背景音樂



等會(huì)兒,還有一件事!打開ViewController.swift,添加一個(gè)新屬性:

var backgroundMusicPlayer: AVAudioPlayer!
還要添加一個(gè)新method:

func playBackgroundMusic(filename: String) {
  let url = NSBundle.mainBundle().URLForResource(
    filename, withExtension: nil)
  if (url == nil) {
    println("Could not find file: \(filename)")
    return
  }
 
  var error: NSError? = nil
  backgroundMusicPlayer =
    AVAudioPlayer(contentsOfURL: url, error: &error)
  if backgroundMusicPlayer == nil {
    println("Could not create audio player: \(error!)")
    return
  }
 
  backgroundMusicPlayer.numberOfLoops = -1
  backgroundMusicPlayer.prepareToPlay()
  backgroundMusicPlayer.play()
}

這個(gè)method很方便,用來添加一些背景音樂。工作原理在此不詳述。

用起來很簡(jiǎn)單,只要在skView.presentScene(scene)那一行后添加viewWillLayoutSubviews():

playBackgroundMusic("BackgroundMusic.mp3")
編寫好之后運(yùn)行,美妙的背景音樂出現(xiàn)啦!太棒了!

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?