Swift: Bitmap data and filters

Note: Source code (FilterExample) available on Github

I was wondering how bitmap programming works on iOS, just like with BitmapData in Flash, I wanted to perform simple operations for painting but also curious about how filters work. Again, in AS3, you would use the applyFilter API on BitmapData, so here is how things work on iOS/MacOS with Swift and the Quartz/Core Image APIs.

Graphics Context and the Quartz drawing engine

In Flash, to perform drawing operations, you create a BitmapData object and use the pixel APIs defined on it. On iOS/MacOS, things are different, you work with a graphics context (which is offscreen) that you manipulate through high-level functions like CGContextSetRGBFillColor, the CG at the beginning stands for Core Graphics which leverages the powerful Quartz drawing engine behind the scenes.

To initiate the drawing, we create a context, by specifying its size, opaque or not and its scaling:

UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 200), true, 1)

Note that we will make our bitmap of 200 by 200px and will be opaque. We pass 1 for the scaling, because to get the size of the bitmap in pixels, you must multiply the width and height values by the value in the scale parameter. If we had passed 0, it would have taken the scaling of the device's screen.

We now have our context created offscreen, ready for the drawing commands to be passed, but we still don't have a reference to it. The previous high-level function UIGraphicsBeginImageContextWithOptions creates the context but did not give us a reference to it, for this, we call the UIGraphicsGetCurrentContext API:

let context = UIGraphicsGetCurrentContext()

Ok, now we are ready to draw, so we use the high-level APIs for that, the names are pretty explicit about their purpose:

CGContextSetRGBFillColor (context, 1, 1, 0, 1)
CGContextFillRect (context, CGRectMake (0, 0, 200, 200))
CGContextSetRGBFillColor (context, 1, 0, 0, 1)
CGContextFillRect (context, CGRectMake (0, 0, 100, 100))
CGContextSetRGBFillColor (context, 1, 1, 0, 1)
CGContextFillRect (context, CGRectMake (0, 0, 50, 50))
CGContextSetRGBFillColor (context, 0, 0, 1, 0.5);
CGContextFillRect (context, CGRectMake (0, 0, 50, 100))

We are now drawing offscreen. Note that at this point, this is not really a bitmap yet that can be displayed, this is really just raw pixels painted. To display this on screen, we need a high-level wrapper, just like in Flash and the relationship between Bitmap and BitmapData. So we will use the UIGraphicsGetImageFromCurrentImageContext API, which will basically take a snapshot/raster of our drawing:

var image = UIGraphicsGetImageFromCurrentImageContext()

At this point, we could just display our UIImage object returned here. Because I am using SpriteKit for my experiments, we need to wrap the UIImage object into an SKSprite object that holds a SKTexture object, so that gives us:

// we create a texture, pass the UIImage
var texture = SKTexture(image: image)
// wrap it inside a sprite node
var sprite = SKSpriteNode(texture:texture)
// we scale it a bit
sprite.setScale(0.5);
// we position it
sprite.position = CGPoint (x: 510, y: 280)
// let's display it
self.addChild(sprite)

This is what you get:

Simple bitmap data

Here is the full code:

import SpriteKit

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        
        // we create the graphics context
        UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 200), true, 1)
        
        // we retrieve it
        let context = UIGraphicsGetCurrentContext()
        
        // we issue drawing commands
        CGContextSetRGBFillColor (context, 1, 1, 0, 1);
        CGContextFillRect (context, CGRectMake (0, 0, 200, 200));// 4
        CGContextSetRGBFillColor (context, 1, 0, 0, 1);// 3
        CGContextFillRect (context, CGRectMake (0, 0, 100, 100));// 4
        CGContextSetRGBFillColor (context, 1, 1, 0, 1);// 3
        CGContextFillRect (context, CGRectMake (0, 0, 50, 50));// 4
        CGContextSetRGBFillColor (context, 0, 0, 1, 0.5);// 5
        CGContextFillRect (context, CGRectMake (0, 0, 50, 100));
        
        // we query an image from it
        let image = UIGraphicsGetImageFromCurrentImageContext()
        
        // we create a texture, pass the UIImage
        let texture = SKTexture(image: image)
        // wrap it inside a sprite node
        let sprite = SKSpriteNode(texture:texture)
        // we scale it a bit
        sprite.setScale(0.5);
        // we position it
        sprite.position = CGPoint (x: 510, y: 380)
        // let's display it
        self.addChild(sprite)
    }
    
    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}

