2015-09-14 31 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