Swift game infinite spawning not working - swift

i've a problem with my swift game. I want to spawn every 2 seconds two sprites and move them like flappy bird pipes. I tried on this way but my game crashes after the delay. Here is DidMoveToView: ( i jump right on the interesting parts)
let distanceToMove = CGFloat(self.frame.size.width + 140)
let movePipes = SKAction.repeatActionForever(SKAction.moveByX(-distanceToMove, y: 0, duration: NSTimeInterval(0.01 * distanceToMove)))
let removePipes = SKAction.removeFromParent()
moveAndRemove = SKAction.sequence([movePipes,removePipes])
let delay = SKAction.waitForDuration(NSTimeInterval(2.0))
let spawn = SKAction.runBlock({() in self.initPipes()})
let spawnAndDelay = SKAction.sequence([spawn,delay])
let spawnAndDelayForever = SKAction.repeatActionForever(spawnAndDelay)
runAction(spawnAndDelayForever)
And here is the func of the pipes:
func initPipes() {
let pY = arc4random_uniform(UInt32(self.size.height - 250) + 250)
let pipePair = SKNode()
pipePair.position = CGPoint(x: self.frame.size.width + 70, y: 0)
//PIPE 1
pipe1.anchorPoint = CGPointMake(0, 0)
pipe1.position = CGPoint(x: 0, y: Int(pY))
pipe1.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70, 700), center: CGPointMake(70/2, 700/2))
pipe1.physicsBody?.dynamic = false
pipe1.physicsBody?.affectedByGravity = false
pipePair.addChild(pipe1)
//PIPE 2
pipe2.anchorPoint = CGPointMake(0,1)
pipe2.position = CGPoint(x: 0, y: pipe1.position.y - 150)
pipe2.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70, 700), center: CGPointMake(35, -700/2))
pipe2.physicsBody?.dynamic = false
pipe2.physicsBody?.affectedByGravity = false
pipePair.addChild(pipe2)
pipePair.runAction(moveAndRemove)
addChild(pipePair)
}
Any idea? Thanks

I think your issue is here
pipePair.addChild(pipe1)
You are not creating a new pipe but instead using an old one you created somewhere else. The first time through you are not going to have a problem, but if you didn't remove the pipe1 from its parent before you try adding it to a new parent it will crash. I would create your pipe1 and pipe2 in that method instead of having a variable outside of it.
func initPipes() {
let pY = arc4random_uniform(UInt32(self.size.height - 250) + 250)
let pipePair = SKNode()
pipePair.position = CGPoint(x: self.frame.size.width + 70, y: 0)
//PIPE 1
let pipe1 = //whatever pipe1 is
pipe1.anchorPoint = CGPointMake(0, 0)
pipe1.position = CGPoint(x: 0, y: Int(pY))
pipe1.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70, 700), center: CGPointMake(70/2, 700/2))
pipe1.physicsBody?.dynamic = false
pipe1.physicsBody?.affectedByGravity = false
pipePair.addChild(pipe1)
//PIPE 2
let pipe2 = //whatever pipe1 is
pipe2.anchorPoint = CGPointMake(0,1)
pipe2.position = CGPoint(x: 0, y: pipe1.position.y - 150)
pipe2.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70, 700), center: CGPointMake(35, -700/2))
pipe2.physicsBody?.dynamic = false
pipe2.physicsBody?.affectedByGravity = false
pipePair.addChild(pipe2)
pipePair.runAction(moveAndRemove)
addChild(pipePair)
}
or if the intention is to only have one set of pipes at a time call
pipe1.removeFromParent()
pipe2.removeFromParent()
before
pipePair.addChild(pipe1)
pipePair.addChild(pipe2)
Hopefully that makes sense and is helpful.

Related

How to fill out an SKLabelNode with a specific color through animation?

