iOS 8: What's New in SpriteKit, Part 2

This tutorial gives an overview of the new features of the SpriteKit framework that were introduced in iOS 8. The new features are designed to make it easier to support advanced game effects and include support for custom OpenGL ES fragment shaders, lighting, shadows, advanced new physics effects and animations, and integration with SceneKit. In this tutorial, you'll learn how to implement these new features.

Series Format

This series is split up into two tutorials and covers the most important new features of the SpriteKit framework. In the first part, we take a look at shaders, lighting, and shadows. In the second part, I'll talk about physics and SceneKit integration.

While each part of this series stands on its own, I recommend following along step-by-step to properly understand the new features of the SpriteKit framework. After reading both parts, you'll be able to create both simple and more advanced games using the new features of the SpriteKit framework.

Download the Xcode project we created in the previous article from GitHub if you'd like to follow along.

1. Physics

In iOS 8, SpriteKit introduced new physics features, such as per-pixel physics, constraints, inverse kinematics, and physics fields.

Kinematics is the process of calculating the 3D position of the end of a linked structure, given the angles of all the joints. Inverse Kinematics (IK) does the opposite. Given the end point of the structure, what angles do the joints need to make in order to achieve that end point? The following image clarifies these concepts.

Inverse Kinematics

With SpriteKit, you use sprites to represent joints that use the parent-child relationship to create a joint hierarchy. For each relationship, you define the inverse kinematics constraints on each joint and control the minimum and maximum rotation angle between them. Note that each joint rotates around its anchor point.

Step 1: Inverse Kinematics (IK)

Open the PhysicsSceneEditor and add the croquette-o.png sprite to the yellow rectangle. Select the sprite and change Name in the SKNode Inspector to Root. Set the Physics Definition Body Type to None.

Add a second sprite, wood.png and change its Name to FirstNode. Change the Parent field to Root. Move FirstNode by putting it on the right of Root and resize it to create a rectangle as shown below. Set the Physics Definition Body Type to None.

The result should look similar to the following scene.

Note that, when you select a sprite node, a white circle appears at its center. That circle represents the sprite node's anchor point around which every rotation is performed.

Anchor point

Step 2: Add More Sprites

Follow the previous steps and add two more sprites.

First Sprite

  • Add another croquette-o.png sprite.
  • Change its Name SecondNode.
  • Change its Parent to FirstNode.
  • Position it on the right of FirstNode.
  • Change its Physics Definition Body Type to None.

Second Sprite

  • Add another wood.png sprite.
  • Change its Name field to ThirdNode.
  • Change its Parent to SecondNode.
  • Position it on the right of SecondNode.
  • Resize it to create a rectangle.
  • Change its Physics Definition Body Type to None.

The result should look similar to the following scene.

Resulting image

Step 3: Edit and Simulate

To test the joint connections, interactions, and constraints, you don't need to build and run your project. Xcode provides two modes, edit and simulate.

The simulate mode provides a real time testing environment while the edit mode is used to create and edit your scene. So far, we've been working in the edit mode. Note that any changes you make in simulate mode are not saved.

At the bottom of the scene editor, you can see which mode you are currently working in. If the bottom bar of the scene editor is white, then you're in edit mode. A blue background indicates you're in simulate mode. Click the label in the bottom bar to switch between the two modes.

Simulate mode
Edit mode

Change the mode to simulate and select the FirstNode, SecondNode, and ThirdNode sprites. You can select multiple sprites by pressing Command.

Next, press Shift-Control-Click and move the sprites around in the scene. The result is that the sprite nodes animate and rotate. However, the rotation is weird and needs to be corrected.

Step 4: IK Constraints

Switch back to edit mode and add a few constraints to the sprite nodes. Select each sprite node and change its properties as follows.

Select the Root and SecondNode sprite nodes and set the IK Constraints Max Angle to 0. Select the FirstNode and ThirdNode sprite nodes and set  Anchor Point X to 0 and IK Constraints Max Angle to 90.

By modifying these properties, the position and size of the sprite nodes will change. After adding the constraints, manually adjust their size and position, and switch to simulate mode to test the new constraints we added.

The below screenshot illustrates the correct constraints configuration.

Constraints in action

Step 5: Magnetic Field Node

Magnetic fields are also new in SpriteKit. Let's see how this works by adding a magnetic field to the physics scene. Open PhysicsScene.m and an instance variable named magneticFieldNode of type SKFieldNode.

In the didMoveToView: method, we first configure the scene by creating a SKPhysicsBody instance for the scene and adding a gravitational force. This means that any nodes in the scene will be pulled downwards.

To configure the magneticFieldNode object, you need to configure its physics body as well as its position and strength. Note that each SKFieldNode has its own properties. The following code snippet shows how to configure the magnetic field node. We add the new node as a child node to the scene.

Step 6: Interactions

To see the magnetic field in action, we need to add a few nodes with which the magnetic field note can interact. In the following code snippet, we create three hundred sprites. Note that each sprite node has its own physics body and we set the affectedByGravity property to YES.

The completed didMoveToView: method should look as follows:

