iOS 7 Sprite Kit: My Top 5 Pros and Cons

Sprite Kit is the new “graphics rendering and animation infrastructure” from Apple, which came out with the release of iOS 7. It provides similar functionalities to existing Open Source projects like Cocos2D and Sparrow, but in addition to being just a graphics engine, it also includes physics support out of the box. It is very easy to build complete physics powered games using Sprite Kit, but this simplicity also comes with it’s downsides, as you’ll see in this post.

We have recently finished our first Sprite Kit game for the iPhone: Tapathon! Touch Racing.  Having now built a complete game using Sprite Kit, I want to share my first experiences and feelings about it.

Pros

1. Intuitive and easy to use API

Having an Adobe Flash background, it was very easy for me to jump right into Sprite Kit. Game objects are organized in a tree structure and every object inherits from SKNode. There are all kinds of SKNodes: SpriteNodes which render Rectangles or Textures, ShapeNodes which render arbitrary shapes, EmitterNodes for particle systems and so on. Very straight forward.

2. Built in physics engine

Every SKNode also has a property named physicsBody, which brings things to life. Just as expected, physical bodies can consist of arbitrary shapes like rectangles, circles, polygons, paths and so on. The API is very similar to the popular physics engine Box2D and it’s built right into Sprite Kit. It’s just so easy and intuitive! Wow!

3. Particle system

The particle system is probably the coolest thing about Sprite Kit. You get the WYSIWYG Editor built right into XCode – no need to jump between IDE and external or web based tools to design your particles. The particle system is really feature rich and flexible. Any aspect can also be changed by code during the animation and you can even add custom actions to each particle created.

4. Node searches

Sprite Kit provides an interesting feature called advanced searches. With advanced searches you are able retrieve named nodes from the tree that match queries specified in Sprite Kit’s own search syntax. It is possible to search descendants recursively or search parents up to the root and include wildcards in your query. I find this feature very interesting and have not seen such a thing in game frameworks before. However, I have not made much use of it yet.

5. Action system

I’ve never used Cocos2D, but I know that the concepts behind Sprite Kit’s action system are borrowed from Cocos2D and I really like it. I am used to tweening engines like the one Sparrow uses and find the action system to be a bit more precise and easy to use. You can also create complex animation-chains and even reverse them. I am only a bit disappointed by the provided timing modes since the only existent modes are linear, easeOut, easeIn and easeInOut. I am missing things like bounce, back or elastic.

Cons

1. No custom shaders

This may not be a big drawback for the average game, but since we cannot plug in any custom render code, we will eventually hit the visual limits of Sprite Kit. For custom rendering we still require an open source framework, or must write our own game engine on top of OpenGL ES.

UPDATE: Custom shaders will be supported in iOS 8!

2. No predictable physics

The physics system adjusts it’s running speed according to the framerate. This means that if your simulation runs on a slower device, which cannot draw at the full framerate of 60 FPS, it will adjust it’s increments to keep up with the speed. This sounds like a good thing in the first place. The downside of this is that the physics will become more and more unstable, the more the framerate drops.

Tapathon! Finish Screen

Tapathon’s physics-based finish screen. Left image: Desired result. Right image: Different simulation results due to low framerates

While the example shown might be a bit extreme (60 FPS vs 3 FPS), there are genres where even small differences in the simulation cannot be accepted. One of the most well-known solutions to this is to use a fixed timestep. I could not find out how I could enable this in Sprite Kit.

3. Limited extensibility

For larger projects it’s appealing to subclass SKNode and to provide your own reusable node classes – even Sprite Kit’s documentation suggests to do so. It’s just very disappointing that this is so limited. Correct me if I am wrong but I couldn’t figure out any clean way to get notified when the node is being added or removed from a parent node, so you have neither access to the parent node, the scene nor the physics world – the latter will deny you from placing physical joints within the node. Even worse: there seems to be no update or render method to override.

4. No scene stacking

Sprite Kit can only present one scene at a time. I would rather have a scene stack where I could push/pop scenes to and maybe have multiple scenes running at once. However this would make Sprite Kit more complex, so in this point I am a bit unsure.

5. Existing pitfalls

Some things in Sprite Kit don’t work as expected:

  • Multi-tasking: If your game is pushed into the background, Sprite Kit won’t automatically pause your game correctly, instead, it will just crash with EXC_BAD_ACCESS (gpus_ReturnNotPermittedKillClient). This means you have to do this by yourself. That’s not that big a deal, it’s just a bit disappointing that it’s not included out of the box in a framework that aims for simplicity.

  • Stretched Textures: SKSpriteNodes support a centerRect property which you can use to make your texture stretchable in a Scale-9 grid. But beware! This feature does currently not work as expected, the result looks like crap! I hope Apple will solve this soon.
    UPDATE: Use the setXScale and setYScale methods and it will work just fine. I was reassigning the size property, which did not actually scale the sprite, but re-assign the native size of the sprite

    centerRect will not scale as expected

    centerRect will not scale as expected

  • Scene Setup: Setting up the coordinate system correctly for the scene is not very well documented and the correct solution is not very intuitive. Please check out the post from my colleague Thomas.

