My game Heartline came out a few weeks ago. Here’s a breakdown of how it was built, challenges, and what I learned.
I wanted to get into iOS development late last year, so I bought a Mac Mini around Christmas. After learning the ropes of the new OS, the thing felt a little sluggish, so I dropped another 50 bucks and added some RAM.
XCode and Objective-C took a little while to get the hang of. At first I was turned off by the incredibly verbose method calls. Calling methods with block syntax felt ugly. Memory management was strange as well (when to use init vs alloc? what attributes for properties?) But going through a few tutorials, and just spending time in the environment, I was able to manage. I’m still not a pro at all the nuances of objective-C, but I can get done what needs to get done, and that’s the important thing.
I decided to go with Cocos2D once I did some research and found that most dev tools for iOS App development came with a cost. Unity, Corona, MonoTouch – all were pretty pricey to release an app. Cocos2D was free, open source, and had a really good community.
Biggest differences from XNA:
No game loop!
There’s probably some sort of game loop going on under the hood, but I wasn’t able to access it via Update Methods, like you do in XNA. I think the tutorial method of managing objects in Cocos2D is to queue up actions and let the framework handle the movement/collision. But that wasn’t fine-tuned enough for me. And besides, I learned to make games with a game loop. Thankfully, you can add a gameloop manually using a scheduler.
Everything is a game object
The other big challenge was that every Cocos2D object was a game object. If you inherit from CCNode, you have a position, and can draw on the screen. But stuff also has to be added (and removed) from scenes to be “in” the game world.
One advantage of Cocos2D over XNA is the built-in screen system, using Scenes and Layers. Scenes are added to a Director. Layers contain all the game objects. So you can easily have a Pause Menu pop up in a few lines of code, without having to worry about managing the state. Even better, there’s a menu system, with the ability to layout buttons in grids or lists.
Drawing is a little different in Cocos2D and iOS. Spritebatch in XNA is pretty powerful – you can use it to scale and rotate textures, and even draw primitives (out of 1 pixel textures). In Cocos2D, the draw method of a game object pretty much just draws the texture at the position. If you want to get fancy (transparencies, primitives) you have to start using low level OpenGL calls, which can get tricky and feels like a bit of a hack. Drawing a straight line requires a bunch of calls, setting different rendering modes and stuff.
Color objects are also a pain in Cocos2D. Instead of single Color object like in XNA, there are 3 or 4 different Color structs, using different data types. Depending on the function, you have to convert between them, which leads to verbose and inelegant code. Alpha blending isn’t as versatile as spritebatch either.
Overall though, I’m very happy with Cocos2D and will be making some more games with the framework.
Ray’s blog has the best tutorials for building iOS apps, not only because he goes in such great detail and walks through the code, but includes standalone applications you can download, run and reference. Best tips were on how to build a Save Game singleton, and info on in-app purchases.
These were annoying for two reasons – setting up the metadata in iTunes Connect and testing it through the sandbox, and then the technical challenges of implementing the API. At first I tried to do it from scratch, using a Wenderlich tutorial. Built a delegate class, used the notification center waiting for asynch responses from the store, was able to purchase to unlock game features. But the entire thing felt very messy and tightly coupled with my game code. And during testing, the sandbox was notoriously slow, so if I hit the buy button a few times, I’d get spammed minutes later with Purchase popups on my iPhone. I ended up submitted with this first version of the code, but it failed because I didn’t include a “Restore Purchases” button. Not sure if a bug would have been found, but I decided to implement MKStoreKit.
MKStoreKit abstracts all the in-app purchase stuff into a nice package, and wiring it up into an application only takes half an hour. The biggest step is converting the app to ARC, which is required for MKStoreKIt. For Heartline, I ended up only converting the MKStoreKit code to use ARC, since the rest of the game, and Cocos2D was written without ARC. Your mileage may vary.
I wanted to beta test my game, so I decided to use TestFlight. Once you make an account, you can upload a binary of the game, enable test users to access it, and even get feedback from an API (crashes, checkpoints, etc). Building the binary was pretty straightforward, but setting up the various provisioning profiles was tricky. Note: the provisioning profile must match the bundle ID exactly (case-sensitive!)
The only other frustrating thing about TestFlight was that once friends and testers signed up, I had to get the ID of their device, and manually copy this into the provisioning profile, then send out an updated binary. You’re limited to only 100 devices, so if you ever wanted to do a massive beta test, you’re out of luck (unless you get an enterprise iTunes developer account or something)
Once the game was complete, releasing it on the store was pretty easy. It’s a minor annoyance that you need screenshots for both iPhone 4 and iPhone 5, since they have different dimensions. The actual review process was quick and clear. When a problem came up with my first build (missing the Restore Purchases button), the status of my app changed and I was sent an email with the problem. I was able to get a new build up there in a few days, and within a week it was approved. Much better than the XBLIG lockout period and peer review.
The tools to monitor sales are also very nice, with charts and breakdowns by the day/month/year. Of course, the app store is flooded with small little games, and since my app wasn’t really promoted, downloads dropped to almost nothing after the initial release.
But overall I’m pretty happy with the experience of building and releasing a game on iOS.
My next goals are to build some more advanced games using what I’ve learned with Cocos2D. I’m not sure the in-app purchase model is the way to go. It seems like you only cross a threshold of profitability if your game is very popular. But it’s a good reminder: I’m not in this for the money 😉