0
votes

I'm creating a SpriteKit game with Swift. I'm using the NSTimer, schedule timer with time interval with the target and the selector. Although repeats is set to true, the pipe comes and goes only once. Here is my timer:

let timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "makePipes", userInfo: nil, repeats: true)

The pipe moves only once although repeats if true. I have declared the function (makePipes) in the didMoveToView.

Here is my full code:

import SpriteKit

class GameScene: SKScene {
func makePipes()
{let action = SKAction.moveToX(self.frame.size.width - 1000, duration: 3)
    pipe.runAction(SKAction.repeatActionForever(action))}

var mainPlayer = SKSpriteNode(imageNamed: "Ball")
var ground = SKSpriteNode(imageNamed: "ground.png")
var pipe = SKSpriteNode(imageNamed: "pipe.png")
var barrier = SKSpriteNode(imageNamed: "Barrier.png")
override func didMoveToView(view: SKView) {
    /* Setup your scene here */
    backgroundColor = UIColor.whiteColor()
    self.physicsWorld.gravity = CGVector(dx: 0, dy: -5)
     mainPlayer.position = CGPoint(x: self.size.width / 2 , y: self.frame.height / 2)
    mainPlayer.color = UIColor.grayColor()
    mainPlayer.colorBlendFactor = 1.0
    ground.size.width = 1000
    barrier.size.width = 1000
    // physics for the main palyer
    mainPlayer.physicsBody = SKPhysicsBody(circleOfRadius: mainPlayer.size.height / 2)
    self.addChild(mainPlayer)


    ground.position = CGPoint(x: self.frame.size.width - 500, y: self.frame.size.height - 750)
    ground.setScale(5)
    ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: self.ground.size.width , height: self.ground.size.height))
    ground.physicsBody?.dynamic = false

    pipe.position = CGPoint(x: self.frame.width , y: self.frame.size.height - self.frame.height + 178)
    pipe.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: pipe.size.width, height: pipe.size.height))
    pipe.physicsBody?.dynamic = true
    pipe.physicsBody?.affectedByGravity = false
    self.addChild(pipe)
    self.addChild(ground)
    barrier.setScale(5)
    barrier.position = CGPoint(x: frame.width / 2 , y: frame.height / 2 + 40)
    barrier.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: barrier.size.width, height: barrier.size.height))
    barrier.physicsBody?.dynamic = false
    barrier.size.height = 200
    self.addChild(barrier)

}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */
    self.physicsWorld.gravity = CGVector(dx: 0, dy: -1)
              if (mainPlayer.size.height < self.frame.height / 5.5) {
        mainPlayer.physicsBody?.velocity = CGVectorMake(0.0, 0.0)
        mainPlayer.physicsBody?.applyImpulse(CGVectorMake(0, 10))
    let timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "makePipes", userInfo: nil, repeats: true)

    }



}

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
}
}
1
Set a breakpoint at the beginning of your makePipes method and see if it is being called repeatedly, or add an NSLog statement at the beginning. - Duncan C

1 Answers

1
votes

I don't see the pipe recreated anywhere. It looks to me like the function is in fact called repeatedly, but because you are not recreating pipes and simply using the same pipe object it just moving farther and farther down. Instead of using only one pipe object, you could try to keep generating pipes within that function like this:

fun makePipes()
{
    //create pipe
    var Pipe = SKSpriteNode(imageNamed:"pipe.png")
    pipe.position = CGPoint(x: self.frame.width , y: self.frame.size.height - self.frame.height + 178)
    pipe.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: pipe.size.width, height: pipe.size.height))
    pipe.physicsBody?.dynamic = true
    pipe.physicsBody?.affectedByGravity = false
    self.addChild(pipe)

    //move pipe
    let action = SKAction.moveToX(self.frame.size.width - 1000, duration: 3)
    pipe.runAction(action, completion: {() -> Void in
        //completed action, can remove pipe
        pipe.removeFromParent()
    })
}

also remove the instance variable from your class so it doesn't conflict and take out your initialization from viewDidLoad. Lastly, I'd recommend to use the SKAction perform selector which will do the same thing. However, it is integrated in SpriteKit (you avoid memory leaks and can have much more control over timing!)