Improve UI/UX with gaming animations using SpriteKit

Matija Kruljac
Undabot

--

We all want our iOS applications to be user friendly and interactive as much as possible. To achieve this, we need interesting design and animations, but we do not want to add too complex animations which could take too long to execute and potentially ruin UX of the application, giving the opposite effect.

In this article I want to present an idea how to improve (change) business logic in applications using gaming animations. How to use such animations for this purpose will be presented in the example of this blog post. But first, I want to focus on business logic and its definition.

There is a very good definition of business logic on Wikipedia; Business logic or domain logic is that part of the program which encodes the real-world business rules that determine how data can be created, displayed, stored and changed. It prescribes how business objects interact with one another, and enforces the routes and the methods by which business objects are accessed and updated. In continuation of this blog post I’m going to provide an example app which can be improved (changed) with gaming animations and which can replace gamification part, but it will still use gamification elements.

Gamification

As it’s explained in this document, gamification refers to the use of game elements in a non-game context to increase the engagement between users and applications. It can be defined as a process of game thinking and game mechanics that engages users to solve problems. Gamification involves using game-based mechanics, aesthetics, and game thinking to engage people, motivate action, promote learning, and solve problems effectively.

Example app

For instance, lets imagine application with gamification elements. Business logic of this application would be:

  • application contains list of stores
  • every store can contain items on which customers can get discounts
  • to get discounts user have to redeem coupons
  • to redeem coupons user have to collect certain amount of points
  • to earn points, users have to physically go into stores and buy certain items which satisfy some conditions, for example, a condition can be a brand of an item, or a manufacturer etc.

Our Xcode project as example application will be called GameElementExample.

Adding gaming animations
To avoid case where user have to physically go to stores, we can add a little game (gaming animations) into our application. Business logic will be slightly changed, maybe improved. It depends on how strictly business logic was defined, but the main goal of earning points will still be the same. Now, last bullet of business logic for GameElementExample prior to adding game animations will be changed into:

  • to earn points user have to play (use) game for every store.

This little game would have the following roles with logic:
- cart - user is able to move it from one end of the screen to another.
- catalogs - fall from the top of the screen, which can be collected. Some of the catalogs fall faster, others slower. Faster ones bring more points if collected. Every catalog represents store catalog in reality. In this way stores can promote some actions, items or agenda.

Every game is time limited and timer is set so that user can see how much playing time is left. There is score label so that user can track how many points he won. Also, game can be paused and continued at any time.

Image 1 GameElementExample structure

In Image 1. you can see GameElementExample structure. It contains TabBarController with three tabs. The first tab contains list of stores from which you can navigate to GameViewController whose UIView actually contains a game.

Image 2 GameElementExample demo

In Image 2. you can see demo of our example application for this blog post. The only big difference from the application from the beginning of the story is that it contains game element.

And here comes the good use of iOS game development frameworks.

iOS frameworks

There are three native game development frameworks for iOS that you can use in applications (game) development and those are:

  • SpriteKit
  • SceneKit
  • Metal

Example in this article is made with SpriteKit. I’m going to explain through example the basics of SpriteKit, how to use it, main actors in the framework, and how user interaction could be hanged with this feature.

If we return to the application with gamification from the beginning, it contains logic where user needs to go to stores to earn points and redeem discounts. We are going to change this by adding gaming animations (game elements) using SpriteKit.

SpriteKit

SpriteKit provides infrastructure used to animate desired textures (shapes, images, etc.) which are also known as sprites. SpriteKit provides rendering loop for rendering contents and frames. SpriteKit is suitable for games and apps that require flexibility in how animations are handled. More details can be found on Apple’s documentation.

We are going to start with main SpriteKit actors. First of all, to use all of its features, we need to import SpriteKit framework into our project.

Now lets focus on the main elements of framework and their usage through GameElementExample project.

SKView
To draw game content (sprite content), I need Sprite View or SKView, which performs animations and rendering. All content is drawn by presenting scenes inside SKView. Below is a snippet of the code of how to create a SKView.

As we can see, only the frame needs to be passed as parameter in SKView’s constructor. SKView can be managed in views’ hierarchy just like any other UIView. GameElementExample contains only one SKView as game container.

SKScene
To organize game content I used scenes or SKScenes. A SKScene holds sprites and other content which will be rendered. Below is a snippet of the code of how to create a scene and present it. To create a scene you must set its size, also you can set its scaleMode. For debugging purposes you can set properties on SKView like ones shown in the snippet below.

