Roll SpriteKit Node Around Phone Screen Using Core Motion Accelerometer Data

Elina Lua Ming
The Startup
Published in
5 min readJan 13, 2020

This was a fun little project I made to learn about SpriteKit and Core Motion, and I think it gives a cool visual effect. In this iOS project, we’ll use SpriteKit and Core Motion to create a node that will roll around the phone screen using data from the accelerometer.

Hamtaro rolls around as we tilt the phone.

Here’s an outline of the article:

  1. Set up project
  2. Set up Game View Controller
  3. Set up Game Scene
  4. Refactor Code

Set up Project

First, let’s set up our project. Open Xcode, go to FileNewProject to create a new project. Then select the Game template under the iOS tab. Next, name your product, and make sure to select SpriteKit as the Game Technology.

Since we won’t be needing the default SpriteKitScene files for this project, we can delete the two .sks files that Apple provided us with.

Set up Game View Controller

  1. In viewDidLoad, we downcast view into SKView. In the if let block, we initialize a GameScene with size equivalent to the bounds of the View Controller. Then, we set the scene’s scaleMode to fill. This ensures that each axis of the scene is scaled independently so that each axis maps exactly to the length of the view axis.
  2. Next, we configure the view’s UI properties such as showsPhysics, showsFPS, and showsNodeCount. We can always adjust these Boolean values after.
  3. Lastly, we let the view present the scene.

Set up Game Scene

First, let’s remove all the default code that Apple provided us with in GameScene.swift. We will only be using didMove and update method. We should also clear the code in the didMove method.

didMove will be called when your scene is about to be presented by a view. Here, we can create the scene’s contents.The update method tells the app to perform any customized logic to update the scene. This method is called by the system exactly once every frame, as long as the scene is presented in a view and is not paused. This is the first method that will be called when animating the scene, before any actions or physics are run.

Now that we have a blank canvas, we can import an image into the Assets.xcassets folder that we’d like to use as the texture of our SpriteKit node. In my case, I will use a random image of my favorite hamster — Hamtaro!

At the top of the GameScene class, we initialize our Hamtaro SpriteNode:

Next, we set the initial position and size of Hamtaro. I chose to set mid screen as its initial position. Then I added the hamtaroSpriteNode as a child of the GameScene class.

Here we can also give hamtaroSpriteNode some physics properties. To do so, we must first give it a physicsBody by creating an instance of SKPhysicsBody. In order to make the hamtaroSpriteNode’s movement realistic, we can set its allowsRotation property to true, and give a restitution value of 0.5. Restitution value is used to determine how much energy the physics body loses as it bounces off another object.

At this point, running our code would give us a Hamtaro that falls out of the phone screen into… the abyss, and never to be found again. In order to avoid this from happening, we must transform the frame of the phone screen into “walls”. We can do this by giving the gameScene a physicsBody too!

To give the GameScene a physicsBody, we provide the GameScene’s physicsBody property with an instance of SKPhysicsBody. Here, we transform the scene’s edge so that it may collide with volume-based physics bodies.

At this point, running our code would give us a Hamtaro that falls towards the bottom of the screen. However, if we tilt or shake the phone, we are still unable to make it roll around. In order to manipulate the gravity of the hamtaroSpriteNode, we must update its gravity property to reflect the instantaneous acceleration of the device in space.

To obtain the real-time acceleration value, we must import the CoreMotion framework. This framework will give us access to a motion manager, from which we can get the device’s motion data, like the device’s accelerometer data.

At the top of the GameScene class, we initialize an instance of CMMotionManager()

In didMove function of the class, we include a line that lets the manager begin accelerometer updates.

Now, in the update method, we unwrap the accelerometer data with an if let statement. Then we set the gravity property of the game scene’s physicsWorld class with the accelerometer data in the x and y axes. Here we can multiply the acceleration value with any multiplier; I chose 9.8 because I feel that it mimics realistic movements best.

Now let’s build and run the project on a device. Tilt the device and we’ll see Hamtaro rolling around in the phone!

Refactor Code

Lastly, we clean up the project with some final touches. First we can refactor the code. The code is mainly separated into three parts: setting up hamtaroSpriteNode, setting up GameScene, and getting accelerometer data updates. Thus, let’s put the lines for hamtaroSpriteNode and GameScene into separate functions. We’ll call them setupHamtaro and setupGameScene. I like to put these helper functions into an extension, because I like to organize my code this way — but this is optional!

Lastly, in order to make the phone appear really like a box, we can set these view properties in the view if let block in GameViewController to false.

Now, when we run the project again, the device looks exactly like a box. Hamtaro is just in there rolling around!

Hope you find this introduction to SpriteKit article clear, fun, and helpful. Have a beautiful day ahead!

Disclaimer: I did not create Hamtaro. It’s just a favorite childhood hamster anime of mine.

--

--

Elina Lua Ming
The Startup

iOS Developer, USAPL Powerlifter, 4th year student at UCLA. I write on iOS development and philosophy. https://github.com/ardentlycurious101