Become an iOS gaming master with SpriteKit, SceneKit and GameplayKit

If you haven't yet picked up 2D Games by Tutorials (an amazing book about SpriteKit and GameplayKit that I helped co-author). Then there has never been a better time to check it out with this incredible combo including the new 3D iOS Games by Tutorials.

Learn all about the amazing features of SceneKit and make your own crossy roads style game. Some amazing content for anyone looking to start SceneKit.

Get it now

Create a scene helper class for iOS / Mac cross platform SpriteKit games

There was a lot of interest in my post giving a few vague suggestions for converting a sprite kit game from iOS to Mac. Since then I've refined my methods a bit and now work with a project which is targeted for both iOS and Mac to make it even easier to implement and test.

Even if you never plan to release your game on Mac OS X, the below is still useful. The iOS simulator is painful at times however running SpriteKit natively on the Mac is simply beautiful, it makes testing a lot more fun.

Getting Started

The first thing you need to do is make a project containing both a target for iOS and for Mac OS.

  1. Create a new Xcode project
  2. Select "Sprite Kit Game" from the iOS templates
  3. Give it a name
  4. Go to "File", "New", "Target..."
  5. Select "Sprite Kit Game" from the Mac templates

You now have a template containing both two targets. If you are familiar with both Mac and iOS development it shouldn't take you too long to work out what is going on here. Have a look at your schemes and project settings.

I like to arrange my folders so that my Mac only code is in a "Mac" folder, the iOS only code is in a "iOS" folder and the shared game is in a "Shared" folder.

You can control which target has access to which game files via the "Target Membership" settings in the file inspector on the right.

Platform specific code

In iOS you are probably familiar with performing different code specific you wether you are running the application on an iPhone or iPad. You will run in to the same problems when coding for both Mac and iOS.

There are a lot of differences in the way you code between both platforms, even which classes you are using, so in most cases a standard IF statement won't be enough and you will need pre-processor #IF statements.

Example:

#if TARGET_OS_IPHONE
#endif

There is also a TARGET_OS_MAC but you will probably find that iOS devices respond to this as well, so it is a lot easier to just check !TARGET_OS_IPHONE.

It's a different world

Before going any further it is worth noting that you are working in two different worlds governed by two different HIG documents. What you know in iOS may not apply to Mac development. 

You are also working with a touch screen device without keyboard and a mouse and keyboard operated device. This is a simple fact but it will show in your game if you don't pay attention to it. I had an app rejected at review once for the reason my start screen said "Tap anywhere to begin" instead of "Click", a rather embarrassing mistake but one I make sure to prepare better for now.

Ok, enough of the lecture, you all want the helper class right?

A scene helper class to get you started

This is a very simple class but I want you guys to take it and add your own code to it. If your game uses a onscreen DPAD on iOS then it makes no sense do the same on Mac, you would need to monitor key presses instead.

This class helps for all other cases, it allows you to single methods for handling both screen clicks and screen taps. Great for games where screen presses translate easily in to screen clicks.

Create a class called SKMScene that inherits from SKScene.

Put the below in SKMScene.h:

// Created by Neil North on 6/02/2014.
// Copyright (c) 2014 Neil North. All rights reserved.
//

#import

@interface SKMScene : SKScene


//Screen Interactions
-(void)screenInteractionStartedAtLocation:(CGPoint)location;
-(void)screenInteractionEndedAtLocation:(CGPoint)location;

@end

And the below in the SKMScene.m file:

// Created by Neil North on 6/02/2014.
// Copyright (c) 2014 Neil North. All rights reserved.
//

#import “SKMScene.h”

@implementation SKMScene

-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
/* Overridden by Subclass */

}
return self;
}

#if TARGET_OS_IPHONE
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
[self screenInteractionStartedAtLocation:positionInScene];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
[self screenInteractionEndedAtLocation:positionInScene];
}

- (void)touchesCancelled:(NSSet *)touches
withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
[self screenInteractionEndedAtLocation:positionInScene];
}
#else
-(void)mouseDown:(NSEvent *)theEvent {
CGPoint positionInScene = [theEvent locationInNode:self];
[self screenInteractionStartedAtLocation:positionInScene];
}

