Going The iPad Way: All You Wanted to Know About Creating Universal Apps

flower_garden_ipad.jpg
It’s one thing to go on record saying I wouldn’t be creating an iPad-specific version of Flower Garden, and another seeing the iPhone version running on an iPad with all the ugly jaggies and huge, pixelated text. So when it came time to do a new update, I decided to at least take advantage of the iPad capabilities to make the existing app prettier by making Flower Garden into a universal app. It’s now available on the App Store, so go get it and check it out!

Surprisingly, there wasn’t that much documentation on how to go about making a universal iPhone/iPad version. There’s a document from Apple showing some initial steps, but that’s about it. So I wanted to share what I learned along the way, including some very useful tips I learned through trial and error or by doing a lot of digging through Twitter and the development forums.

Flower Garden is a strange hybrid of OpenGL and UIKit, which made things more complicated than if it were just one or the other. Learning curve and all, it took two full days of my time. If you’re using just OpenGL or just UIKit, the conversion to a universal app will be significantly faster.

Universal Project

The first thing you need to do is understand what’s going on with all the SDK versions. At this time, the latest iPhone OS version is 3.1.3, but you’re going to be developing the universal app with SDK 3.2. You want the resulting binary to run on both 3.X OS on iPhones and 3.2 OS on iPad. It’s a very similar situation to when we were writing apps that worked on both 3.X and 2.X.

So fire up XCode 3.2.2 (yes, all those version numbers start getting very confusing–that’s the XCode version that comes with SDK 3.2), and load your iPhone project you want to make into a universal one. If you look under the Project menu item, you’ll see an entry called “Upgrade Current Target For iPad”. The Apple documentation even warns you not to create a universal app in any other way.

Go ahead and use it if you want. It will work… as long as you have a single target you want to convert. For some inexplicable reason [1], it will only work once per project (even though it’s phrased as working with whatever the current target is). When would you have more than one target executable? If you have a free and a paid version for example.

Besides, I’m uncomfortable with automated “smart” tools that do things behind my back without me knowing exactly what’s going on, so I upgraded by hand by looking at the diffs of what the upgrade command did. It turns out it’s extremely simple.

  1. Under the project properties, set your base SDK to 3.2.
  2. Set Architectures to “Optimized (arm6, arm7)”
  3. Uncheck “Build Active Architectures Only”
  4. proejct_settings_1.png

  5. In the Deployment section, set it to SDK 3.1.3 (or whatever 3.X you want to target)
  6. project_settings_2.png

That’s it, really. That’s all you need to compile and run your app both on an iPhone and an iPad. When you build for the device, it will compile both arm6 and arm7 versions and create a combined fat executable with both. And yes, this means the size of your executable is going to double (which could be an issue if you’re near the 20MB limit). In the case of Flower Garden, the combined executable is 3.4MB, so that’s not a big deal.

iPad Functionality

What about that new xib file that the upgrade process creates? You don’t really need it. It’s there in case you want to have a different set of xibs for each platform, and it’s hooked up to the info file so the app knows to load it at startup.

ib.pngFor the universal version of Flower Garden, I wasn’t trying to make a whole new brand experience on the iPad. Instead, I was looking for a quick and easy way to make it look much better. Because of it, I decided to reuse the same xib files as for the iPhone version.

That meant I had to go in Interface Builder, and adjust the autosize properties for a lot of the views. Some of them I wanted to stretch and get bigger with the high resolution iPad screen (background views). Others, I wanted to leave at the same size, but remain at the same relative distance from a particular border (buttons). Some other ones, I left the same size and their position just scaled up with the resolution (info boxes). All in all, that was the most time-consuming part of the process. It also required a few tweaks here and there to support the resolution change correctly.

The other big change was updating the resolution of the 3D views. Fortunately, that was just worked without a single line change. The render target code I’m using, takes the view dimensions and creates a frame buffer of the correct size. And it’s not just the dimensions: Remember that the iPad has a different aspect ratio (grumble, grumble), so you need to make sure your perspective and orthographic projections take that into account.

The only other changes I had to make was supporting an upside-down portrait orientation. That was very easy because the frame buffer didn’t have to change. Make sure you support it both at launch time and during gameplay. If you have a root controller whose view is attached directly to the main window from the start, it’s as easy as adding this to your controller:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait ||
            interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}

And make sure you add the supported orientations to your plist.

plist.png