I've been searching the internet for a while now and I couldn't come up with any solution.
I've created a SKLabelNode in my SpriteKit project which displays level numbers.
SKLabelNode:
let levelLbl = SKLabelNode(fontNamed: "LEMON-Bold")
levelLbl.text = "1"
levelLbl.fontSize = 100
levelLbl.fontColor = .grey
levelLbl.zPosition = 2
levelLbl.horizontalAlignmentMode = .center
levelLbl.verticalAlignmentMode = .center
levelLbl.position = CGPoint(x: frame.midX, y: frame.height * 0.75)
addChild(levelLbl)
Screenshot:
Screenshot of my label
I want to fill up the number of my label smoothly with white color from the bottom to the top with an animation so that after x seconds the label is completely white.
I don't want the color to fade in but rather to be filled up similar to a cup of water.
It would be amazing if someone could help me out here!
This is how far I came by using a SKCropNode. My problem is I don't know why I don't see an animation:
func labelAnimation() {
let levelLbl = SKLabelNode(fontNamed: "LEMON-Bold")
let blackRect = SKShapeNode(rectOf: CGSize(width: levelLbl.frame.width, height: levelLbl.frame.height))
blackRect.fillColor = .grey
blackRect.strokeColor = .grey
blackRect.position = CGPoint(x: 0, y: levelLbl.frame.height / 2)
let whiteRect = SKShapeNode(rectOf: CGSize(width: levelLbl.frame.width, height: levelLbl.frame.height))
whiteRect.fillColor = .white
whiteRect.strokeColor = .white
whiteRect.position = CGPoint(x: 0, y: -levelLbl.frame.height / 2)
//Level Node
levelNode.position = CGPoint(x: 0, y: 0)
levelNode.addChild(blackRect)
levelNode.addChild(whiteRect)
//Mask Node
levelLbl.text = "\(levelNr)"
levelLbl.fontSize = 100
levelLbl.horizontalAlignmentMode = .center
levelLbl.verticalAlignmentMode = .center
//Crop Node
cropNode.addChild(levelNode)
cropNode.maskNode = levelLbl
cropNode.position = CGPoint(x: frame.midX, y: frame.midY)
cropNode.zPosition = 5
addChild(cropNode)
//action
let movelevelNode = SKAction.move(to: CGPoint(x: 0, y: frame.height / 3), duration: 8)
levelNode.run(movelevelNode)
}

Why does the app lag a lot when calling functions