- (void)mouseUp:(NSEvent *)theEvent
{
CGPoint positionInScene = [theEvent locationInNode:self];
[self screenInteractionEndedAtLocation:positionInScene];
}

- (void)mouseExited:(NSEvent *)theEvent
{
CGPoint positionInScene = [theEvent locationInNode:self];
[self screenInteractionEndedAtLocation:positionInScene];
}
#endif

-(void)screenInteractionStartedAtLocation:(CGPoint)location {
/* Overridden by Subclass */
}

-(void)screenInteractionEndedAtLocation:(CGPoint)location {
/* Overridden by Subclass */
}

@end

That's it, now all you have to do is make sure all your scenes inherit from SKMScene instead of SKScene and implement the two screenIntereaction methods.

There's a lot more to this process and I'm only just starting to learn to make cross platform games myself but I hope the above tips have helped you on your journey. Give it a go and see what you think.

You can also download a sample project on GitHub.

Converted a SpriteKit game from iOS to OS X

My February game for my one game a month challenge is now complete and in apple's hands for approval. In designing this game I always intended it to be available for both iOS and OS X even though I knew nothing about OS X development. I expected the conversion to be a complete disaster but everything actually went better than expected...

My preparations were actually quite simple:

  • Minimised usage of UIKit until it was nearly completely unused.
  • Made sure to use % of self.size coordinates instead of hard coded coordinates where possible.
  • Made sure that any variables or defined code that relied on device type or screen size to be stored in my constants.h file so it could be easily modified.

As you can see, my preparations were rather minimal. We are talking about a very small time investment in order to get my game on another platform.

The conversion itself was rather painless:

  • I created a new Mac OS X Sprite Kit project and dumped my game in to it.
  • Setup the appDelegate to point to my first game scene.
  • Went through each scene replacing Touch events with Mouse click events.
  • Fixed links to plists, the way I referenced them in iOS didn't work for Mac OS, I believe using the code I changed it to in iOS as well will resolve this issue in the future.
  • Fixed some game center differences.
  • New Icons, profiles, settings, etc

The process took less than 4 hours and in the future I expect it to be a lot quicker now that I have learnt a few things. I plan to make all future SpriteKit games completely cross platform (assuming Mac OS X sales will be reasonable).

I know this post was vague, drop me a line if you want a tutorial.

Design your app for localization from day one

Something which had been more of an afterthought for me in the past had been Localization, I figured there were enough english speaking iOS users out there for my business to be profitable. In retrospect this was a rather uncultured and closed minded view considering how big my audience could potentially be and how little it could cost me to reach them.

Here are a few tips for early development to make the localization process easy and painless:

  • Consider the dialog early, every word works out to around 9 cents per language (using professional translation services), if you can keep your dialog short and maybe replace some words with common symbols like arrows then it will make things cheaper
  • Plan to use a professional translation service, they are rather cheap and while google translate is reasonably good you will miss out on a lot of dialect and detail which can be rather embarrassing for your company and lead to demands for refunds. It will also kill your chances of getting featured (Apple love to feature well localized apps!).
  • Whenever you create a NSString while programming, don't forget to do it as a NSLocalizedString(@"",@"") and actually leave a detailed note in the second parameter where there is room for confusion. For example: If the text is "Ok", then leave a note about what you are agreeing to with this text as certain things are agreed to in different ways in different languages. Also if you have abbreviations like "m" for meters, make sure you let the translator know with a note.
  • Don't worry about populating your Localizable.strings file as you go, it's a waste of time as using genstrings can do this automatically.
  • Plan to localize towards the end of your development cycle, most translators are quick and last minute updates or changes can be time consuming.
  • Don't forget about your app name, store description, key words, in-app purchases, game center achievements and leaderboards. They all need to be localized for a complete experience.
  • Don't forget about images or data in plists which may contain words.

Ok, so you have kept your strings short and minimal to reduce costs, you have run genstrings to prepare your localizable.strings file. What next? 

You need to decide what languages you need, it is recommended to localize in:

English, Spanish, French, German, Italian, Portuguese, Chinese (Simplified), Chinese (Traditional), Russian, Korean and Japanese.

You may want to do some market research first to see how popular the subject of your app will be in those regions. You may find that your game only really applies to English speaking countries or on the other hand you may find that Korea is 80% of your world market. If you are still unsure, its not that expensive to cover your bases and do all of the above.