Pretty simple right? Now you can move your sprite, animate it, scale it, etc. But what if we have an existing image and we want to apply filters on it. In Flash, a loaded bitmap resource would give us a Bitmap object that had a bitmapData property pointing to the bitmap data that we could work with. How does that work here? This is where Core Image comes into play.

Core Image

This is where it gets really cool. If you need to apply filters and perform any video or image processing, real time, you use the powerful Core Image APIs. So let's take the image below, unprocessed:

Ayden no filter

Now, let's apply a filter with the code below. In that example we use the CIPhotoEffectTransfer, that applies a nice Instagramy kind of effect, look at all the filters available, pretty endless capabilities:

// we create Core Image context
let ciContext = CIContext(options: nil)
// we create a CIImage, think of a CIImage as image data for processing, nothing is displayed or can be displayed at this point
let coreImage = CIImage(image: image)
// we pick the filter we want
let filter = CIFilter(name: "CIPhotoEffectTransfer")
// we pass our image as input
filter.setValue(coreImage, forKey: kCIInputImageKey)
// we retrieve the processed image
let filteredImageData = filter.valueForKey(kCIOutputImageKey) as CIImage
// returns a Quartz image from the Core Image context
let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent())
// this is our final UIImage ready to be displayed
let filteredImage = UIImage(CGImage: filteredImageRef);

This gives us the following result:

Ayden filtered

And here is the full code:

import SpriteKit

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        
        // we reference our image (path)
        let data = NSData (contentsOfFile: "/Users/timbert/Documents/Ayden.jpg")
        // we create a UIImage out of it
        let image = UIImage(data: data)
        
        // we create Core Image context
        let ciContext = CIContext(options: nil)
        // we create a CIImage, think of a CIImage as image data for processing, nothing is displayed or can be displayed at this point
        let coreImage = CIImage(image: image)
        // we pick the filter we want
        let filter = CIFilter(name: "CIPhotoEffectTransfer")
        // we pass our image as input
        filter.setValue(coreImage, forKey: kCIInputImageKey)
        // we retrieve the processed image
        let filteredImageData = filter.valueForKey(kCIOutputImageKey) as CIImage
        // returns a Quartz image from the Core Image context
        let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent())
        // this is our final UIImage ready to be displayed
        let filteredImage = UIImage(CGImage: filteredImageRef);
        
        // we create a texture, pass the UIImage
        let texture = SKTexture(image: filteredImage)
        // wrap it inside a sprite node
        let sprite = SKSpriteNode(texture:texture)
        // we scale it a bit
        sprite.setScale(0.5);
        // we position it
        sprite.position = CGPoint (x: 510, y: 380)
        // let's display it
        self.addChild(sprite)
    }
    
    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}

We can also apply filters and play with the parameters to customize them, we could also use shaders for more flexibility, more on that later :) In the code below, we apply a pinch distortion effect to our initial image, that will give us the following:

Simple distortion

And here is the full code:

import SpriteKit

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        
        // we reference our image (path)
        let data = NSData (contentsOfFile: "/Users/timbert/Documents/Ayden.jpg")
        // we create a UIImage out of it
        let image = UIImage(data: data)
        
        // we create Core Image context
        let ciContext = CIContext(options: nil)
        // we create a CIImage, think of a CIImage as image data for processing, nothing is displayed or can be displayed at this point
        let coreImage = CIImage(image: image)
        // we pick the filter we want
        let filter = CIFilter(name: "CIPinchDistortion")
        // we pass our image as input
        filter.setValue(coreImage, forKey: kCIInputImageKey)
        // we pass a custom value for the inputCenter parameter, note the use of the CIVector type here
        filter.setValue(CIVector(x: 300, y: 200), forKey: kCIInputCenterKey)
        // we retrieve the processed image
        let filteredImageData = filter.valueForKey(kCIOutputImageKey) as CIImage
        // returns a Quartz image from the Core Image context
        let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent())
        // this is our final UIImage ready to be displayed
        let filteredImage = UIImage(CGImage: filteredImageRef);
        
        // we create a texture, pass the UIImage
        let texture = SKTexture(image: filteredImage)
        // wrap it inside a sprite node
        let sprite = SKSpriteNode(texture:texture)
        // we scale it a bit
        sprite.setScale(0.5);
        // we position it
        sprite.position = CGPoint (x: 510, y: 380)
        // let's display it
        self.addChild(sprite)
    }
    
    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}

