Sam Sam - 5 months ago 61
Swift Question

How to properly animate SKSpriteNode subclasses

I designed a SKSpriteNode subclass

, and I want to know how to go about animating it with a couple different images. I'm currently passing in an original image with:

class Ship:SKSpriteNode{
static var shipImage = SKTexture(imageNamed:"Sprites/fullShip.png")

init(startPosition startPos:CGPoint, controllerVector:CGVector){
super.init(texture: Ship.shipImage, color: UIColor.clearColor(), size: Ship.shipImage.size())

but I'm not sure how to loop through an image atlas afterwards. I first attempted using a method inside the class that was then called in the

func animateShip() {
timePerFrame: 0.2,
resize: false,
restore: true)),


var shipAnimationFrames : [SKTexture]!
is declared right above
, and this block is located in

//Ship animation
let shipAnimatedAtlas = SKTextureAtlas(named: "ShipImages")
var blinkFrames = [SKTexture]()

let numImages = shipAnimatedAtlas.textureNames.count
for var i=1; i<=numImages; i += 1 {
let shipTextureName = "samShip\(i).png"

shipAnimationFrames = blinkFrames

Any help would be awesome!


Texture Atlas

First of all you need to create a texture atlas into Assets.xcassets. You'll put here the images related to the frames of your character.

enter image description here

Subclassing SKSpriteNode

This is how you create you own sprite with a beginAnimation method

class Croc: SKSpriteNode {

    init() {
        let texture = SKTexture(imageNamed: "croc_walk01")
        super.init(texture: texture, color: .clearColor(), size: texture.size())

    func beginAnimation() {
        let textureAtlas = SKTextureAtlas(named: "croc")
        let frames = ["croc_walk01", "croc_walk02", "croc_walk03", "croc_walk04"].map { textureAtlas.textureNamed($0) }
        let animate = SKAction.animateWithTextures(frames, timePerFrame: 0.1)
        let forever = SKAction.repeatActionForever(animate)

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")

As you can see the beginAnimation method creates a texture atlas using the same name of the texture atlas I previously created in Assets.xcassets.

Then the an array of textures is created (frames) and used as parameter to create the animate action.

Starting the animation

Now you need to create your sprite and invoke beginAnimation just once. You do NOT have to invoke beginAnimations inside any update method otherwise you will create a new animation every new frame. The is wrong. beginAnimation must be called only once.

Here's an example

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        let croc = Croc()
        croc.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))


enter image description here