SpriteKit background animation with depth

I am building my first game using Swift and SpriteKit and want to add a background. The game takes place in space, so I want the stars in the background to move at different speeds. I'm currently going to make a 3D look by making large stars move faster on the screen than smaller ones. Is there an effective way to do this rather than subclassing SKNode this way and adding it as a child at the beginning of DidMoveToView ? This method seems to be pretty intense, but I thought I would try it before reusing the same image over and over again.

 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") } 

}

Any help would be great.

+5
source share
3 answers

As I mentioned in the commentary, you can create a beautiful parallax background using particles.

Add this function anywhere in your class.

 //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.textureFromNode(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: CGRectGetMidX(frame), y: CGRectGetMaxY(frame)) emitterNode.particlePositionRange = CGVector(dx: CGRectGetMaxX(frame), dy: 0) emitterNode.particleSpeedRange = 16.0 //Rotates the stars emitterNode.particleAction = SKAction.repeatActionForever(SKAction.sequence([ SKAction.rotateByAngle(CGFloat(-M_PI_4), duration: 1), SKAction.rotateByAngle(CGFloat(M_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.whiteColor(),time: CGFloat(i) * 2 * twinkleTime / 2) colorSequence.addKeyframeValue(SKColor.yellowColor(), time: (CGFloat(i) * 2 + 1) * twinkleTime / 2) } emitterNode.particleColorSequence = colorSequence emitterNode.advanceSimulationTime(NSTimeInterval(lifetime)) return emitterNode } 

Then add this feature. This is a function that will create layers of stars. Just call this function, for example, in the didMoveToView file.

 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) } 

And this is how it looks.

enter image description here

+6
source

How to do this without particles, you create layers and just move individual layers

So, create a background SKNode, fill it with background sprites

Create a foreground SKNode, fill it with sprites in the foreground

Add the background as a foreground child, give it a zPosition of at least -1

Then you move the foreground, no matter what you move the foreground, you move the background in the opposite direction, usually by a smaller percentage (I like to use half). If your foreground moves 10 pixels to the left, you move the background 5 pixels to the right

Since all of your nodes are inside these layers, all nodes will move when you move the layer

+1
source

Updated @JozemiteApps solution for Swift 4 / iOS 11

Add this function anywhere in your class.

 //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 } 

Then add this feature. This is a function that will create layers of stars. Just call this function, for example, in the didMoveToView file.

 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) } 
+1
source

All Articles