Now, can we apply a filter to the first bitmap we created through drawing commands? Sure. Here is the code for a blur effect:

import SpriteKit

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        /* Setup your scene here */
        
        // we create the graphics context
        UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 200), true, 1)
        
        // we retrieve it
        let context = UIGraphicsGetCurrentContext()
        
        // we issue drawing commands
        CGContextSetRGBFillColor (context, 1, 1, 0, 1);
        CGContextFillRect (context, CGRectMake (0, 0, 200, 200));// 4
        CGContextSetRGBFillColor (context, 1, 0, 0, 1);// 3
        CGContextFillRect (context, CGRectMake (0, 0, 100, 100));// 4
        CGContextSetRGBFillColor (context, 1, 1, 0, 1);// 3
        CGContextFillRect (context, CGRectMake (0, 0, 50, 50));// 4
        CGContextSetRGBFillColor (context, 0, 0, 1, 0.5);// 5
        CGContextFillRect (context, CGRectMake (0, 0, 50, 100));
        
        // we query an image from it
        let image = UIGraphicsGetImageFromCurrentImageContext()
        
        // we create Core Image context
        let ciContext = CIContext(options: nil)
        // we create a CIImage, think of a CIImage as image data for processing, nothing is displayed or can be displayed at this point
        let coreImage = CIImage(image: image)
        // we pick the filter we want
        let filter = CIFilter(name: "CIGaussianBlur")
        // we pass our image as input
        filter.setValue(coreImage, forKey: kCIInputImageKey)
        // we retrieve the processed image
        let filteredImageData = filter.valueForKey(kCIOutputImageKey) as CIImage
        // returns a Quartz image from the Core Image context
        let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent())
        // this is our final UIImage ready to be displayed
        let filteredImage = UIImage(CGImage: filteredImageRef);
        
        // we create a texture, pass the UIImage
        let texture = SKTexture(image: filteredImage)
        // wrap it inside a sprite node
        let sprite = SKSpriteNode(texture:texture)
        // we scale it a bit
        sprite.setScale(0.5);
        // we position it
        sprite.position = CGPoint (x: 510, y: 380)
        // let's display it
        self.addChild(sprite)
    }
    
    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}

And here is the result:

Simple Bitmap data filtered

I hope you guys enjoyed it! Lots of possibilities, lots of fun with these APIs.

Swift: Touch event and physics field

Note: Source code (PhysicsField Example) available on Github

Swift logoiOS8  introduces a set of new features for SpriteKit, and one of them is Physics field (SKFieldNode). They simulate physical forces and as a result, automatically affect all the physics bodies living in the same tree, very useful for games or any other kind of experiments.

Multiple kinds of fields are introduced, from vortex, magnetic, spring, etc. A SKFieldNode is invisible, but still needs to be in the same node tree (display list) to affect physics bodies.

The API is very simple, in the code below, I have the field follow the touch position to simulate a force field:

// Think as below as your Main class, basically the Stage
// Note: The code below is for iOS, you can run it with the iOS simulator

// this imports higher level APIs like Starling
import SpriteKit

// canvas size for the positioning
let canvasWidth: UInt32 = 800
let canvasHeight: UInt32 = 800

// From the docs:
// When a physics body is inside the region of a SKFieldNode object, that field node’s categoryBitMask property is
// compared to this physics body’s fieldBitMask property by performing a logical AND operation.
// If the result is a non-zero value, then the field node’s effect is applied to the physics body.
let fieldMask : UInt32 = 0b1
let categoryMask: UInt32 = 0b1

// our main logic inside this class
// we subclass the SKScene class by using the :TheType syntax below
class GameScene: SKScene {
    
    // our field node member
    let fieldNode: SKFieldNode
    
