Cptn. Array
Cptn. Array

Reputation: 59

Xcode SpriteKit SKAction not changing properties of an SKSpriteNode?

If I create an SKSpriteNode, and run an SKAction on the node, the action runs on the simulator, but the properties of the node have not changed. E.g. in the following example, in the simulator, the node starts at (50,50) and moves to (0,0) over 1 second. However, the print statement at the end prints (50,50) instead of the new position (0,0)

let test = SKSpriteNode()

test.position = CGPoint(x: 50.0, y: 50.0)
test.size = CGSize(width: 20.0, height: 20.0)
test.color = UIColor.black
addChild(test)

test.run(SKAction.move(to: CGPoint(x: 0, y: 0), duration: 1.0))
print("(\(test.position.x), \(test.position.y))")

The only reason I can think of is that the print statement executes before the SKAction is executed. If this is the case, then how do I execute code later on that relies on getting the position values of the SKSpriteNode?

Upvotes: 2

Views: 258

Answers (3)

Alessandro Ornano
Alessandro Ornano

Reputation: 35402

In SpriteKit, SKAction class have many instance methods, but you don't need to add more code like a SKAction.sequence and another SKAction to print your position.

In fact you have run(_:completion) , you can find the official docs here that

have a completion block called when the action completes

So your code is completed as is, just add completion syntax like this example:

test.run(SKAction.move(to: CGPoint(x: 0, y: 0), duration: 1.0), completion:{ 
   print("(\(test.position.x), \(test.position.y))")
})

Upvotes: 3

Sweeper
Sweeper

Reputation: 274500

The only reason I can think of is that the print statement executes before the SKAction is executed.

You are exactly right!

then how do I execute code later on that relies on getting the position values of the SKSpriteNode?

By combining SKAction.sequence and SKAction.run method calls.

The sequence method returns an action that consists of a bunch of actions which are run one after another.

The run method returns an action that when run, executes the block of code that you pass in as the parameter.

You want to print the position after the "move" finishes, so create an action like this:

let runCodeAction = SKAction.run { 
    print("(\(test.position.x), \(test.position.y))") 
}

Then, create a sequence of action using sequence:

let sequence = SKAction.sequence(
    [SKAction.move(to: CGPoint(x: 0, y: 0), duration: 1.0), runCodeAction])

Now run this sequence:

test.run(sequence)

Upvotes: 1

Julio Montoya
Julio Montoya

Reputation: 1614

The initial position of your node is printed before it´s moved to the desired position, what you need to do is print the position of your node when it gets to your desired position.

you can fix it with a sequence like the following:

let test = SKSpriteNode()
test.position = CGPoint(x: 50.0, y: 50.0)
test.size = CGSize(width: 20.0, height: 20.0)
test.color = UIColor.red
addChild(test)

let moveAction = SKAction.move(to: CGPoint(x: 0, y: 0), duration: 1.0)
let printAction = SKAction.run {
  print("(\(test.position.x), \(test.position.y))")
}
let sequence = SKAction.sequence([moveAction, printAction])

test.run(sequence)

It´s already tested, Hope it helps

Good Luck!! :]

Upvotes: 1

Related Questions