I am building a game that requires a function (out of several) to be called depending if a condition is true or not. The condition checks the variable every 0.0001 seconds for game purposes, but the functions are called every 4-6 seconds. I just needed the
Whenever I was testing the game on a device, I noticed that the app lags at certain times. I believe its when a function is called but I'm not sure.
This is an SKAction that calls the function that checks the condition:
let triangle = SKAction.sequence([SKAction.run(obstaclesFunc),SKAction.wait(forDuration: 0.0001)])
run(SKAction.repeatForever(triangle))
This is the condition checker:
func obstaclesFunc() {
GameScene.nextObstacle = Int(arc4random_uniform(6) + 1 )
if(GameScene.first == true){
GameScene.randomNum = 1
}
if (GameScene.pass == true){
number = GameScene.nextObstacle
print(number)
//Rectangle Call Function
if(GameScene.randomNum == 1){
sideRectangles()
//More code at bottom
}
I noticed that the biggest lag occurs when this function is called:
func sideRectangles() {
let rectangle1 = SKSpriteNode(imageNamed: "rectangleWalls")
let rectangle2 = SKSpriteNode(imageNamed: "rectangleWalls")
let rectangle3 = SKSpriteNode(imageNamed: "rectangleWalls")
let rectangleTexture = SKTexture(imageNamed: "rectangleWalls")
//Physics World
rectangle1.physicsBody = SKPhysicsBody(texture: rectangleTexture, size: CGSize(width: rectangle1.size.width - 20, height: rectangle1.size.height - 20))
rectangle1.physicsBody?.categoryBitMask = PhysicsNumbering.rectangle_1
rectangle1.physicsBody?.contactTestBitMask = PhysicsNumbering.player
rectangle1.physicsBody?.affectedByGravity = false
rectangle1.physicsBody?.isDynamic = true
rectangle1.physicsBody?.collisionBitMask = 0
//Physics World
rectangle2.physicsBody = SKPhysicsBody(texture: rectangleTexture, size: CGSize(width: rectangle1.size.width - 20, height: rectangle1.size.height - 20))
rectangle2.physicsBody?.categoryBitMask = PhysicsNumbering.rectangle_2
rectangle2.physicsBody?.contactTestBitMask = PhysicsNumbering.player
rectangle2.physicsBody?.affectedByGravity = false
rectangle2.physicsBody?.isDynamic = true
rectangle2.physicsBody?.collisionBitMask = 0
//Physics World
rectangle3.physicsBody = SKPhysicsBody(texture: rectangleTexture, size: CGSize(width: rectangle1.size.width - 20, height: rectangle1.size.height - 20))
rectangle3.physicsBody?.categoryBitMask = PhysicsNumbering.rectangle_3
rectangle3.physicsBody?.contactTestBitMask = PhysicsNumbering.player
rectangle3.physicsBody?.affectedByGravity = false
rectangle3.physicsBody?.isDynamic = true
rectangle3.physicsBody?.collisionBitMask = 0
let moveDown = SKAction.moveTo(y: self.frame.minY - rectangle3.size.height / 2, duration: 2)
let moveDown2 = SKAction.moveTo(y: self.frame.minY - rectangle3.size.height / 2, duration: 3)
let moveDown3 = SKAction.moveTo(y: self.frame.minY - rectangle3.size.height / 2, duration: 4)
let removeNode = SKAction.removeFromParent()
rectangle1.position = CGPoint(x: self.frame.minX - rectangle3.size.height * 0.1, y: self.frame.maxY + rectangle3.size.width) //use 4.5 for the close one
rectangle2.position = CGPoint(x: self.frame.minX - rectangle3.size.width / 40 , y: self.frame.maxY + rectangle3.size.height) //use 4.5 for the close one
rectangle3.position = CGPoint(x: self.frame.midX - rectangle3.size.width / 1.55, y: self.frame.maxY + rectangle3.size.height * 1.8)
rectangle1.run(SKAction.sequence([moveDown,removeNode]))
rectangle2.run(SKAction.sequence([moveDown2,removeNode]))
rectangle3.run(SKAction.sequence([moveDown3,removeNode]))
//second set
let rectangle5 = SKSpriteNode(imageNamed: "rectangleWalls")
let rectangle6 = SKSpriteNode(imageNamed: "rectangleWalls")
let rectangle7 = SKSpriteNode(imageNamed: "rectangleWalls")
//Physics World
rectangle5.physicsBody = SKPhysicsBody(texture: rectangleTexture, size: CGSize(width: rectangle1.size.width - 20, height: rectangle1.size.height - 20))
rectangle5.physicsBody?.categoryBitMask = PhysicsNumbering.rectangle_5
rectangle5.physicsBody?.contactTestBitMask = PhysicsNumbering.player
rectangle5.physicsBody?.affectedByGravity = false
rectangle5.physicsBody?.isDynamic = true
rectangle5.physicsBody?.collisionBitMask = 0
//Physics World
rectangle6.physicsBody = SKPhysicsBody(texture: rectangleTexture, size: CGSize(width: rectangle1.size.width - 20, height: rectangle1.size.height - 20))
rectangle6.physicsBody?.categoryBitMask = PhysicsNumbering.rectangle_6
rectangle6.physicsBody?.contactTestBitMask = PhysicsNumbering.player
rectangle6.physicsBody?.affectedByGravity = false
rectangle6.physicsBody?.isDynamic = true
rectangle6.physicsBody?.collisionBitMask = 0
//Physics World
rectangle7.physicsBody = SKPhysicsBody(texture: rectangleTexture, size: CGSize(width: rectangle1.size.width - 20, height: rectangle1.size.height - 20))
rectangle7.physicsBody?.categoryBitMask = PhysicsNumbering.rectangle_7
rectangle7.physicsBody?.contactTestBitMask = PhysicsNumbering.player
rectangle7.physicsBody?.affectedByGravity = false
rectangle7.physicsBody?.isDynamic = true
rectangle7.physicsBody?.collisionBitMask = 0
rectangle5.zPosition = 0
rectangle6.zPosition = 0
rectangle7.zPosition = 0
rectangle5.position = CGPoint(x: self.frame.maxX + rectangle3.size.height * 0.1, y: self.frame.maxY + rectangle3.size.width) //use 4.5 for the close one
rectangle6.position = CGPoint(x: self.frame.maxX + rectangle3.size.width / 40 , y: self.frame.maxY + rectangle3.size.height) //use 4.5 for the close one
rectangle7.position = CGPoint(x: self.frame.midX + rectangle3.size.width / 1.55, y: self.frame.maxY + rectangle3.size.height * 1.8)
rectangle5.run(SKAction.sequence([moveDown,removeNode]))
rectangle6.run(SKAction.sequence([moveDown2,removeNode]))
rectangle7.run(SKAction.sequence([moveDown3,removeNode]))
addChild(rectangle1)
addChild(rectangle2)
addChild(rectangle3)
addChild(rectangle5)
addChild(rectangle6)
addChild(rectangle7)
}
Can someone please help me find out what is causing this lag? I cannot seem to figure it out. Thank You in advance!
Generating physicsBodies on the fly is very expensive and that is why your game will lag everytime it tries to do that.
I suggest you create the objects and put them in an array of the obstacle and then copy the array items whenever you need to recreate them.
You have soooooo much code that is being repeated for every object, I've tried to reduce the amount of code by reusing a lot of it for every obstacle.
FYI SKAction.wait(forDuration: 0.0001) is the same as 0 so it is pointless
The code in your obstaclesFunc contains irrelevant or code not contained in your questions so I have omitted that functionality, if it is dire to your game you'll have to figure it out and put it in the generateObstacles func.
//variables needed in your scene
private var rectangles = [SKSpriteNode]()
private var moveDown: SKAction!
private var moveDown2: SKAction!
private var moveDown3: SKAction!
private var removeNode: SKAction!
//in your didMove func
//preload the obstacles into an array
createRectangles()
//in your startGame func
//this func call will start the generation of the obstacles
generateObstacles()
func createRectangles() {
let rectangle1 = createRectangle(category: PhysicsNumbering.rectangle_1)
rectangles.append(rectangle1)
let rectangle2 = createRectangle(category: PhysicsNumbering.rectangle_2)
rectangles.append(rectangle2)
let rectangle3 = createRectangle(category: PhysicsNumbering.rectangle_3)
rectangles.append(rectangle3)
let rectangle5 = createRectangle(category: PhysicsNumbering.rectangle_5)
rectangles.append(rectangle5)
let rectangle6 = createRectangle(category: PhysicsNumbering.rectangle_6)
rectangles.append(rectangle6)
let rectangle7 = createRectangle(category: PhysicsNumbering.rectangle_7)
rectangles.append(rectangle7)
let width: CGFloat = rectangle3.size.width
let height: CGFloat = rectangle3.size.height
//position the rectangles afterward creating them since they appear to be relevant to each other
rectangle1.position = CGPoint(x: frame.minX - height * 0.1, y: frame.maxY + width) //use 4.5 for the close one
rectangle2.position = CGPoint(x: frame.minX - width / 40 , y: frame.maxY + height) //use 4.5 for the close one
rectangle3.position = CGPoint(x: frame.midX - width / 1.55, y: frame.maxY + height * 1.8)
rectangle5.position = CGPoint(x: frame.maxX + height * 0.1, y: frame.maxY + width) //use 4.5 for the close one
rectangle6.position = CGPoint(x: frame.maxX + width / 40 , y: frame.maxY + height) //use 4.5 for the close one
rectangle7.position = CGPoint(x: frame.midX + width / 1.55, y: frame.maxY + height * 1.8)
//now create the actions so that they can be used again and again
createActions(height: height / 2)
}
func createActions(height: CGFloat) {
moveDown = SKAction.moveTo(y: frame.minY - height, duration: 2)
moveDown2 = SKAction.moveTo(y: frame.minY - height, duration: 3)
moveDown3 = SKAction.moveTo(y: frame.minY - height, duration: 4)
removeNode = SKAction.removeFromParent()
}
func generateObstacles() {
let randomWaitTime = Int(arc4random_uniform(6) + 1 )
self.run(.wait(forDuration: randomWaitTime) {
loadAndMoveRectangles()
//now call the generate func again to get a diff random time to wait
generateObstacles()
}
}
func loadAndMoveRectangles() {
let rectangle1 = rectangles[0].copy() as? SKSpriteNode
addChild(rectangle1)
let rectangle2 = rectangles[1].copy() as? SKSpriteNode
addChild(rectangle2)
let rectangle3 = rectangles[2].copy() as? SKSpriteNode
addChild(rectangle3)
let rectangle5 = rectangles[3].copy() as? SKSpriteNode
addChild(rectangle5)
let rectangle6 = rectangles[4].copy() as? SKSpriteNode
addChild(rectangle6)
let rectangle7 = rectangles[5].copy() as? SKSpriteNode
addChild(rectangle7)
rectangle1.run(.sequence([moveDown, removeNode]))
rectangle2.run(.sequence([moveDown2, removeNode]))
rectangle3.run(.sequence([moveDown3, removeNode]))
rectangle5.run(.sequence([moveDown, removeNode]))
rectangle6.run(.sequence([moveDown2, removeNode]))
rectangle7.run(.sequence([moveDown3, removeNode]))
}
func createRectangle(category: UInt32) -> SKSpriteNode {
let rectangle = SKSpriteNode(imageNamed: "rectangleWalls")
rectangle.zPosition = 0
rectangle.physicsBody = SKPhysicsBody(texture: rectangleTexture, size: CGSize(width: rectangle1.size.width - 20, height: rectangle1.size.height - 20))
rectangle.physicsBody?.categoryBitMask = category
rectangle.physicsBody?.contactTestBitMask = PhysicsNumbering.player
rectangle.physicsBody?.affectedByGravity = false
rectangle.physicsBody?.isDynamic = true
rectangle.physicsBody?.collisionBitMask = 0
return rectangle
}

Trail of nodes along a path as in hello world

hi I have a node traveling back and forth along a path. I am trying to integrate the moving shapeNode as in the hello world example to trail my moving node. I'm using a trigger from frame update to trigger the copying of the shape node. And using the position of the travelling node.
The problem is that the trail has some sort of offset and i don't know where its coming from. I have tried to compensate but to no avail. I'm wondering if it might have anything to do with the actions. Thanks for reading.
I have tried looking at this link but i cannot translate
Here is my code so far
spriteKit xcode 9 swift 4 iPad Air
// GameScene.swift
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var borderBody = SKPhysicsBody()
var myMovingNode = SKSpriteNode()
var trailNode : SKShapeNode?
override func didMove(to view: SKView) {
//Define Border
borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
physicsWorld.contactDelegate = self
//Define myMovingNode
myMovingNode = SKSpriteNode(imageNamed: "greenball")
myMovingNode.size.width = 50
myMovingNode.size.height = 50
let myMovingNodeBody:CGSize = CGSize(width: 50, height: 50)
myMovingNode.physicsBody = SKPhysicsBody.init(rectangleOf: myMovingNodeBody)
myMovingNode.zPosition = 2
addChild(myMovingNode)
//Make Path for myMovingNode to travel
let myPath = CGMutablePath()
myPath.move(to: CGPoint(x: 30, y: 30))
myPath.addLine(to: CGPoint(x: 500, y: 500))
/*This is another path to try*/
// myPath.addCurve(to: CGPoint(x: 800, y: 700), control1: CGPoint(x: 500, y: 30), control2: CGPoint(x: 50, y: 500))
/*This draws a line along myPath*/
let myLine = SKShapeNode(path: myPath)
myLine.lineWidth = 10
myLine.strokeColor = .green
myLine.glowWidth = 0.5
myLine.zPosition = 2
addChild(myLine)
/*This sets myMovingNode running along myPath*/
let actionForward = SKAction.follow(myPath, asOffset: false, orientToPath: true, duration: 10)
let actionReverse = actionForward.reversed()
let wait = SKAction.wait(forDuration: 1)
let actionSequence = SKAction.sequence([actionForward, wait, actionReverse, wait])
myMovingNode.run(SKAction.repeatForever(actionSequence))
/*This defines TrailNode and its actions*/
trailNode = SKShapeNode.init(rectOf: CGSize.init(width: 20, height: 20), cornerRadius: 10)
if let trailNode = trailNode {
trailNode.lineWidth = 1
trailNode.fillColor = .cyan
trailNode.run(SKAction.sequence([SKAction.wait(forDuration: 5),
SKAction.fadeOut(withDuration: 3),
SKAction.removeFromParent()]))
}//Eo if Let
}//eo overdrive
func timeFunction (){/*This is controlled by func update*/
let n = trailNode?.copy() as! SKShapeNode?
/*this is where i'm trying to compensate*/
let movingNodeX = myMovingNode.position.x
let movingNodeY = myMovingNode.position.y
let movingNodeOffSet = CGPoint(x: movingNodeX - 0, y: movingNodeY - 0)
n?.position = movingNodeOffSet
myMovingNode.addChild(n!)
}
var frameCounter = 0
override func update(_ currentTime: TimeInterval) {
// print( "Called before each frame is rendered")
if frameCounter == 10{frameCounter = 0; timeFunction()}
frameCounter = frameCounter + 1
}
}//class GameScene
hi in answer to my own question. It was the simplest. On the last line change from
myMovingNode.addChild(n!) to addChild(n!)

How to fix this NSTimer issue?

Everything is fine until I use NSTimer to run the tree, that the images of tree is gone. I use SKview to show the physic then I find out that the code is still run, just only the image is gone. How can I fix it?
Part 1
class PlayScene: SKScene {
var BG6 = SKSpriteNode()
var balloon = SKSpriteNode()
var tree1 = SKSpriteNode()
var tree2 = SKSpriteNode()
Part 2
override func didMoveToView(view: SKView) {
MakeBG()
// add balloon
var ballontexture = SKTexture(imageNamed: "Balloon.png")
balloon = SKSpriteNode(texture: ballontexture)
balloon.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/5)
balloon.physicsBody = SKPhysicsBody(rectangleOfSize: balloon.size)
balloon.physicsBody?.dynamic = true
balloon.physicsBody?.allowsRotation = false
balloon.zPosition = 5
self.addChild(balloon)
var timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: Selector("MakeTree"), userInfo: nil, repeats: true)
var ground = SKNode()
ground.position = CGPointMake(0, 0)
ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width,1))
ground.physicsBody?.dynamic = false
self.addChild(ground)
}
Part 3
func MakeBG(){
// chen hinh nen
//BG1
var BG1texture = SKTexture(imageNamed: "BG2")
var BG1 = SKSpriteNode(texture: BG1texture)
BG1.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
BG1.size.height = self.size.height
var BG1move = SKAction.moveToY(-self.frame.size.height, duration: 90)
BG1.runAction(BG1move)
self.addChild(BG1)
//BG2
var BG2texture = SKTexture(imageNamed: "BG3")
var BG2 = SKSpriteNode(texture: BG2texture)
BG2.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2 + self.frame.size.height)
BG2.size.height = self.size.height
var BG2move = SKAction.moveToY(-self.frame.size.height, duration: 140)
BG2.runAction(BG2move)
self.addChild(BG2)
//BG3
var BG3texture = SKTexture(imageNamed: "BG4")
var BG3 = SKSpriteNode(texture: BG3texture)
BG3.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2 + self.frame.size.height*2)
BG3.size.height = self.size.height
var BG3move = SKAction.moveToY(-self.frame.size.height, duration: 195)
BG3.runAction(BG3move)
self.addChild(BG3)
//BG4
var BG4texture = SKTexture(imageNamed: "BG5")
var BG4 = SKSpriteNode(texture: BG4texture)
BG4.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2 + self.frame.size.height*3)
BG4.size.height = self.size.height
var BG4move = SKAction.moveToY(-self.frame.size.height, duration: 250)
BG4.runAction(BG4move)
self.addChild(BG4)
//BG5
var BG5texture = SKTexture(imageNamed: "BG6")
var BG5 = SKSpriteNode(texture: BG5texture)
BG5.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2 + self.frame.size.height*4)
BG5.size.height = self.size.height
var BG5move = SKAction.moveToY(-self.frame.size.height, duration: 305)
BG5.runAction(BG5move)
self.addChild(BG5)
// BG6
var BG6texture = SKTexture(imageNamed: "BG7")
BG6 = SKSpriteNode(texture: BG6texture)
BG6.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2 + self.frame.size.height*5 + self.frame.size.height*5)
BG6.size.height = self.size.height
BG6.runAction(SKAction.moveTo(CGPoint(x: self.size.width/2 , y: self.size.height/2), duration: 276.5))
self.addChild(BG6)
}
func MakeTree(){
// between
let between = balloon.size.width
// random
var movementAmount = arc4random() % UInt32(self.frame.size.height/2)
var treeoffset = CGFloat(movementAmount) - self.frame.size.height/4
// move tree
var treemove = SKAction.moveByX(0, y: -self.frame.size.width*2, duration: NSTimeInterval(self.frame.size.height/50))
var treeremove = SKAction.removeFromParent()
var treemoveandremove = SKAction.sequence([treemove, treeremove])
// add tree1
var tree1texture = SKTexture(imageNamed: "C2.png")
tree1 = SKSpriteNode(texture: tree1texture)
tree1.position = CGPointMake(CGRectGetMidX(self.frame) - tree1texture.size().width/2 - between + treeoffset, CGRectGetMidY(self.frame) + self.frame.size.height)
tree1.runAction(treemoveandremove)
tree1.physicsBody = SKPhysicsBody(rectangleOfSize: tree1.size)
tree1.physicsBody?.dynamic = false
self.addChild(tree1)
// add tree2
var tree2texture = SKTexture(imageNamed: "C1.png")
tree2 = SKSpriteNode(texture: tree2texture)
tree2.position = CGPointMake(CGRectGetMidX(self.frame) + tree2texture.size().width/2 + between + treeoffset, CGRectGetMidY(self.frame) + self.frame.size.height)
tree2.runAction(treemoveandremove)
tree2.physicsBody = SKPhysicsBody(rectangleOfSize: tree2.size)
tree2.physicsBody?.dynamic = false
[enter image description here][1]
self.addChild(tree2)
}
If I understood your question correctly, then you want to know why your "tree" is gone.
It appears that your MakeTree() method moves all the tree sprite nodes off the screen:
var treemove = SKAction.moveByX(0, y: -self.frame.size.width*2, duration: NSTimeInterval(self.frame.size.height/50))
Also, you shouldn't use NSTimers in SpriteKit. Use SKAction.waitForDuration instead. Like this:
let delay = SKAction.waitForDuration(3)
someNode.runAction(delay) {
//run code here after 3 seconds
}

