我正在使用Swift和SpriteKit构建我的第一个游戏并想要添加背景。游戏发生在太空中,所以我想让背景中的星星以不同的速度移动。目前,我正在通过使较大的恒星比较小的恒星更快地在屏幕上移动来进行3D外观。有没有一种有效的方法来做到这一点,而不是像这样创建一个SKNode子类,并在DidMoveToView
的开头添加它作为一个孩子?看起来这种方法非常密集,但我想我会在重复使用相同的图像之前尝试一下。
class BackGroundAnimation:SKNode{
let theView:SKView
init(aView:SKView){
theView = aView
super.init()
animate()
}
func animate(){
for _ in 1...200{
let randomSize = random(1, max: 3)
var randomPosx = random(1,max: 1000)
randomPosx = randomPosx/1000.0
var randomPosy = random(1,max: 1000)
randomPosy = randomPosy/1000.0
let star:SKSpriteNode = SKSpriteNode(texture:starTexture)
star.setScale(randomSize/60.0)
star.position = CGPoint(x:(theView.scene?.size.width)! * randomPosx,y:(theView.scene?.size.width)! * randomPosy)// (self.scene.size.width)*randomPosx, y:(self.scene.size.height) * randomPosy)
//star.position = CGPoint(x: 200,y: 200)
star.physicsBody = SKPhysicsBody(circleOfRadius: star.size.width/2 )
star.physicsBody?.collisionBitMask = 0
star.physicsBody?.categoryBitMask = 0
star.physicsBody?.contactTestBitMask = 0
star.physicsBody?.linearDamping = 0
star.physicsBody?.velocity = CGVector(dx:1 * randomSize, dy:0)
star.name = "star"
//addChild(star)
self.addChild(star)
self.moveToParent(self.scene!)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
任何帮助都会很棒。
答案 0 :(得分:8)
正如我在评论中提到的,你可以使用粒子创建一个漂亮的视差背景。
在班级的任何地方添加此功能。
func createStarLayers() {
//A layer of a star field
let starfieldNode = SKNode()
starfieldNode.name = "starfieldNode"
starfieldNode.addChild(starfieldEmitterNode(speed: -48, lifetime: size.height / 23, scale: 0.2, birthRate: 1, color: SKColor.lightGrayColor()))
addChild(starfieldNode)
//A second layer of stars
var emitterNode = starfieldEmitterNode(speed: -32, lifetime: size.height / 10, scale: 0.14, birthRate: 2, color: SKColor.grayColor())
emitterNode.zPosition = -10
starfieldNode.addChild(emitterNode)
//A third layer
emitterNode = starfieldEmitterNode(speed: -20, lifetime: size.height / 5, scale: 0.1, birthRate: 5, color: SKColor.darkGrayColor())
starfieldNode.addChild(emitterNode)
}
然后添加此功能。这是创建星星层的功能。只需调用此函数,例如在didMoveToView中。
{{1}}
这就是它的样子。
答案 1 :(得分:3)
针对 Swift 4 / iOS 11
更新了@JozemiteApps解决方案在班级的任何地方添加此功能。
//Creates a new star field
func starfieldEmitterNode(speed speed: CGFloat, lifetime: CGFloat, scale: CGFloat, birthRate: CGFloat, color: SKColor) -> SKEmitterNode {
let star = SKLabelNode(fontNamed: "Helvetica")
star.fontSize = 80.0
star.text = "✦"
let textureView = SKView()
let texture = textureView.texture(from: star)
texture!.filteringMode = .nearest
let emitterNode = SKEmitterNode()
emitterNode.particleTexture = texture
emitterNode.particleBirthRate = birthRate
emitterNode.particleColor = color
emitterNode.particleLifetime = lifetime
emitterNode.particleSpeed = speed
emitterNode.particleScale = scale
emitterNode.particleColorBlendFactor = 1
emitterNode.position = CGPoint(x: frame.midX, y: frame.maxY)
emitterNode.particlePositionRange = CGVector(dx: frame.maxX, dy: 0)
emitterNode.particleSpeedRange = 16.0
//Rotates the stars
emitterNode.particleAction = SKAction.repeatForever(SKAction.sequence([
SKAction.rotate(byAngle: CGFloat(-Double.pi/4), duration: 1),
SKAction.rotate(byAngle: CGFloat(Double.pi/4), duration: 1)]))
//Causes the stars to twinkle
let twinkles = 20
let colorSequence = SKKeyframeSequence(capacity: twinkles*2)
let twinkleTime = 1.0 / CGFloat(twinkles)
for i in 0..<twinkles {
colorSequence.addKeyframeValue(SKColor.white,time: CGFloat(i) * 2 * twinkleTime / 2)
colorSequence.addKeyframeValue(SKColor.yellow, time: (CGFloat(i) * 2 + 1) * twinkleTime / 2)
}
emitterNode.particleColorSequence = colorSequence
emitterNode.advanceSimulationTime(TimeInterval(lifetime))
return emitterNode
}
然后添加此功能。这是创建星星层的功能。只需调用此函数,例如在didMoveToView中。
func createStarLayers() {
//A layer of a star field
let starfieldNode = SKNode()
starfieldNode.name = "starfieldNode"
starfieldNode.addChild(starfieldEmitterNode(speed: -48, lifetime: size.height / 23, scale: 0.2, birthRate: 1, color: SKColor.lightGray))
addChild(starfieldNode)
//A second layer of stars
var emitterNode = starfieldEmitterNode(speed: -32, lifetime: size.height / 10, scale: 0.14, birthRate: 2, color: SKColor.gray)
emitterNode.zPosition = -10
starfieldNode.addChild(emitterNode)
//A third layer
emitterNode = starfieldEmitterNode(speed: -20, lifetime: size.height / 5, scale: 0.1, birthRate: 5, color: SKColor.darkGray)
starfieldNode.addChild(emitterNode)
}
答案 2 :(得分:1)
没有粒子的方法是创建图层,然后移动单个图层
所以创建一个背景SKNode,用你的背景精灵填充它
创建一个前景SKNode,用前景精灵填充它
添加背景作为前景的子项,给它一个zPosition至少为-1
然后移动前景,无论你移动前景,你都会以相反的方向移动背景,通常是它的一小部分(我喜欢使用一半)。如果前景向左移动10个像素,则将背景向右移动5个像素
由于您的所有节点都在这些图层中,因此移动图层时所有节点都会移动