    // the NSCoder abstract class declares the interface used by concrete subclasses (thanks 3r1d!)
    // see: http://stackoverflow.com/users/2664437/3r1d
    init(coder decoder: NSCoder!){
        // we create a magnetic field
        fieldNode = SKFieldNode.magneticField()
        // we define its body
        fieldNode.physicsBody = SKPhysicsBody(circleOfRadius: 80)
        // we add it to the display list (tree)
        fieldNode.categoryBitMask = categoryMask
        // strength of the field
        fieldNode.strength = 2.8
        // we initialize the superclass
        super.init(coder: decoder)
    }
    
    // this gets triggered automatically when presented to the view, put initialization logic here
    override func didMoveToView(view: SKView) {
        
        // we set the background color to black, self is the equivalent of this in Flash
        self.scene.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
        // we live in a world with gravity
        self.physicsWorld.gravity = CGVectorMake(0, -1)
        // we put contraints on the top, left, right, bottom so that our balls can bounce off them
        let physicsBody = SKPhysicsBody (edgeLoopFromRect: self.frame)
        // we set the body defining the physics to our scene
        self.physicsBody = physicsBody
        // we add it to the display list
        self.addChild(fieldNode)
        
        // let's create 300 bouncing cubes
        for i in 1..300 {
            
            // SkShapeNode is a primitive for drawing like with the AS3 Drawing API
            // it has built in support for primitives like a circle, or a rectangle, here we pass a rectangle
            let shape = SKShapeNode(rect: CGRectMake(-10, -10, 20, 20))
            // we set the color and line style
            shape.strokeColor = UIColor(red: 255, green: 0, blue: 0, alpha: 1)
            // we set the stroke width
            shape.lineWidth = 4
            // we set initial random positions
            shape.position = CGPoint (x: CGFloat(arc4random()%(canvasWidth)), y: CGFloat(arc4random()%(canvasHeight)))
            // we add each circle to the display list
            self.addChild(shape)
            // we define the physics body
            shape.physicsBody = SKPhysicsBody(circleOfRadius: shape.frame.size.width/2)
            // from the docs:
            /*The force generated by this field is directed on line that is determined by calculating the cross-product
            between direction fo the the physics body’s velocity property and a line traced between the field node and the
            physics body. The force has a magnitude proportional to the field’s strength property and the physics body’s
            charge and velocity properties.*/
            // we define a mass for the gravity
            shape.physicsBody.mass = 0.9
            // the charge and field strength are two properties fun tweaking
            shape.physicsBody.charge = 0.6
            // we set the field mask
            shape.physicsBody.fieldBitMask = fieldMask
            // this will allow the balls to rotate when bouncing off each other
            shape.physicsBody.allowsRotation = true
        }
    }
    
    // we capture the touch move events by overriding touchesMoved method
    override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
        // we grab the UITouch object in the current scene (self) coordinate
        let touch = event.allTouches().anyObject().locationInNode(self)
        // we apply the position of the touch to the physics field node
        self.fieldNode.position = touch
    }
    
    // magic of the physics engine, we don't have to do anything here
    override func update(currentTime: CFTimeInterval) {
    }
}

Here is what this produces:

Swift: Bouncing balls with built-in physics engine

Note: Source code (Bouncing Balls Example) available on Github

Swift logoI have been playing tonight with the built-in physics engine in SpriteKit. Like most Flash developers, I am sure you have played or used the Box2D engine in some projects. I have to admit, the APIs have always been pretty brutal to use.

The engine that comes out of the box with SpriteKit has a much more approachable API, very intuitive. I was able to discover a large portion of it by just playing, tweaking and guessing some APIs.

If you want to test this code, paste it inside GameScene.swift of your SpriteKit project:

// Consider this your Main class, basically the Stage
// Note: The code below is for iOS, you can run it with the iOS simulator

// this imports higher level APIs like Starling
import SpriteKit

// canvas size for the positioning
let canvasWidth: UInt32 = 800
let canvasHeight: UInt32 = 800

// our main logic inside this class
// we subclass the SKScene class by using the :TheType syntax below
class GameScene: SKScene {

    // this gets triggered automatically when presented to the view, put initialization logic here
    override func didMoveToView(view: SKView) {

        // we set the background color to black, self is the equivalent of this in Flash
        self.scene.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)

