2015-09-14 60 views
3

我一直在嘗試SKCameraNode,但是我找不到任何關於用它創建視差效果的東西。SpriteKit - SKCameraNode視差效果?

比方說,我添加到上面的代碼,並在我的baseNode下面添加behindNode。然後我製作相機的動畫。

let behindNode = SKNode() 
addChild(behindNode) 

let blueSquare = SKSpriteNode(color: SKColor.blueColor(), size: CGSize(width: 80, height: 80)) 
blueSquare.position = CGPoint(x: size.width/2+40, y: size.height/2+40) 
behindNode.addChild(blueSquare) 

let baseNode = SKNode() 
addChild(baseNode) 

let redSquare = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 80, height: 80)) 
redSquare.position = CGPoint(x: size.width/2, y: size.height/2) 
baseNode.addChild(redSquare) 


let cameraNode = SKCameraNode() 
camera = cameraNode 
addChild(camera!) 
camera!.position = redSquare.position 

cameraNode.runAction(SKAction.sequence([ 
    SKAction.waitForDuration(1), 
    SKAction.moveBy(CGVector(dx: 100, dy: 100), duration: 3), 
    SKAction.moveBy(CGVector(dx: -100, dy: 100), duration: 1), 
    SKAction.moveBy(CGVector(dx: 100, dy: -100), duration: 1) 
])) 

enter image description here

我需要的藍色正方形,以相對於紅色方塊以較慢的速度移動時,相機而動。我會期待cameranode有一個相對位置詞典之類的,但它不..

回答

3

我在我的iOS 9 SpriteKit遊戲中使用視差效果。

基本上,你會添加幾行代碼到你的場景update()函數,移動正方形相機的相反方向,但有一些縮放因子。

update(){ 
    let moveXFactor: CGFloat = 3 
    let moveYFactor: CGFloat = 2 
    camera.position = CGPoint(camera.position.x + moveXFactor, camera.position.y + moveYFactor) 

    let redSquareParallaxSpeedFactor: CGFloat = -0.2 
    let blueSquareParallaxSpeedFactor: CGFloat = -0.1 
    redSquare.position = CGPoint(redSquare.position.x + redSquareParallaxSpeedFactor * moveXFactor, redSquare.position.y + redSquareParallaxSpeedFactor * moveYFactor) 
    blueSquare.position = CGPoint(blueSquare.position.x + blueSquareParallaxSpeedFactor * moveXFactor, blueSquare.position.y + blueSquareParallaxSpeedFactor * moveYFactor) 
} 

這是一個簡化的例子。使用一個變量,用一個時鐘跟蹤fps,並根據恆定的時間尺度移動對象,而不是根據設備當前的fps經常變快或變慢。

因此,在場景的類文件中定義一些變量。

var lastUpdate: NSTimeInterval 
var deltaTime: CGFloat 

然後在場景類的init()函數中初始化它們。

lastUpdate = 0 
deltaTime = 0.01666 

最後,在場景的update()函數中更新它們。

deltaTime = CGFloat(currentTime - lastUpdate) 
lastUpdate = currentTime 

if deltaTime > 1.0 { 
    deltaTime = 0.0166 
} 

所以,現在這個時鐘的工作,讓我們用它來縮放視差效果,所以它更平滑。

update(){ 
    deltaTime = CGFloat(currentTime - lastUpdate) 
    lastUpdate = currentTime 

    if deltaTime > 1.0 { 
    deltaTime = 0.0166 
    } 

    let someScale: CGFloat = 0.001 

    var moveXFactor: CGFloat = 3 * deltaTime * someScale 
    var moveYFactor: CGFloat = 2 * deltaTime * someScale 
    camera.position = CGPoint(camera.position.x + moveXFactor, camera.position.y + moveYFactor) 

    let redSquareParallaxSpeedFactor: CGFloat = -0.2 
    let blueSquareParallaxSpeedFactor: CGFloat = -0.1 
    redSquare.position = CGPoint(redSquare.position.x + redSquareParallaxSpeedFactor * moveXFactor, redSquare.position.y + redSquareParallaxSpeedFactor * moveYFactor) 
    blueSquare.position = CGPoint(blueSquare.position.x + blueSquareParallaxSpeedFactor * moveXFactor, blueSquare.position.y + blueSquareParallaxSpeedFactor * moveYFactor) 
} 
+1

感謝所有的代碼。我有點希望有一個更好的方式來做到這一點。 skcameranode不是真的爲我們節省了很多代碼。不妨沿着老式的方式滑動一堆sknode – hamobi

+0

這個想法是讓你的遊戲對象與攝像機保持在同一水平,並且所有的背景視差對象都使用上面的代碼。 – jmcmahon443

+1

如何對z順序進行排序,使背景對象永遠不會出現在前景對象前面? – Confused

3

我創建了一個不涉及秒或幀的解決方案。

您可以創建SKCameraNode的子類,並使用Swift的didSet()方法,該類在更改類變量後被調用。在我們的例子中,我們想要聽取攝像機節點位置變量的變化。

class CameraNodeParallax:SKCameraNode{ 

override var position : CGPoint { 
    didSet { 
     // Move our backgrounds 
    } 
} 

我們進一步要創建一個包含所有我們的視差背景節點和一個包含相應的移動速度相對於相機的移動速度一個陣列。

var backgroundNodes:[SKNode] = [] 
var backgroundNodesSpeedFactor:[CGVector] = [] // in relation to camera nodes speed 

func addParallaxBackgroundNode(background:SKNode, vector:CGVector) { 
    backgroundNodes.append(background) 
    backgroundNodesSpeedFactor.append(vector) 
} 

一的init(),填補了新的變數可能會以及

init(position:CGPoint) { 
    super.init() 
    self.position = position 
} 

現在我們可以填寫didSet()監聽器有用:

// Move our backgrounds 
var i = 0 
for node in backgroundNodes { 

    let positionChangeX = position.x-oldValue.x 
    let positionChangeY = position.y-oldValue.y 
    let changeX = positionChangeX*backgroundNodesSpeedFactor[i].dx 
    let changeY = positionChangeY*backgroundNodesSpeedFactor[i].dy 
    node.position = CGPointMake(node.position.x+changeX,node.position.y+changeY) 

    i += 1 
} 

最終的代碼看起來像這個:

class CameraNodeParallax:SKCameraNode{ 

    var backgroundNodes:[SKNode] = [] 
    var backgroundNodesSpeedFactor:[CGVector] = [] // in relation to camera nodes speed 

    init(position:CGPoint) { 
     super.init() 
     self.position = position 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    override var position : CGPoint { 
     didSet { 

      // Move your parallax backgrounds 
       var i = 0 
       for node in backgroundNodes { 

        let positionChangeX = position.x-oldValue.x 
        let positionChangeY = position.y-oldValue.y 
        let changeX = positionChangeX*backgroundNodesSpeedFactor[i].dx 
        let changeY = positionChangeY*backgroundNodesSpeedFactor[i].dy 
        node.position = CGPointMake(node.position.x+changeX,node.position.y+changeY) 

        i += 1 
       } 
     } 
    } 

    func addParallaxBackgroundNode(background:SKNode, vector:CGVector) { 
     backgroundNodes.append(background) 
     backgroundNodesSpeedFactor.append(vector) 
    } 
} 

I crea這裏沒有繼承SKCameraNode的替代實現https://github.com/gitmalong/lovelySpriteKitHelpers/blob/master/ParallaxBackgroundMover.swift