Finally, before you submit it to the App Store, you’ll need an iPad-specific icon. The documentation explains how to explicitly list all the icons in the info file, but at the very least, you can provide a file called Icon-72.png that is a 72×72 image and you’re done.

Running On The Simulator

This is one that should be a lot easier than it is. You’re creating a universal binary with SDK 3.2. Now you want to run it on the simulator. No problem, you run it as usual and you get the iPad simulator. You can debug it and do everything you normally do.

Now you want to run it on the simulator on iPhone mode. It turns out, that’s not so obvious.

You can’t just turn the simulator hardware setting to iPhone, because whenever you launch it from XCode it will override that again with the iPad one. Building and running on the 3.1.3 SDK is a no-no because you’re really running a different build than you’re going to be submitting (3.2) and all 3.2 SDK features you’re using are going to result in compile errors.

So after much searching and tweeting, here’s the solution:

  • Build for 3.2 SDK on the simulator platform.
  • Change project drop-down to 3.1.3 SDK
  • sdk_version.png

  • Launch with debugger (Cmd + Options + Y). Don’t build and run!

That will launch the simulator on iPhone mode, but still run your 3.2 build. Talk about unintuitive! [2]. The worst thing is, when you’re done, you need to switch the project to 3.2 again or you’ll get tons of compiler errors. That definitely has to go for SDK 4.0.

Here’s an invaluable tip. Maybe it’s obvious to long-term Mac users, but it baffled me for a while. The iPad simulator is very well thought out, and it has a 100% and a 50% mode. That makes it possible to use the simulator on screens without very high resolution. Even my external monitor at 1680×1050 can’t display the iPad simulator at full 1024×768 resolution in portrait mode because of the window borders.

The problem comes in when you want to take a screenshot to add to the App Store or anything else. On the iPhone simulator it was easy, but how do you do that with the iPad since you can’t fit it on the screen? Cmd + Ctrl + C will take a screenshot at full resolution even when running at 50% mode and add it to the clipboard! Switch over to Preview and select New from Clipboard and voila! Full resolution screenshot!

SDK 3.2 Features

Chances are that even if you do a simple iPad port, you’re going to end up using a few 3.2 features. The main one I used in the case of Flower Garden is a UIPopoverController. Here you should follow the steps outlined in the Apple documentation down to a T. But it comes down to this: If a symbol that is defined on 3.2 appears anywhere, even as a member pointer variable in a class, it will compile and run on the iPad fine, but will crash and burn on the iPhone.

So you need to both check that the 3.2 features are available, and you need to “hide” the new symbol so it never appears anywhere: Use an id variable and cast it based on the class info. Even casting it directly to the symbol you want will cause a crash.