        // we live in a world with gravity on the y axis
        self.physicsWorld.gravity = CGVectorMake(0, -6)
        // we put contraints on the top, left, right, bottom so that our balls can bounce off them
        let physicsBody = SKPhysicsBody (edgeLoopFromRect: self.frame)
        // we set the body defining the physics to our scene
        self.physicsBody = physicsBody
        
        // let's create 20 bouncing balls
        for i in 1..30 {
        
        // SkShapeNode is a primitive for drawing like with the AS3 Drawing API
        // it has built in support for primitives like a circle, so we pass a radius
        let shape = SKShapeNode(circleOfRadius: 20)
        // we set the color and line style
        shape.strokeColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.5)
        shape.lineWidth = 4
        // we create a text node to embed text in our ball
        let text = SKLabelNode(text: String(i))
        // we set the font
        text.fontSize = 9.0
        // we nest the text label in our ball
        shape.addChild(text)
        
        // we set initial random positions
        shape.position = CGPoint (x: CGFloat(arc4random()%(canvasWidth)), y: CGFloat(arc4random()%(canvasHeight)))
        // we add each circle to the display list
        self.addChild(shape)
        
        // this is the most important line, we define the body
        shape.physicsBody = SKPhysicsBody(circleOfRadius: shape.frame.size.width/2)
        // this defines the mass, roughness and bounciness
        shape.physicsBody.friction = 0.3
        shape.physicsBody.restitution = 0.8
        shape.physicsBody.mass = 0.5
        // this will allow the balls to rotate when bouncing off each other
        shape.physicsBody.allowsRotation = true
        }
    }

    // magic of the physics engine, we don't have to do anything here
    override func update(currentTime: CFTimeInterval) {
    }
}

And here is the video preview of what this should give you:

Swift: Types conversion, subclassing, casting and drawing

Here is another Swift example, showing how to convert types, subclass a native one, perform casting and draw multiple shapes (like with the Drawing API) and make them move:

// Playground - noun: a place where people can play
// Consider this your Main class, basically the Stage
// Note: The code below is for OSX Playground, not iOS

// this imports higher level APIs like Starling
import SpriteKit
import XCPlayground

// we create our custom MyCircle class extending SKShapeNode
// we define two properties for the destination properties
// we use Float for a 32 bit floating point, we would use Double if we needed 64 bit precision
class MyCircle : SKShapeNode {
    var destX: Float = 0.0
    var destY: Float = 0.0
}

// canvas size for the positioning
let canvasWidth: UInt32 = 500
let canvasHeight: UInt32 = 500

// our main logic inside this class
// we subclass the SKScene class by using the :TheType syntax below
class GameScene: SKScene {
    
    // this gets triggered automatically when presented to the view, put initialization logic here
    override func didMoveToView(view: SKView) {
        
        // let's iterate 20 times
        for i in 1..20 {
            // we create new instances of our MyCircle class
            // note that we don't use new, this is done implicitely
            // SkShapeNode is a primitive for drawing like with the AS3 Drawing API
            // it has built in support for primitives like a circle, so we pass a radius
            let shape = MyCircle(circleOfRadius: 10)
            // we set initial position
            shape.position = CGPoint (x: CGFloat(arc4random()%(canvasWidth)), y: CGFloat(arc4random()%(canvasHeight)))
            // we set random destination values
            // we convert the random values returned as Int to Float
            // Note the use of arc4random() as an equivalent to Math.random()
            shape.destX = Float(arc4random()%(canvasWidth))
            shape.destY = Float(arc4random()%(canvasHeight))
            // we add each circle to the display list
            self.addChild(shape)
        }
    }
    
