In my last post I covered the absolute most basic thing you can do with Apple’s new Sprite Kit API – put a single sprite onscreen. Dave Thomas wrote a much more in depth (and interesting) post on the topic which you should check out here.
Today I’d like to introduce the physics portion of Sprite Kit.
The physics in SpriteKit come courtesy of Box2D, a rich 2D-only physics engine written in C++. SpriteKit and Xamarin exposes this smoothly to all .NET languages. There’s also an excellent pure C# version called Farseer which is fully usable from Xamarin iOS and Android if cross-platform is your thing.
Creating a world
Just like in the previous post, all the code I’m going to include will live in the ViewDidLoad method on the ViewController from the default F# SingleViewController project.
So first a quick recap – let set up a SpriteKit scene
let skView = new SKView() skView.Bounds <- RectangleF(0.f,0.f, x.View.Bounds.Width * UIScreen.MainScreen.Scale, x.View.Bounds.Height * UIScreen.MainScreen.Scale) skView.ShowsFPS <- true skView.ShowsNodeCount <- true x.View <- skView let scene = new SKScene(skView.Bounds.Size) scene.BackgroundColor <- UIColor.Cyan scene.ScaleMode <- SKSceneScaleMode.AspectFit
Now, a Scene comes with a PhysicsWorld property, pre-allocated to something that will allow use to set settings on our scene’s physics properties. By default the world is set up with Gravity at (0,-9.8). Should you want to change gravity, its as simple as
scene.PhysicsWorld.Gravity <- CGVector(0.f,-198f) //Really strong gravity!!
Having a scene with gravity is great, but by default nothing is affected by gravity or anything else in the scene! To do this, lets rewind again to loading a sprite.
let spriteNode = new SKSpriteNode "Filename" scene.AddChild spriteNode
To add physical properties (which is what lets SpriteKit know we want the physics engine to control it) you have to set the PhysicsBody property of the sprite:
spriteNode.PhysicsBody <- SKPhysicsBody.BodyWithCircleOfRadius 10.f
Now this will set up the object as a circle, but of course you’re not limited to a Circle – there are a number of methods to set the shape as almost anything using boxes and polygon shapes – for example:
By default the bodies created will have a the following (useful) properties set to true – AffectedByGravity and Dynamic. AffectedByGravity means that when you run the scene the sprite will automatically drop from its initial position under the force of gravity until something stops it. Dynamic means that when something hits it it too responds (Newton’s 3rd law). Setting Dynamic to false makes it an immovable object (think wall or floor).
So here’s a complete code sample – nothing too exciting – a bunch of balls (well, owls) dropping to the floor.
override x.ViewDidLoad () = base.ViewDidLoad () //Create SpriteKit view let skView = new SKView() skView.Bounds <- RectangleF(0.f,0.f, x.View.Bounds.Width * UIScreen.MainScreen.Scale, x.View.Bounds.Height * UIScreen.MainScreen.Scale) skView.ShowsFPS <- true skView.ShowsNodeCount <- true x.View <- skView //Create a SpriteKit Scene let scene = new SKScene(skView.Bounds.Size) scene.BackgroundColor <- UIColor.Cyan scene.ScaleMode <- SKSceneScaleMode.AspectFit let r = Random() //Load a texture and create 100 sprite in random locations //With physical properties let texture = SKTexture.FromImageNamed "Owl" for i in 0..100 do let spriteNode = new SKSpriteNode(texture) spriteNode.Position <- PointF(float32 <|r.Next 650,float32 <| r.Next 2000) spriteNode.PhysicsBody <- SKPhysicsBody.BodyWithCircleOfRadius 10.f scene.AddChild spriteNode //Add an immovable floor for the owls to bounce off let floor = new SKSpriteNode "Floor" floor.Position <- PointF(x.View.Bounds.Width / 2.0f ,0.0f) floor.PhysicsBody <- SKPhysicsBody.BodyWithRectangleOfSize(SizeF(640.f,32.f)) floor.PhysicsBody.AffectedByGravity <- false floor.PhysicsBody.Dynamic <- false scene.AddChild floor //Run the scene skView.PresentScene scene
Note the owls are all dynamic and affected by gravity and the floor is not.
The result of the above code is this rather impressive demo:
Half Life 2 eat your heart out!
This simple demo shows how easy it is to add sprites with realistic physics to a scene in SpriteKit. There are lots of properties to play with on the PhysicsBody, to adjust the mass, density, restitution and more.
I’ll walk through how to react when something happens (think play sound effect when 2 objects collide) and how to apply forces to add gameplay using touch control.