Absolutely DO NOT use a timer.
SpriteKit has a well defined update cycle and every kind of update (logic, physics, graphics) should happen into a well defined time frame.
If you really want to write the update logic inside your nodes then the best solution is creating your own update
method and then manually invoking it from the GameScene
.
Let's see a (possible) structured approach
The protocol
protocol Updatable: class {
func update(currentTime: NSTimeInterval)
}
Making your sprite/node updatable
class Player: SKSpriteNode, Updatable {
func update(currentTime: NSTimeInterval) {
// your logic goes here
}
}
Forwarding the updates from the scene to the nodes
class GameScene: SKScene {
private var updatables = [Updatable]()
override func didMoveToView(view: SKView) {
let player = Player()
updatables.append(player)
self.addChild(player)
}
override func update(currentTime: NSTimeInterval) {
updatables.forEach { $0.update(currentTime) }
}
}
As you can see I am using an Array of Updatables
. You should also take care of adding (or removing) new Updatables
to the Array when they are added (or removed) to the scene graph.
While it's definitely possible searching the whole scene graph every frame it would be very bad by a performance point of view.
Is this the right way to go?
Personally I don't like writing this kind of code inside my subclasses of SKNode
or SKSpriteNode
.
I usually create a Logic
class. This class is the ones that receives the update
events from GameScene. It also receives other "logic events" like:
gameStarted
touchesBegan
touchesEnded
This class contains the pure game logic of the game.
It is something like the Instruction Manual you can find into a board game and it is totally agnostic about the graphics representation of the game entities.
In an ideal scenario I would be able to extract the Logic
class from my SpriteKit game and use it with another framework or even with a (non electronic) board game version of the same game.