GameElementExample contains three scenes: InitialScene, GameScene and TimesUpScene. InitialScene is the first scene in the scene hierarchy which will serve as an intro into the game of certain store. GameScene contains game and deals with user interactions. TimesUpScene indicates that the game is over due to the expiration of time. All these scenes are handles by the SKView as mentioned earlier.

SKTransition
For switching between scenes you can use SKTransition because game content is usually divided into scenes. Below is a snippet of the code of how to create transition with properties and use it in a scene presentation.

In GameElementExample I used SKTransition to navigate between scenes when certain condition is met, like tap on Play Button or expiration of game time.

SKNode
Nodes are the fundamental building blocks for all content. Even the SKScene class is a descendant of the SKNode class which acts as the root node for a tree of node objects. Nodes are organized hierarchically, similar to views and their subviews. A child node takes properties from its parent, but they can be overridden.

One of the most important properties of SKNode is physicsBody property which is of SKPhysicsBody type and it adds physics simulation to a node, which will be explained later.

SKSpriteNode
SKSpriteNode is a descendant of SKNode. SKSpriteNode draws a texture, an image, a colored square, etc. It represents characters in game, background elements, or even user interface elements which are added to the scene. Below is a snippet of the code of how to create SKSpriteNode with texture.

There are several constructors with which we can initialize SKSpriteNode. In the GameElementExample I’m going to use initialization with image. In this way our node will look exactly the same way as object represented by the image.

SKPhysicsBody
This object is assigned to the physicsBody property of the SKNode. It adds physics simulation to the node and its default value is nil, which indicates that the node does not participate in the physics simulation at all.

Below is a snippet of the code of how to create physics body with its properties for sprite node which I’ll explain next.

First, we have to create SKPhysicsBody with rectangle and add it as physicsBody of cart node. On this physics body we have to set:

  • categoryBitMask — a mask that defines which categories this physics body belongs to
  • contactTestBitMask — a mask that defines which categories of bodies cause intersection notifications with this physics body
  • collisionBitMask — a mask that defines which categories of physics bodies can collide with this physics body

isDynamic property is used as indicator whether physics simulation is applied to a physics body. Default value is true, but in GameElementExample isDynamic property is set to false for all nodes. In that case I can apply my own physics.

zPosition — with this property I’ve set node’s height (distance from node’s parent). It determines order of drawing and rendering nodes in parent or hierarchy of node’s children. Nodes with the same value of zPosition are equally distanced from the parent node.

After adding SKPhysicsBody to our SKSpriteNode, it can be affected by gravity and be able to collide with other nodes.

On the code snippet below we define physics categories which represents the types or categories of objects that will interact between each other and when your game is notified of these interactions. This is how you define the mask values used in the game of GameElementExample.

Custom forces and impulses can also be applied to a body (SKNode), which means that we can write our own physics for this object, which is not the case in GameElementExample project.

SKPhysicsWorld
To add general physics rules for scene (SKScene) and all of its children (SKNodes), we can create SKPhysicsWorld and set it as value of property physicsWorld. It simulates collisions and other physical properties. In GameElementExample I did not create my own physic but used default.

SKPhysicsContactDelegate
Contains methods our GameElementExample implements to respond when physics bodies come into contact. In GameElementExample those are cart and catalogs. Implementation can be seen on the code snippet below.

Protocol will respond when two physics bodies with overlapping contactTestBitMask values are in contact with each other in a physics world. The physics contact delegate methods are called during the physics simulation step.

SKPhysicsContact
Contains a description of the contact between two physics bodies. It is passed as parameter in didBegin(_:) method of SKPhysicsContactDelegate delegate. It contains bodyA (which is the first body in the contact) and bodyB (which is the second body in contact) properties and they are of SKPhysicsBody type.

To determine type of object (SKNode) in collision, we can use SKPhysicsBody’s categoryBitMask or name properties and compare them with a defined physics categories. In GameElementExample those would be PhysicsCategory.cart or PhysicsCategory.catalog which can be seen in the code snippet below.

SKAction
I used SKAction to create interesting effects and animations to make the game more beautiful and interactive. An SKAction object is an action that is executed by a node in the scene (SKScene).

