我一直在尝试使用SKCameraNode,但我找不到任何关于用它创建视差效果的信息。
我们假设我添加了上面的代码,并在behindNode
下方添加baseNode
。然后我为我的相机制作动画。
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)
]))
当相机移动时,我需要蓝色方块相对于红色方块以较慢的速度移动..我希望cameranode有相对位置字典或其他东西,但它不会......
答案 0 :(得分:4)
我创建了一个不处理秒或帧的解决方案。
您可以创建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)
}
}
我在这里创建了一个不从SKCameraNode继承的替代实现https://github.com/gitmalong/lovelySpriteKitHelpers/blob/master/ParallaxBackgroundMover.swift
答案 1 :(得分: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 )
}