Before we build and run the application, we override the touchesMoved:withEvent: method so you can move the magnetic field node by tapping your finger.

Build and run the application to test the magnetic field node's effect on the scene. For additional information about simulating physics using the SpriteKit framework, I recommend reading Apple's documentation about this topic.

2. SceneKit Integration

SceneKit is a high-level Objective-C framework for building applications and games that use 3D graphics. It supports the import, manipulation, and rendering of 3D assets. The rendering algorithm only requires the description of your scene's contents, animations, and actions you want it to perform.

Through SceneKit, you are now able to create and deliver 3D content using SpriteKit. SceneKit has a tree structure and can be used in two ways:

  • standalone SceneKit environment
  • integrated into SpriteKit

SceneKit has a tree hierarchy composition. In a standalone SceneKit environment, the base class for the tree structure is an SCNNode instance as shown in the diagram below. An SCNNode object by itself has no visible content when the scene containing it is rendered. It simply defines a position in space that represents the position, rotation, and scale of a node relative to its parent node.

SceneKit hierarchyt

When you integrate SceneKit into a SpriteKit-based app, you need to define a SK3DNode object as the root object for your scene. This means that the core SceneKit hierarchy changes to the following:

SceneKit  SpriteKit hierarchy

Note that not every child node in the above diagram is required. You only define and configure the nodes that fit your needs. For instance, you can add an SCNLight node to illuminate the scene even if you don't include an SCNCamera node in the scene.

Step 1: Live Preview of Models

SpriteKit and SceneKit support a number of file formats for importing models. You can preview these models in real-time in Xcode. Inside the Textures folder in your project (Resources > Textures), there's a file named ship.dae. When you select this file, you're presented with a new user interface as shown below.

Xcode live preview

On the left of the editor, you can see two groups:

  • Entities: This group contains information about the predefined animations, camera position, lights, and materials defined by the model file. The file we've opened only contains information about the model's geometry and its material.
  • Scene graph: This group contains information about the original object mesh. In this case, the object was created as a whole and you only see a single mesh.

Step 2: Importing an External Model

To use SceneKit in combination with SpriteKit, you need to import the SceneKit library from the SceneKit framework. Open SceneKitScene.m and include it as shown below.

We're going to use the model stored in ship.dae as the 3D scene. Inside the didMoveToView: method, create the SCNScene object that loads a scene from that file.

Remember the tree hierarchy I mentioned earlier? To add the shipScene object to the SKScene object, two steps are required:

  • create a SK3DNode object
  • define a SceneKit scene to render

In this case, the scene to render is the shipScene. Note that you also define the node's position and its size.

Finally, add the SK3DNode object as a child node to the SKScene object.

To make the final result a bit more appealing, set the scene's background color to green as shown below.

This is what the complete didMoveToView: method should look like. Build and run the application to see the result.

Step 3: Creating a Custom Scene

Let's create a more complex scene that contains several SCNNode objects. For this second scene, we need to create another SK3DNode object.

Next, we create the SCNScene object, the one that will contain the scene child nodes.

This sceneObject will have three nodes:

  • Camera: This node is used to view the scene through a given position.
  • Light: This node enables you to see different material properties of the 3D object. You normally  define the light type and color.
  • 3D object: This is the imported or defined object within your code. By default, SceneKit enables you to define several parametric 3D objects, that is, torus, box, pyramid, sphere, cylinder, cone, tube, capsule, floor, 3D Text, or a custom shape.

For each individual node, you always perform three actions. Let's take the camera node as an example.

  1. Create an SCNCamera object and define its properties.
  2. Create an SCNNode to which the SCNCamera will be assigned.
  3. Add the SCNNode as a child node to the SCNScene object.

Let's now create the three nodes I mentioned earlier. This is what we need to implement to create the camera node.

By default, the camera location and 3D scene are located at the origin, (0,0,0). Using the position property, you can adjust the camera along the three x, y, and z axes to change its position.

The light node requires a little bit more work, but the following code snippet should be easy to understand.

We'll also create a torus object as shown in the following code snippet.

Finally, we set the scene that we want to render and add the sk3DNode as a child node of the SKScene instance.

This is what the final didMoveToView: method should look like.

Build and run the application. You should see something similar to the following screenshot.

Final result

Step 4: Animating the Scene

You can animate the scene using the CABasicAnimation class. You just need to create an instance of CABasicAnimation by invoking animationWithKeyPath:. The animation we create in the following code snippet will loop indefinitely and has a duration of five seconds. Add the following code snippet to the didMoveToView: method.

Build and run the application to test the animation.

3. More SpriteKit

If you want to learn more about SpriteKit, then I encourage you to read the following SpriteKit tutorials:

If you'd like to read more about the SpriteKit framework, then I recommend reading Apple's SpriteKit Programming Guide or browsing the framework reference.

Conclusion

This concludes the second tutorial of this two-part series on the new features of the SpriteKit framework introduced in iOS 8. In this part, you learned how to use physics simulation and integrate SceneKit. If you have any questions or comments, feel free to drop a line in the comments.

Tags:

Comments

Related Articles