SpriteKit game lag when the function touchesBegan is called

I'm creating my first game, similar to flappy bird. I want it to start when the screen is touched like the real game. But it lags for about a second and an half, the result is that you die without even playing. Here is my code:
override func didMoveToView(view: SKView) {
/* Setup your scene here */
//Here i init some stuff
distanceToMove = CGFloat(self.frame.size.width + 140)
movePipes = SKAction.repeatActionForever(SKAction.moveByX(-distanceToMove, y: 0, duration: NSTimeInterval(1.2)))
removePipes = SKAction.removeFromParent()
moveAndRemove = SKAction.sequence([movePipes,removePipes])
let delay = SKAction.waitForDuration(NSTimeInterval(0.6))
let spawn = SKAction.runBlock({() in self.initPipes()})
let spawnAndDelay = SKAction.sequence([spawn,delay])
spawnAndDelayForever = SKAction.repeatActionForever(spawnAndDelay)
}
TouchesBegan:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
let touch = touches.first! as UITouch!
let touchLocation = touch.locationInNode(self)
if state == GameState.Starting {
state = GameState.Playing
instNode.hidden = true
if state == GameState.Playing {
runAction(spawnAndDelayForever)
addChild(pipes)
initScore()
}
}
Pipes init:
func initPipes() {
let upper = UInt32(self.size.height - 250)
let pY = arc4random_uniform(upper) + 200
let pipePair = SKNode()
pipePair.position = CGPoint(x: self.frame.size.width + 70, y: 0)
//PIPE 1
let pipe1 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(70, 700))
pipe1.anchorPoint = CGPointMake(0, 0)
pipe1.position = CGPoint(x: 0, y: Int(pY))
pipe1.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70, 700), center: CGPointMake(70/2, 700/2))
pipe1.physicsBody?.dynamic = false
pipe1.physicsBody?.affectedByGravity = false
pipe1.physicsBody?.categoryBitMask = PipeCategory
pipe1.physicsBody?.contactTestBitMask = PlayerCategory
pipe1.physicsBody?.collisionBitMask = PlayerCategory
pipePair.addChild(pipe1)
//PIPE 2
let pipe2 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(70, 700))
pipe2.anchorPoint = CGPointMake(0,1)
pipe2.position = CGPoint(x: 0, y: pipe1.position.y - 150)
pipe2.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70, 700), center: CGPointMake(35, -700/2))
pipe2.physicsBody?.dynamic = false
pipe2.physicsBody?.affectedByGravity = false
pipe2.physicsBody?.categoryBitMask = PipeCategory
pipe2.physicsBody?.contactTestBitMask = PlayerCategory
pipe2.physicsBody?.collisionBitMask = PlayerCategory
pipePair.addChild(pipe2)
//SCORE
let scoreSprite = SKSpriteNode(color: SKColor.clearColor(), size: CGSize(width: 50, height: 150))
scoreSprite.anchorPoint = CGPointMake(0, 1)
scoreSprite.position = CGPointMake(pipe1.position.x + 10, pipe1.position.y)
scoreSprite.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 50, height: 150), center: CGPointMake(25, -75))
scoreSprite.physicsBody?.categoryBitMask = GapCategory
scoreSprite.physicsBody?.contactTestBitMask = PlayerCategory
scoreSprite.physicsBody?.collisionBitMask = 0
scoreSprite.physicsBody?.dynamic = false
pipePair.addChild(scoreSprite)
pipePair.runAction(moveAndRemove)
pipes.addChild(pipePair)
}
It's pretty simple: in initPipes() i create the pipes and i run the action of moving and removing. In touchesBegan i call the action of spawning them.. But it's laggy when i touch the screen.
Run your app through the Time Profiler Instrument to find out where the lag is coming from. It'll give you detailed results (down to individual lines of code) that'll let you know where your issues are.
That'll be much more accurate than people on here guessing.