Targeting 2.x With 3.0 Features. Trouble Ahead.

iPhone-SDK-for-iPhone-OS-3-0-Beta-2-Released-Download-Here-2As far as Apple goes, OS 2.x doesn’t exist anymore. That much was clear from WWDC when we asked their engineers any questions about it. And as cool as 3.0 is, with all the new nifty features, the reality is that there’s still a good percentage of (mostly iPod Touch) users out there still on 2.2. We can have our cake and eat it too by targeting 2.x and still using a few select 3.0 features. But it’s more complicated than Apple made it out to be. Trouble is looming just under the surface.

Trouble With Versions

When you install the 3.0 SDK and create a new project, it will be automatically set up to build only for 3.0. To target earlier versions while still having access to 3.0 features, you need to take a few extra step. These steps are described in detail in the readme of the MailComposer sample (iPhone dev account required). My friend Serban also wrote about how to do it when you add Snow Leopard to the mix.

The required steps are:

  • Under project properties, set up the Base SDK setting to be OS 3.0

step1

  • Also in project properties, change the iPhone OS Deployment Target to OS 2.2 (or whichever version you want to target).

step2

  • Go to target properties, and add a 3.0 library with the features you need. Make sure you set its type to Weak instead of Required.

step4

  • In your code, check that a feature is available before using it. For example, you can do this check to see if the in-app mail functionality is available:
Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
 return (mailClass != nil && [mailClass canSendMail]);
  • Make sure you set your app to build with the 3.0 SDK and off you go.

step3

If all goes well, it should run under 2.x and 3.0. If all goes well…

Trouble With Libraries

If that was the end of the story, then we would all be happy and I wouldn’t have to write this entry. And for a while I really thought that was everything I had to do to get Flower Garden to use 3.0 features and still work on 2.x devices. Everything compiled fine, but when I went to run it on a 2.2 device, it crashed.

Looking at the crash logs, it was crashing inside a static library that used Objective C and UIKit. Digging further, it seemed that function calls were being sent to the wrong place. What was going on?

At this point I realized the root of this problem was the linker flags I was using. As soon as I started using the 3.0 SDK, I had to add the -all_load linker flag in order to be able to use the static library. I believe this loads all the symbols used by the libraries and links with them at link time. Without it, the library code would crash at runtime as soon as it was executed

The -all_load flag seems fine, except that the 2.x and 3.x versions of the SDK have different libraries and resolve symbols to different locations. So by doing -all_load, we’re linking against the location of the 3.0 version and trying to run it on 2.x. Bad idea.

I thought long and hard on how to get around this. I came up with all sorts of crazy schemes, and after a couple frustrating days, I gave up. Then, all of a sudden, I realized that it had an embarrassingly simple solution: Don’t use a library! I’m not kidding. Just move the files in XCode directly into your main game target and you’re done. No -all_load and everything works fine.

Yes, I’m still embarrassed for not figuring that out after 30 seconds…

Trouble With Compilers

So all happy with that discovery, I rebuild and run the app and… crash again!

The call stack this time looked like this:

Thread 0 Crashed:
0   dyld                              0x2fe01060 dyld_fatal_error + 0
1   dyld                              0x2fe07ca8 dyld::bindLazySymbol(mach_header const*, unsigned long*) + 484
2   dyld                              0x2fe15eb4 stub_binding_helper_interface + 12

What was going on in there? Some Googling and searching in the iPhone forum later, I learned that SDK 3.0 uses a different version of GCC (4.2 instead of 4.0). That means it will try to use some runtime functions that are not available with earlier versions. In particular, my crash was related to subtracting two uint64_t variables. Re-writing the code by casting the values to uint32_t before doing the operation fixed the problem. There’s an ugly “solution” for you!

So how do you know if something will work on 2.0? I don’t have a good answer for that other than test it as much as you can. Does someone have a better solution?

The good news is that, after I made those fixes, Flower Garden was happily running on 2.2 and 3.0. Now I can finally roll out in-app email without giving up on 2.x devices and cutting my potential customer base (or depriving current users of future updates).

Open Questions

Going through this answered a few questions, but also created a few new ones. Maybe someone here will know the answer or will be able to point me in the right direction.

  • Does anyone know how to debug your OS 3.0 app on the simulator set to 2.2? Whenever I launch it from the debugger, the simulator gets set to 3.0. Even if I set it to 2.2, I wonder if it will behave the same as a 2.2 device.
  • I’ve heard rumours about somehow, packing two versions of the app in the same executable (kind of like the universal MacOS executables with both a PowerPC and an Intel version). Has anyone done something like that with the iPhone? Any docs on that?

Balancing Flowers

I feel bad for the designers of games like Civilization or Supreme Commander. And I don’t even want to think about World of Warcraft. I thought it was tricky to balance the different flowers in Flower Garden, so I can only imagine the amount of time and effort than went into tweaking all the properties of the many dozens of units in those games to balance them just right.

At first, things sounded simple enough: Create 20 different seeds, with varied looks and properties. I had a really cool tool to tweak the flower DNA in real time (more on that another day), so how hard could it be?