Now that you have decided on your languages, it's time to pick a translation service. I like to use iCanLocalize. They are very affordable, very quick and allow for lots of communication with the translators so you can get your translation done with the right context and style of your app. They also have a review process where another translator checks the translations done to ensure impeccable quality. You can also send them your .strings files and they can return them in the same format for easy implementation.

It's good to keep Google Translate handy too for unimportant quick translations. Be sure to check the context is as accurate as possible even with these simple translations.

Follow these tips and localizing your apps should be as painless as it has been for me in my latest app which goes on sale in two to three weeks time.

Implementing better iOS game menu strategies

One of the biggest mistakes I've ever made is designing a menu structure poorly. It lead to a 100,000 downloads and counting app making a grand total of $6. 

My mistake? Building a primarily multi-player game where the menu gave focus to the single player (late addition and less refined) content, made it difficult to find tutorials and makes in-app purchases unattractive and even difficult to find.

The menu was beautiful but it didn't do it's job, it didn't quickly and simply show the user what they wanted to find. It didn't lead the user where they needed to go, it didn't fast track the user to the game itself. Huge problems given minimal consideration.

So what makes a good menu structure?

Take me too the game

If it takes more than 2 taps to get from the menu to the game, it's taking too long. One game that especially impressed me was Jetpack Joyride by Halfbrick. The game has both a minimal and extended menu, the first time you play you are given 1 option "Tap anywhere to begin", you can't focus more on taking the player to the action than that!

Set the focus point

Having your important buttons bigger and and more central than the other options instantly makes the player focus on that option. If you need to have a more extensive menu structure then it guides the user through a default set of options by simply following the biggest buttons.

Develop your menus with your monetization strategy

A lot of developers favor having a separate store on their main menu where players can go through and find additional content they wish to buy. Something to consider is mixing your in-app content with the actual games content. Such as allowing players to buy "Save Me" tokens at the point of them failing in the game itself, kind of like adding coins at the continue screen of an arcade game. If you have a character select screen why not add your locked in-app purchases to the list as well.

Keep it simple

So many apps fail this step but it is by far the most important. If you don't need an option or level of menu options then cull them, cull as much as possible, give the player the bare minimum number of options. Use prototyping and design software to layout and revise your interface. Keep iterating and removing things that aren't needed. This will not only cut down on development time but make the players experience smoother.

I cannot stress enough that last point about keeping it simple, draft up your concept menu structure, revise it and work through it with a handful of different people until everyone you talk to is comfortable with it and feels that your users will be as well.

I've gone through this process thoroughly with my next upcoming (February) game and hopefully I will have some good statistics of how the experience has been improved.

Some great SpriteKit resources

In order to start getting some games on the store quickly with my challenge I'm having to cram a lot of SpriteKit knowledge.

It seems everyone has a different idea of how things are done and surprisingly some of the most experienced iOS developers I've seen are still using old methods of doing things, possibly because they are coming fresh from Cocos2D.

Right now I have 5 different sample projects open with different implementations of an entity class, as I observe each of them I have been using ideas I've liked and trying to write the code as robust as possible, at times it sort of feels like music, like a different person would have a completely different interpretation of what is good or bad but neither are technically wrong.

It's an interesting world of 2D development to be working in, here are a few tools I've found along the way which have been useful:

  • SKPhysicsBody Generator  - This website is great, you can drag in an image then draw a polygon and get the code straight away to put it in your app. I even took this a little further by making a simple spreadsheet tool which prepares the results for a plist and method to loop through creating the physics body from a plist file.
  • Kobold Kit - I haven't used it myself by this looks promising and I will probably be implementing in at least some of my apps when it reaches version 1.0.
  • iOS Games by Tutorials - This book has been a fantastic learning reference, I've picked up a lot of useful information and their additional tools are great. Easily worth the price. (Disclaimer: I am affiliated with the Ray Wenderlich Team).
  • Cartoon Smart on Udemy - I love the work these guys do, while their Obj-C is still back in Cocos2D land, their examples are fairly top notch and its really good to learn something from a different perspective than just RW.
  • Apportable -  While I am yet to try it, Apportable sounds like a high quality and reliable way to convert your Sprite Kit projects in to a format usable on the android platform. If it works then you have just increased your market size with minimal effort.