    // we override update, which is like an Event.ENTER_FRAME or advanceTime in Starling
    override func update(currentTime: CFTimeInterval) {
        // to remove ambiguity we annotate ball
        for ball: AnyObject in self.children{
            // we downcast with the as keyword before using the MyCircle custom properties
            let currentBall = ball as MyCircle
            // we apply easing motion to the balls
            currentBall.position.x += (CGFloat(currentBall.destX)-currentBall.position.x)*0.1
            currentBall.position.y += (CGFloat(currentBall.destY)-currentBall.position.y)*0.1
            // we calculate the difference between positions (distance)
            // by default x and y positions use the CGFloat type that can accept Float and Double values, we cast it to Float to be consistent with our destX and destY properties
            let diffX = Float(currentBall.position.x) - currentBall.destX
            let diffY = Float(currentBall.position.y) - currentBall.destY
            // if less than 1, we are done, let's set new a destination
            if ( diffX <= 1.0 && diffY <= 1.0 ){
                currentBall.destX = Float(arc4random()%(canvasWidth))
                currentBall.destY = Float(arc4random()%(canvasHeight))
            }
        }
    }
}

// we create our scene (from our GameScene above), like a main canvas
let scene = GameScene(size: CGSize(width:CGFloat(canvasWidth), height: CGFloat(canvasHeight)))

// we need a view
let view = SKView(frame: NSRect(x: 0, y: 0, width: CGFloat(canvasWidth), height: CGFloat(canvasHeight)))

// we link both
view.presentScene(scene)

// display it, XCPShowView is a global function that paints the final scene
XCPShowView("result", view)

Which should give you this:

Types conversion, subclassing, casting and drawing

Hello Swift/Playgrounds

Swift logoWow, it's been a while. I have to say, the combination of Swift and Playgrounds (in XCode 6) brings a lot of fun. I spent the night playing with it, and I wanted to share a piece of code you can try and get started quickly. I could talk about the details of the language and how nice it is, as an F# lover, I love that Swift got some inspiration from it (and other languages too).

With the combination of SpriteKit, similar to Starling, you guys should feel at home.

So there we go, I will post more articles in the next weeks (if you guys like the idea) about my Swift experiments and how the language works, but let's start with a classic Flash dev Hello World with some simple API calls, to make something move over time with an EnterFrame style event:

// Playground - noun: a place where people can play
// Consider this your Main class, basically the Stage
// Note: The code below is for OSX Playground, not iOS

// this imports higher level APIs like Starling
import SpriteKit
import XCPlayground

// our main logic inside this class
class GameScene: SKScene {
    
    // properties initialization
    // note that the spriteNode property below is not initialized
    // we initialize it through the init initializer below
    var spriteNode: SKSpriteNode
    var i = 0.0
    
    // this is our initializer, called once when the scene is created
    // we do our initialization/setup here
    init(size: CGSize){
        
        // let's grab an image, like [Embed] in AS3, results in image data like BitmapData
        // let is to declare a constant, var a variable
        // note that we don't type things, you actually can to resolve ambiguity sometimes
        // but it is inferred by default and does not cause performance issues to not statically type
        let sprite = NSImage(contentsOfFile:"/Users/timbert/Documents/Adium.png")
        
        // let's create a bitmap, like Bitmap in AS3
        let myTexture = SKTexture(image: sprite)
    
        // let's wrap it inside a node
        spriteNode = SKSpriteNode(texture: myTexture)
        
        // we position it, we could scale it, etc.
        spriteNode.position = CGPoint (x: 250, y: 250)
        
        // we complete the initialization by initializating the superclass
        super.init(size: size)
    }
    
    // this gets triggered automtically when the scene is presented by the view
    // similar to Event.ADDED_TO_STAGE
    override func didMoveToView(view: SKView) {
        
        // let's add it to the display list
        self.addChild(spriteNode)
    }
    
    // we override update, which is like an Event.ENTER_FRAME or advanceTime in Starling
    override func update(currentTime: CFTimeInterval) {
        i += 0.1
        // oscillation with sin, like Math.sin
        var osc = 1.5 + sin(CDouble(i))
        // let's scale it
        spriteNode.setScale(CGFloat(osc))
        // we could have retrieved spriteNode also with the code below, similar to getChildAt(0)
        //let node = self.children[0] as SKSpriteNode
    }
}

// we create our scene (from our GameScene above), like a main canvas
let scene = GameScene(size: CGSize(width: 500, height: 500))

// we need a view
let view = SKView(frame: NSRect(x: 0, y: 0, width: 500, height: 500))

// we link both
view.presentScene(scene)

// display it, XCPShowView is a global function that paints the final scene
XCPShowView("result", view)

This should give you the following animation (scaled bitmap) in Playgrounds:

Swift Playgrounds Hello World