Adding Retina / Multitasking support to my iOS apps
Tuesday, November 30th, 2010Today I felt it was about time I got around to updating my Galcon apps with proper 4.x support now that everyone has it.
Adding retina is pretty easy. In EAGLView.m I had to add this snippet into initWithCoder:
float scale = 1; if([[UIScreen mainScreen] respondsToSelector: NSSelectorFromString(@"scale")]) { if([self respondsToSelector: NSSelectorFromString(@"contentScaleFactor")]) { scale = [[UIScreen mainScreen] scale]; self.contentScaleFactor = scale; } }
Then in my code anywhere where the scale matters, I use that information to sort things out. I found that adding retina Icons, startup graphics, and other in-game graphics was as easy as adding an extra file: Icon.png becomes Icon@2x.png, my_game_stuff.png becomes my_game_stuff@2x.png, etc. It was pretty simple. Fonts were a bit more complex because I have different font data for each sized font, so I use the scale information I discovered earlier to ensure that I use entirely different font images, instead of using the @2x trick. The one goofy bit was importing to subversion. It doesn’t work, unless you put a trailing @ at the end of the filename, since subversion treats @ as the version identifier.
Doesn't work: svn add Icon@2x.png Works: svn add Icon@2x.png@
Multitasking was even easier. In my AppDelegate.m I added these methods:
- (void)applicationDidEnterBackground:(UIApplication *)application { game->save(); Event e; e.type = EVT_SUSPEND; game->event(&e); [glView stopAnimation]; } - (void)applicationWillEnterForeground:(UIApplication *)application { Event e; e.type = EVT_RESUME; game->event(&e); [glView startAnimation]; }
The first is called when the app is suspended, the second is called when the app resumes. The iOS handles saving / restoring all the texture data, so really I didn’t have to do anything. The only catch was I had to add in the glView stop/start calls to ensure that no GL calls were made while the app was suspending. The app will crash if any GL calls are made while in the background.
I do not do any background work to keep the network alive. This seems sensible because it makes it so the game will timeout after 30 seconds but you’ll still be connected if you get back sooner than that. Anything fancier could keep a player on the network indefinitely even if they are really gone. This gives the user at least a momentary opportunity to duck away and check something then resume playing.
-Phil