Conclusion

I really like Sprite Kit. It’s the perfect fit for small games such as Tapathon and most likely also some bigger projects. I guess that at some point it will stop being so useful because of it’s limited extensibility and for some genres, the physics system will just not be stable enough. However I really like its simplicity and expressive API – you can create simple game prototypes in no time.

  1. To stretch textures the way you expect, just remove filtering….

    • Maybe the Sprite would look a bit better that way, but I guess it would still be stretched instead of having actual round corners.

      However in the meantime I did find out what I made wrong: It turned out that I was using the wrong method to scale the sprite. I reassigned the sprite’s size instead of using the setXScale and setYScale method. Reassigning the size property worked in an early beta version, but stopped working when iOS 7 was released, so I thought that it has to be a bug in Sprite Kit. I reported it and Apple told me to use the setXScale and setYScale method instead. I forgot to update the article, sorry about that.

  2. Hi,Could u please tell me How I can pause my game when application did enter background?
    I am a newer in developing IOS and Game.Thank you!
    (I can’t find any answer about “gpus_ReturnNotPermittedKillClient” crash);

    • Hi Kevin,

      SKScene has a paused property.
      You can toggle this in your AppDelegate’s applicationWillResignActive and applicationDidBecomeActive methods.

      Hope that helps?

  3. Why don’t you try to report the bug you’ve found in Sprite Kit to Apple if you’re really sure at your findings?  You can do it easily by reaching http://bugreport.apple.com/.

    • Thanks for that advice, however I did that already months ago. I didn’t check whether it’s fixed now.

  4. Cons #3 and #4 are things that Kobold Kit (http://koboldkit.com) adds to Sprite Kit, and con #2 is fixable (see below).

    Notifications

    To get notified of a node being added or removed from its parent (and to have valid self.parent and self.scene objects to work with) Kobold Kit nodes can implement the following methods:

    /** Called after addChild / insertChild. The self.scene and self.parent properties are valid in this method. */
    -(void) didMoveToParent;
    /** Called after removeFromParent and other remove child methods. The self.scene and self.parent properties are still valid. */
    -(void) willMoveFromParent;

    Override didMoveToParent and your node can access the parent, scene and the scene’s view and physicsWorld. In other words this is where you’d put code that requires the node to be “fully initialized”.

    In Kobold Kit you can also “observe” events that the scene receives, classified into three categories: scene, physics and input events. In your custom node you would implement the same methods as in the scene, for example didSimulatePhysics or touchesBegan:withEvent: or didBeginContact: and so on.

    To actually receive these events the node has to subscribe itself as an observer for one of the three types of events, via:

    [self observeSceneEvents];
    [self observePhysicsContactEvents];
    [self observeInputEvents];

    Pushing & Popping Scenes

    Kobold Kit implements a scene push/pop stack more flexible than the one in cocos2d. For example you can both push AND pop scenes with a transition, you can replace a currently pushed scene (replace top of stack), you can unwind the stack to the root scene (popToRoot), and pop to a specific scene with a given name. So you can push 5 scenes and return to the 2nd if you know its name.

    Behaviors

    Kobold Kit’s behaviors are code plugins (aka components) that you can add to any node. This allows you to extend nodes without having to subclass them, which has always been a particularly restrictive way of extending nodes in cocos2d as well. Take for example cocos2d’s CCPhysicsSprite class – who is to say I wouldn’t want physics on a label or particle node? Normally you’d have to subclass those as well.

    With behaviors you can just write the code that works once for any node, possibly with special cases for specific classes. For example there’s a “stay in bounds” behavior which keeps the node’s position within a rectangle (ie the screen), but if the node that contains this behavior is a SKSpriteNode it considers the node’s size as well so it won’t leave the screen half-way.

    With behaviors you can even implement custom physics. Create a “physics body” behavior that manages a physics engine’s body and in the didSimulatePhysics (which Sprite Kit will send out regardless of whether its internal physics did anything or not) apply the body’s position and rotation to the node. Voila, you have custom physics. And to wrap the custom “physics world” you’d create a corresponding behavior wrapping the world and add it to the scene, again as a behavior. Do that and you can strike off con #2 from your list. ;)

    OpenGW

    Since I’m currently very busy creating OpenGW (http://opengameworld.com) I hope someone picks up some of these ideas (custom physics, iso tilemap, etc) and adds them to Kobold Kit. I’ll gladly give anyone push/pull access who wants to contribute to making Sprite Kit better.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">