For example, here are the most common things you can use actions for:

  • Changing a node’s position and orientation.
  • Changing a node’s size or scaling properties.
  • Changing a node’s visibility or making it translucent.
  • Changing a sprite node’s contents so that it animates through a series of textures.
  • Colorizing a sprite node.
  • Playing simple sounds.
  • Removing a node from the node tree.
  • Calling a block.
  • Invoking a selector on an object.

One interesting thing about actions is that many of them can be reversed. That allows you to reverse the effect of that action.

In the GameElementExample I used SKAction, for instance to create cart pulse animation when it’s collided with catalog, catalog rotations while they falling from top of the screen, increment of score effect when catalog is collected, etc. On the snippet code below we can see actions move up, scale up and fade out grouped together and executed at the same time.

Here I’ve added pulse up and pulse down actions into sequence, after which this sequence is repeated forever on playButton node. Every node has a run(_ :) method for executing SKActions.

For every SKAction you can add a key so that later in a scene (node) this action can be accessed or removed over defined key.

SKEmitterNode
One other interesting role in this project is SKEmitterNode. A SKEmitterNode object is a node that automatically creates and renders small particle sprites. Emitter nodes are often used to create sparks, fire, smoke, and other particle effects.

There are many properties that can be defined on SKEmitterNode which determine how our particle emitter will look like. Changing those values give us specific shape, color, speed of emitting, rotation, alpha, scale of particles, etc. Example can be seen on the code snippet below.

In the GameElementExample SKEmitterNode is used to create explosion effect (animation) on the store title when InitialScene is presented. This is imagined just like an example and effects like these are not fully polished.

SKTexture
I used SKTexture object as an image to apply it to SKSpriteNode object. Used SKTexture object is created from source images stored in the app bundle. Texture objects can consume a lot of memory, depending on the size of source data, so we have to be careful how we manage them.

You should always use textures whenever there’s a need to apply the same image to multiple sprites. Once initialized, texture can be used where it is needed. A snippet of the code below shows how to initialize SKTexture with image.

pause is name of the image inAssets directory of GameElementExample. Texture is used when creating scene’s background, cart, catalogs, labels and buttons.

Retrospective
We went through some of the main roles and terms of SpriteKit framework (there is a lot more of them). I’ve tried to explain how to use this framework without too much details, at the same time providing basics and definitions. For every role in SpriteKit I’ve provided a link to Apple documentation so if you want to know more, you can study it further and checkout every detail to get the full concept and powers of SpriteKit.

SpriteKit is very intuitive and easy to learn game development framework. In your games you can develop your own algorithms for game characters behavior and interactions between themselves. That’s the case in GameElementExample where I implemented behavior for cart movement, catalogs and their interaction. But I could also use another framework for this kind of stuff and it’s called GameplayKit.

GameplayKit

GameplayKit is also native and it can be imported when ever it’s needed. GameplayKit organizes and architects game logic. It brings common gameplay behaviors in game such as random number generation, artificial intelligence, pathfinding and agent behavior. GameplayKit is game-engine agnostic, and it works with SpriteKit, SceneKit, Metal, even UIKit… I’m not going to explain GameplayKit in this blog post because it would be even longer. It is a theme for another blog.

Conclusion

In my opinion SpriteKit is very good for development of games with less complexity if you mean to target only iOS users. But if you develop a game (not “in-app game” like it’s the case in GameElementExample of this blog post) a better option would be Unity, to also cover Android platform. Advantages of SpriteKit over Unity would be: it’s built right into iOS, it’s written by Apple and very well documented and it’s free. But it is not cross-platform and Unity is more powerful.

If we compare the GameElementExample without game animations from beginning and the GameElementExample with game animations, I can say that the GameElementExample with game animations have more dynamic UX and UI. Also, users immediately get feedback for their actions. They can track how many points they won and for which store they have to collect more points to get free coupons. On the other side, stores can promote their actions, agendas and items, for instance, over API, informing users in this manner and induce them to interact with application in a fun way which will cause better usability of an application.

On this link you can download the entire project GameElementExample which served as an example in this blog post. I hope I’ve made SpriteKit a little bit closer to you and inspired you to further research it.

Thanks to Sinisa Cvahte for the design.

Thank you for reading. Please comment, like or share it with your friends and we hope to see you soon.

Would you like to join us? Check out the open positions at our Careers page.

Undabot and Trikoder are partner organisations. We analyse, strategise, design, code and develop native mobile apps and complex web systems.

--

--