Class classPopoverController = NSClassFromString(@"UIPopoverController");
if (classPopoverController)
{
    m_moreGamesPopover = [[classPopoverController alloc] initWithContentViewController:moreGames]; 
    [m_moreGamesPopover setDelegate:self];
    [m_moreGamesPopover setPopoverContentSize:CGSizeMake(320, moreGamesHeight) animated:NO];
    [m_moreGamesPopover presentPopoverFromRect:m_moreGamesButton.frame inView:self.view
                        permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

Not pretty, uh? It works, but I couldn’t imagine doing this all over the place.

Gotchas

In the process of creating a universal app, I found a couple more things to watch out for.

When you submit the new binary through iTunes Connect and it’s accepted, the application status will change to something like “Missing screenshot”. If you go back and edit the app information, you’ll see there’s a new set of screenshots you can submit. You’ll need at least one for your application to enter “Waiting for Review” state. And if you have localized descriptions of your app, you’ll need to do that for every language.

Last, and perhaps most puzzling because I never figured this one out: I was not able to get in-app purchases to work with a test account from a development version of a universal app running on the iPad. I must have tried everything, but whenever I tried purchasing anything, it never brought up the familiar “sandbox environment” message. Also, items that hadn’t been approved yet did not show up in the list of available items. The exact same code worked fine on an iPhone, so that’s quite puzzling. Is it a major bug on Apple’s part, or did I miss some obscure “enable IAPs in debug mode” checkbox somewhere? It was a bit of a gamble submitting it like that, but fortunately, the approved version on the App Store allows in-app purchases without any problem.

I thought afterwards that maybe that was because the app version on the App Store was no universal, so the Store Kit server was not allowing the iPad version to access the store through the test account. But I tried it again even after it was approved and I had the same problem.

Has anybody managed to use an App Store test account from an iPad on a universal app?

Conclusion

All in all, it was a relatively painless process considering it’s different hardware, with a different resolution, and it’s the first iteration of the SDK. Was it worth it? I think so. Apart from looking a lot better on an iPad, universal apps get ranked on both iPhone and iPad charts. Flower Garden managed to get all the way up to #14 on the free games chart on the iPad (and around #60 free app overall on the iPad). I’m sure it got some exposure from being so high up, which in turn helped the iPhone rankings as well.

I can’t imagine that my next game is going to be iPad-only, but I’ll certainly have the iPad in mind from the beginning and release it on both platforms. Whether I choose to go universal or separate apps will depend on the game and business decisions, but at least it’s good to know that it’s fairly easy to create a universal app.

flower_garden_ipad_charts.jpg



[1] Actually, there’s a pattern that is clear by looking at the hoops we have to jump to do a universal build: Apple was clearly scrambling to get this out the door. As a result, things are buggy, unintuitive, and clunky. Hopefully all that will be fixed for SDK 4.0.

[2] See? That confirms point [1].

Flower Garden Is Free This Weekend To Celebrate Mother’s Day!

Icon-128x128.pngflower_shop.jpgSince this Sunday is Mother’s Day (in the US at least), I’m making Flower Garden FREE for the weekend. Yes, that’s right, completely free!

Am I going crazy? Giving away the fruit of my labor for so many months? The App Store will do that to people, but this is a bit more sane. The idea is to encourage many more people to try it out. I’m actually hoping some of them will like it so much, they’ll buy a few of the in-app purchases from the Flower Shop. And even if they don’t, hopefully they’ll spread the (good) word about Flower Garden and they might also sign up for the mailing list. And in this business, expanding your user base is a great strategy that can be leveraged for future projects.

The idea of giving away a free app isn’t anything new. There are whole sites like FreeAppCalendar dedicated to doing exactly that, and other developers, like NimbleBit have been doing that on and off very successfully to reach a wider audience with their games.

How will it work out? I don’t know yet, but Flower Garden is quickly going up the charts even early on Saturday. It’s currently in the top 50 free apps in Japan, and about to get in the top 10 kids games in the US, so it’s looking good.

If you haven’t picked it up yet, this is the time. And if you have, make sure you tell your friends and family to download it and check it out before it goes back to the regular price. I’ll report back on the results of this promotion in a few days.

Flower Garden a Finalist for The 2010 Pocket Gamer Awards for Most Innovative Game!

10AF654B-A6A5-4C29-BE46-D58B3A09BAEA.jpgPocket Gamer just announced the finalists for the 2010 Pocket Gamer Awards. I was thrilled to see that Flower Garden has been selected as a finalist for the Most Innovative iPhone Game award.

On a personal level, this nomination means quite a bit for me. Flower Garden has gotten some great reviews, and some incredible user feedback, and it was even featured as an Apple Staff Favorite on the App Store, but it had never been up for an award of this importance.

It’s also the category that it was nominated for. It makes me really proud that it was nominated for Most Innovative Game, because one of my original goals was to create something unique and original.

Finally, these awards are particularly meaningful because they’re not based on popularity, sales, or voting, which are bound to bias awards towards best-selling titles. Instead, these finalists were hand-picked by the editors of Pocket Gamer. With the crazy amount of good apps out there, it really is an honor that they selected Flower Garden as one of the top 5 for 2009.

Thank you, Pocket Gamer!

Buy Flower Garden This Wednesday To Help Haiti

As part of Indie+Relief, all proceeds from Flower Garden this Wednesday will be donated to Haiti through Doctors Without Borders. Encourage your friends to buy Flower Garden for a good cause! That includes in-app purchases, so feel free to load up on fertilizer :-)

If you’ve already purchased Flower Garden and you’d still like to help out, you can check out the great lineup of Mac and iPhone apps at Indie+Relief, or donate directly to Doctors Without Borders here.

ir_500

Making A Living (Barely) On The iPhone App Store (aka The Numbers Post)

The App Store is a very hit-driven environment. A few apps sell a large amount of units, and the great majority sell next to nothing. That’s somewhat similar to the music industry, except that the audience for music is much larger, so both the big hits and the small players get more sales. We’ve drooled over the numbers chart toppers sold, we’ve seen sales reports of very successful games, and we’ve also seen what happens when apps languish at the bottom.

I want to share the sales data for Flower Garden. Not just the raw data, but a bit of the story behind it, my thoughts, struggles, and why things happened the way they did.

The first thing that you’ll notice is that Flower Garden is a strange in-between app. It’s far from being very successful or being at the top of any chart, but at the same time it probably made more money than 99% of the apps on the App Store. It was also reelased on April 10th, so this represents 10 months of data, an age after which most apps are usually on drip support. So this should be an interesting new data point.

The Full Monty

I know that if I put it off, you’re just going to skip to the end to see the sales plot, so let’s get that out of the way. Here it is.

Full

The vertical axis is daily profit in US $ (after Apple’s 30% cut). Flower Garden generated a bit over $21,500 over a period of 10 months. I would hardly consider that an entry-level salary, much less in California, but it’s enough for someone without a family or mortgage to (barely) make a living. I supplemented that with some teaching, writing, contracting and consulting, so overall I managed do fine and even save a bit of money last year, all while being totally indie and having full creative control over what I did every day. I’m not getting rich, but it’s not a bad life, really.

How many hours of work does Flower Garden represent? It’s really hard to say. It was 6 solid months of work from conception to release, but then there was the fuzzy time spent on marketing, updates, support, new features, etc. I would estimate it was a total of 8 months of full time work, which, at 50 hours per week, makes it 1600 hours. So that’s a depressing $13.44/hour. At least it’s over minimum wage! :-) On the positive side, Flower Garden should continue to sell in the foreseeable future, so that amount will go up a bit over time.