The main properties I had to balance were amount of care required (as in, how often you had to water them before they would go dry) and how long the flower took to grow. The first few flowers came along just fine, but after the fifth or sixth seed, they all started blurring together. Did I have a fast-growing flower that needed a lot of care already? To get around this, I started writing all the seeds I had done so far and their characteristics in a text file so I could refer to them easily.

After a few more seeds, I knew I was in trouble again. Reading through all the flowers was a pain, but now I was starting to forget what they looked like. Did I already have an orange flower with a few, large petals? How about a small white one with lots of rounded petals and glossy leaves? The text file didn’t cut it anymore, I had to go graphical. So I created a document with a picture of each flower along with all its relevant information (name, growth time, and amount of care).

This helped a lot, but it eventually became inadequate when I started creating the unlock conditions and balancing and the different seeds in order of difficulty. I just wasn’t able to look at a list of 20 entries, each of them with 3 key elements (care, duration, and unlock condition) and keep it all in my head to make intelligent decisions based on it.

I’m a very visually-oriented person. Whenever I can, I try to solve problem visually instead of memorizing lists or plugging equations. In particular, I love to take a multi-dimensional problem and visualize it along its main axes. So I took the next logical step to help me make sense of all that data and created a seed chart.

FlowerSequence_s

This seed chart is a two-dimensional arrangement of all the common seeds in the game, along with their picture and the key information we had before (there are another dozen bonus seeds that aren’t listed in this chart). The horizontal axis indicates how much care a plant needs. Specifically, it shows how many segments in the water meter before it dries out (and each segment is 3 hours). The vertical axis indicates the growth duration for the plant in real time. Instead of making it a straight, linear scale, I decided to go with regions, which is how they are presented in the game (“Instant”, “A few hours”, “Overnight”, “A few days”, “About a week”, and “Quite a while!”). Within the region, they’re roughly ordered by duration (shorter towards the top, longer towards the bottom).

Now it was really easy to see at a glance the key characteristics for each seed, see where I had clusters, and where I had empty spaces that no seeds were currently using. As a bonus, I was able to come up with a rough ordering indicating the level of difficulty for each seed. The further down and to the right a seed was, the more difficult it was to grow.

That allowed me to block out some regions (dotted red lines) indicating difficulty ratings, which are listed in the game in the seed information as “Piece of cake”, “Easy”, “Moderate”, “Hard”, or “Experts only”. Notice how the lines separating the regions are not parallel (even though the vertical axis is kind of logarithmic). That’s because moving along the horizontal axis increases difficulty a lot faster than moving down the vertical axis. So even a relatively complex relationship like that can be observed at a glance from the chart.

Another great benefit of the seed chart is that I was able to draw paths between seeds, showing the unlocking relationships between them. Before it was hard to see these relationships in text, but now it was very visual, and I could make sure that easier flowers unlocked the path to harder ones as long as the unlock relationship flowed roughly from the top left to the bottom right.

As a side effect, the chart allowed me to learn even more things about the data than I had expected. For example, I was able to see which colors I had used so far, and which colors I still needed to use. One really interesting thing I noticed is that colors were clustering around specific areas. Red colors seemed to be mostly in the harder flowers. Yellow colors were predominant with the dry plants, and blue colors with the wetter ones. I thought that was pretty neat, so I tweaked a few seeds here and there to make that color connection even stronger.

The lesson learned here is that the old saying applies even more in this age of information: One picture is worth one mega of words.

Teaching a Two-Day OpenGL iPhone Class. Register Now!

openglI’m excited to announce the intensive, two-day class on OpenGL for the iPhone that I’ll be teaching. The class will be held September 26th-27th, in Denver, right before the 360iDev conference, and it’s part of the Mobile Orchard Workshops.

The class is aimed at iPhone developers without previous OpenGL experience. It’s going to be very hands-on, and you’ll create both 2D and 3D applications during the weekend. You’ll learn all the basics: cameras, transforms, and how to draw meshes, but we’ll also cover some more advanced topics such as lighting, multitexturing, point sprites, and even render targets. Most importantly, you’ll walk away with a solid understanding of the basis, which will allow you to continue learning OpenGL and advanced computer graphics on your own from the docs, samples, or even browsing the API directly.

The main requirement for the class is that you’re familiar with the iPhone development environment and that you have basic knowledge of the C language. Beyond that, to the the most out of the course, you should be familiar with the basics of linear algebra (vector, matrices, and dot products). Anything else, we’ll cover it all during the class.

Registration is now open, and you can get some great discounts by registering early and attending the 360iDev conference. For more details, check the official announcement page.

Hope to see some of you there!

Flower Garden Coverage and Interview on Spanish TV

A couple of weeks ago I gave a presentation about iPhone development at Gamelab, the main game development conference in Spain (yes, it was my first technical presentation in Spanish!). Afterwards I was interviewed by Zoom Net, a popular TV show about games and technology. Yesterday they aired the episode with my interview and I was pleasantly surprised to see they turned it into a full 4-minute section covering Flower Garden. Coverage starts at 8m 40s from the start (and, obviously, it’s in Spanish).

noel_tv

Notice the other iPhone games that flash at the start of the Flower Garden section: Harbor Master, Up There, and Little Red Sled, all App Treasures games! The video also starts with coverage of Fifa 10, so we’re in pretty good company 🙂