SpriteKit and Inverse Kinematics with Swift

In this tutorial, learn how to use Sprite Kit’s inverse kinematics to make a ninja punch and kick dynamically! By Jorge Jordán.

Leave a rating/review
Save for later
Share
Update 9/30/16: Updated for Swift 3, iOS 10, and Xcode 8 by Ray Wenderlich. Original tutorial by Jorge Jordán and Ken Toh.

If you’ve ever added an animated character to a game, you probably pre-created animations for running, punching, jumping and so forth, and played them when the game executes the associated actions.

While this “canned” approach works for simple scenarios, there are often cases where you’d prefer your character to interact more realistically with other game objects.

For instance, if your character needs to reach out to pick up a nearby object at a variable height, you may not want to use the same animation for every picking action, or it could look really silly when the predefined hand motions don’t line up exactly with the object’s position!

Since iOS 8, Sprite Kit comes with inverse kinematics, a technique that alleviates this issue by allowing you to procedurally generate joint motions such as reaching out to a point in space. This means you don’t have to resort to making a possibly infinite number of animations to reach every possible position.

In this tutorial, you’ll learn how to use Sprite Kit’s inverse kinematics feature to implement dynamic punches and kicks in a fun and simple ninja game. :]

In particular, you’ll learn how to:

  • Set up joint hierarchies in the Sprite Kit Scene Editor.
  • Define joint constraints for more realistic joint behavior.
  • Dynamically animate selected joint hierarchies such that the terminal bones can reach out to various positions in 2D space.

Let’s get moving!

Note: This Swift tutorial assumes you have working knowledge of Sprite Kit and Swift. If you’re new to Sprite Kit, check out our Sprite Kit Swift Tutorial for Beginners or our full book, 2D Apple Games by Tutorials. For an introduction to Swift, check out this beginner Swift tutorial.

Getting Started

Download the starter project, open it in Xcode and build and run it. You’ll see a static ninja already set up in the middle of the scene, begging to be released from his yoga stretch.

Introducing a new iOS Framework: YogaKit!

Introducing a new iOS Framework: YogaKit!

Take some time to familiarize yourself with the structure of the sample project. In particular, select GameScene.sks in your project navigator. The file should open up in the integrated Sprite Kit Scene Editor:

SceneEditor

Note: Xcode’s Scene Editor provides a convenient user interface for initializing a scene by allowing you to visually manipulate your sprites and their properties such as position, scale and physics bodies. Later, you can create SKScene objects by unarchiving the .sks files you configured in the Scene Editor.

In the following steps, you’ll take advantage of the Scene Editor to set up and tweak the behavior of the joint hierarchy for your ninja, which would be difficult to visualize and set up programmatically.

Overview of Skeletal Hierarchy

In the scene, you can see that the ninja already has a basic skeleton comprised of a hierarchy of bones, each represented by a sprite node. The nodes are connected in a tree of parent-child relationships, as depicted below:

Skeletal Hierarchy of Ninja

The lower torso node, in red, is the root parent of the entire skeleton hierarchy, which in turn is a child of the scene itself.

The anchor point for each sprite node acts as a joint connecting the node with its parent. These have been adjusted with an offset so that one end of the node can rotate naturally about the joint.

Setting up a Rest Pose

While the ninja looks cool in that mid-air pose, you unfortunately aren’t building a game involving levitation, so you’ll have to bring him back to earth.

Let’s start by adjusting the legs so they touch the shadow on the ground. In the scene, select the front upper leg node, leg_upper_front, by either clicking on it directly, or selecting it from the scene navigator. After you select it, make sure the Utilities panel is open, displaying the Attributes inspector (the third tab).

AttributesInspector

Set the rotation of leg_upper_front to -14. You can do this either by rotating the handle of the selected sprite or by setting the Rotation property manually in the editor, as shown below:

Properties

Note: Some of the other values (such as position) may be slightly different for you than this screenshot; just make sure the Rotation is -14 and you should be good!

Next, select leg_lower_front and set its rotation to -9 to keep it slightly bent backwards.

Moving on to the back leg nodes, set the rotations of leg_upper_back and leg_lower_back to 22 and -30, respectively. You should see the following:

Adjusting the legs

Now that your ninja is finally standing, let’s work on the arms. Set the rotation angles of both upper arm nodes, arm_upper_front and arm_upper_back, to -10. Also, set the rotation angles of the lower arm nodes, arm_lower_front and arm_lower_back, to 130.

You should see the following:

Rest Pose

Finally, you’re going to do some housekeeping to ensure that the ninja and the shadow always stays centralized, regardless of the screen size. (Currently, the ninja would be off-center on the iPad 2.)

Switch to GameScene.swift and add the following code within and at the top of the GameScene class:

//1
var shadow: SKNode!
var lowerTorso: SKNode!

In didMoveToView(), add the following code:

//2
lowerTorso = childNode(withName: "torso_lower")
lowerTorso.position = CGPoint(x: frame.midX, y: frame.midY - 30)
 
//3
shadow  = childNode(withName: "shadow")
shadow.position = CGPoint(x: frame.midX, y: frame.midY - 100)

Let’s go through what you just did:

  1. You create two SKNode properties to reference the shadow node and lower torso node (the root node of the ninja), respectively.
  2. You obtain a reference to the lower torso node by its name, “torso_lower”, and assign its value to the lowerTorso property. Next, you set its position to the center of the screen with an offset of -30 units.
  3. Similarly, you grab a reference to the shadow node by its name, “shadow”, and assign its value to the shadow property. Finally, you set its position to the center of the screen with an offset of -100 units.

Build and run the project, and you’ll see your ninja in its rest stance, ready for a fight!

Ninja is ready!

With the joint hierarchy all set up and your ninja ready for action, you can begin using Sprite Kit’s inverse kinematics feature to deploy some serious martial arts.

Jorge Jordán

Contributors

Jorge Jordán

Author

Over 300 content creators. Join our team.