There’s clearly a story behind that graph. It’s not the usual exponential drop off you expect from most (unsuccessful apps) and shows how an aging app can pick up steam on its own after many months on the store, without ever being featured by Apple.

Launch

Let’s start from the beginning. Release day!

Beginning2

After six hard months of work, I submitted Flower Garden to Apple sometime at the beginning of April, and on April 10th I was surprised to see it had been approved. It caught me a bit off guard without my marketing campaign in place, but I announced it high and wide on this blog, Twitter, Facebook, and I even spammed all my friends with an email. The results are the area marked as (A): About $50-$60 in revenue per day (so about 25-30 sales). Not bad considering that was mostly my friends taking pity on me and people randomly seeing it on the new releases list, but it was far from an auspicious start.

I also contacted all the media sites I knew with a press release and promo codes to entice them to write a review. I was lucky that many reviews appeared over the next couple of weeks, but unfortunately they were all spread out, minimizing the PR effect. The biggest effect was when Flower Garden was simultaneously covered on TouchArcade and MacRumors. That’s what caused the big sales spike (B). From there, it was a standard exponential drop off, until, on the last day of the month, just three weeks after launch, revenue dropped below $100/day again. If that was all there was to it, Flower Garden was a big flop and I should start dusting off my resume.

Mother’s Day

I wasn’t ready to throw in the towel yet. I had a couple cards up my sleeve that I was hoping would change things around. After all, May 5th is Mother’s Day in the US. What better time to do some promotion and get Flower Garden noticed?

I decided to run a contest and give away $100 in real flowers to the winner at the same time I put Flower Garden on sale for $1.99 for the week of Mother’s Day. The result? The revenue dip you see in (A).

Middle_long

Mother’s day is probably the small, second spike in that period, but overall, that week was a loss. Lesson learned: Don’t make a sale unless your app is in a visible position (on a top chart somewhere). Flower Garden was nowhere to be seen, so the sale had no effect other than to cut profits by 33%.

I released a couple updates and did the trick updating the release date to get on the new releases list (which no longer works) and I got a couple minor spikes with (B) and (C). Subsequent updates later that summer had almost no effect anymore on sales. The trend was worryingly clear as profits dipped as low as $10/day in mid June (I have no idea what happened that day, but it was the lowest day ever for Flower Garden).

App Treasures

In early June we launched App Treasures. App Treasures is a label for indie iPhone game developers with top-quality games, and one of the main tools we’re leveraging is some cross-promotion for our games, both through the web site, and from an in-game view liking to each other’s games. Initially there was no measurable effect, but then Harbor Master was released and shot all the way to the #2 position on the US store and held its position on the top 50 for a while. The results is the area under (D). It definitely brought in some sales to Flower Garden and reversed the downward trend.

Unfortunately all good things come to an end, and referrals from Harbor Master dropped off and its slipped down the charts, and Flower Garden sales continued sinking.

Facebook and Lite

At this point I had to face reality. Was it time to give up on Flower Garden and move on to another project? I was ready to do that, but every day I would get several emails from users saying how much they loved Flower Garden, how much happiness it was bringing to their lives, etc. Some of the stories were really touching.

At the same time, every time I would show the game to someone, they usually really liked it. Not liked-it-because-I’m-there, but really, genuinely liked it. Why weren’t more people buying it then? Two problems: First, screenshots were not conveying how cool growing, animated flowers you could touch were, and second, most people didn’t even know Flower Garden existed. It had never been featured by Apple on the App Store, and the audience I was trying to reach didn’t read TouchArcade or other iPhone review sites.

It was at this point that I decided to give it one more try. My goal wasn’t adding more features as I had done with the updates so far, but to make Flower Garden more visible. I wanted more people to know that Flower Garden existed.

The first thing I did was to add Facebook integration. Not only could you send bouquets through email, but you were able to send them directly to your Facebook friends. The advantage of that approach from my point of view is that all your friends also saw the flowers so for every bouquet sent on Facebook, hopefully dozens or hundreds of people were being exposed to Flower Garden. The result on sales: Not much. Maybe it made the early part of July a little higher than it would have been otherwise, but no noticeable difference.

The second approach was to release a lite version of Flower Garden in early September. I was confident that Flower Garden was a good app, and I was hoping that once people had a chance to try the lite version, they would purchase the full version. Fortunately I was right and the effect on sales was very noticeable, pretty much doubling sales (E), but it never really took off in any significant way, and sales slowly declined over time.

Second Wind

You’d think that I would give up at this point, wouldn’t you? And I don’t say that with pride. I mean, it probably would have been smarter to quit a long time ago. But somehow, every time I was ready to move on , something else would come up that would entice me to try something else with Flower Garden.

This time it was in-app purchases (IAP). Apple had announced IAP back in June. They seemed like a very natural fit for Flower Garden, but given how few units Flower Garden had sold, I would have a very limited audience for IAP. A small percentage of a small number is a tiny number! :-( However, in late October Apple announced that IAP were finally allowed from free apps as well. That encouraged me to give Flower Garden one… last… try…

To be totally honest, I wasn’t expecting very much. Even including all the units of the Lite version out there, there just weren’t that many units. Especially not that many people using it on a daily basis (I’m sure a lot of the free ones were downloaded and quickly forgotten). But I thought it would be a good experience and if I only spent a week on it and made $1,000 I could call it even.

End

The result was totally unexpected. The Flower Shop opened on December 6th and revenue immediately shot up (A). On December 21st I released a new IAP called Seeds of Winter with 8 new winter-themed flowers, and people loved it and immediately purchased it. Christmas day came and went with somewhat of an increase in sales (C) but nothing really spectacular. Finally, to wrap up the year, there was a big spike on New Year’s Eve (D) (do people send flowers on New Year’s Eve? Really?).

Afterwards revenue flattened out, but at a much higher amount than before. Before IAP, daily revenue was about $50/day. Now it’s more around $180/day. That’s totally beyond any of my expectations!

But hang on, where is the revenue coming from? There are three possible sources: You can purchase Flower Garden, you can make IAP in the full version, and you can also make purchases in the free version. Here’s the breakdown:

End_broken_down

It looks like sales for Flower Garden (blue) continue to be more or less the same, with a slight increase after Christmas. The IAP from the full version of Flower Garden (green) account for most of the extra revenue, especially at the beginning. But it’s very interesting that the purchases coming from Flower Garden Free (orange) are steadily increasing and, as of last week, they became almost as large as the ones from the full version.

That can be explained because more and more people are getting the free version and upgrading it instead of buying the full version (which is exactly what I was hoping for). What’s also really interesting is the downloads of Flower Garden Free.

fg_free

Flower Garden Free was never a big player. It had the usual big initial spike, but then it settled down at around 100-200 downloads per day (which is very few considering there were 50-60 purchases per day of Flower Garden Full during that period). But, as soon as the in-app Flower Shop was released, downloads started climbing, and on Christmas day they went through the roof (relatively speaking). So it’s no surprise that IAP from Flower Garden Free picked up in these last few weeks.

The Future

I have no idea what the future will hold for Flower Garden. This week Apple selected Flower Garden and featured it on the App Store as a Staff Favorite worldwide (that period is not show in the sales graphs). I’m also already preparing a new update and some more IAP for Valentine’s Day, so I’m sure there will be more ups and downs in the near future. I’d certainly like to continue supporting Flower Garden for as long as it’s profitable.

I’ll follow up this post in a couple of months with the aftermath of the App Store feature and Valentine’s Day. Also, stay tuned for another post with more details of the IAP, what’s successful, purchase patterns, and more.