Thursday, December 18, 2008

Tip: Install SmartSleep for OS X

Brent Simmons, maker of the excellent NewNewsWire, linked to Mike D's Virtualization Blog for manually configured how Intel Macs go to sleep, specifically changed the default (suspend to RAM + hibernate to disk) to the old PowerPC based Macs style (suspend to RAM), aka Fast Sleep. Brent then linked to SmartSleep, which is a preference pane that puts a GUI around configured the sleep options that were previously only available in Terminal, and implements SmartSleep. This setting configures OS X to use suspend to RAM when the battery has a strong charge, and turns on hibernate when it drops below a threshold. Sweet!

If you are positive you don't want to use hibernate, you can disable it and then get some disk space back (file size matches much RAM you have installed back).

  1. Close System Preferences
  2. Open Terminal
  3. Type cd /var/vm
  4. Type sudo rm sleepimage

Thursday, December 11, 2008

Friday, November 28, 2008

iTimeZone is on sale for Black Friday

iTimeZone has been discounted to $0.99 to commemorate Black Friday in the US in the App Store in iTunes. Extremely curious if I can "make it up in volume", the 50% reduction in sales price and revenue.

Tuesday, November 11, 2008

iTimeZone on iTunes App Store Front Page

As I usually do, I logon to to the iTunes Store on Tuesday and check to see what new content is available. I happened to do this last night after midnight right before I went to bed. Imagine my utter shock to see iTimeZone in the NEW section on top of the App Store home page. Here is a screenshot for posterity's sake:


click for larger view

Real estate is even more precious on the App Store app on the iPhone and iPod touch, but iTimeZone also managed to make it to the top of the list. Here are two images, one the default loaded, the the second slightly scrolled to show the iTimeZone row completely:

Why Now, What's Changed?
I have no idea why iTimeZone has been granted pretty prominent placement in the NEW section on the App Store home page now. iTimeZone 1.0 was released when the App Store opened, iTimeZone 1.1 was released on October 21, 2008, and iTimeZone 1.1.1 (small bug fixes) was released on October 30, 2008. I have not been contacted by Apple, but if anyone from Apple is reading this and you can comment, I would love to hear why (dave dot murdock at mac dot com). It is entirely possible this is an accident, but I think that unlikely. Each of those tiles on the any of the iTunes Store home pages (Movies, TV Shows, App Store) is premium real estate and clearly under editorial control. I think iTimeZone's promotional position on the App Store will last a week and I am hopeful it will accelerate sales. Thanks Apple!

Friday, October 24, 2008

Using the built-in OS X Grammar Checker with Mail.app

I am no spelling whiz or grammar genius, so I rely heavily on software tools like Microsoft Word and OS X's built-in system wide spelling and grammar checking. Word I believe was the first to implement spelling and grammar checking as you type, for me it was a huge innovation. OS X's built-in spell check nearly anywhere you type text, especially on the Web in Safari, was one of those extremely nice surprises coming from Windows years ago. It is one of those "why isn't this in Windows" features.

Mac OS X 10.5 Leopard added English Grammar checking as you type. When I saw this on the Leopard Feature List (pictured left), I was extremely excited about having a system wide grammar checker. I was really looking forward to having this functionality in Mail.app, problem was, I am embarrassed to admit I couldn't figure out how to use it. But I figured it out now, here's what I am talking about.

Turn it on
Grammar check is supposed to be on by default as you type, but it seems to depend on the app. If you want to make sure it's on, you have to right click in a box you enter text, then click on Spelling and Grammar, then finally make sure Check Grammar With Spelling is checked.

Make Mistakes, Get Suggestions
Here is a sample sentence that the OS X Grammar checker flags:

I had always expected that you should right-click on any of the words with the green underline to see grammar suggestions, just like in Microsoft Word. In Mail.app, this isn't what happens. When you right-click in Mail, you see the menu on the left without suggestions. When Leopard first shipped, I thought this surely must be just a bug and kinda forgot about it. Then today something unexpected happened. I hovered over the grammar text by accident, which you then get to see a tooltip like this:

So you can use the tooltip, but I also found that their is a floating Spelling and Grammar tool window:

But What If Mail.app Is Broken in 10.5.0 - 10.5.5
Seeing the tooltip I thought Mail.app's behavior must be by design, but after playing around some more, I don't think that is the case. I use MarsEdit to write my blog posts, and since it's a Mac OS X app, the place where I type my content is the same OS X text area that does automatic spell checking. I didn't remember ever seeing grammar checking while typing, so I went and turned that on and typed my sample sentence:
Bob said better to be feared than respected, with regards to investing in stocks.
Sure enough, with regards to was highlighted as having faulty grammar. I right-click, and there are suggestions on the right-click menu as pictured on the left! Tough to draw a conclusion, Mail could intentionally (by design) or unintentionally (bug) not be showing grammar suggestions on the right-click menu. I filed a bug on it, #6319745 in RadarWeb (and I hope Radar, but I don't have access to the actual app).

iTimeZone 1.1 Released to the App Store

On Tuesday October 21, 2008, iTimeZone 1.1 was released to iTunes App Store. This was actually a shock, since I had been reading from other iPhone developers that approval times where somewhere between 1-2 weeks. iTimeZone 1.1 was approved in 33 hours! This was such a surprise, that I hadn't done anything on the Tangerine Element site to document the release. I was scrambling around on Wednesday in my spare time to get it done, and it took me a bit of discovery to use the Apple approved App Store logo (seen left) instead of the App Store iPhone icon I was using since launch.

As for what new or different in iTimeZone 1.1, you can visit the product page or other posts on the blog:

Thursday, October 16, 2008

Video game saving is broken, the content is the gamers, and how to fix it

Save Game Info I have never designed a video game, but I have been playing games for a long time. Being a software developer, I have some strong opinions on software design, and game design in particular lately. Specifically, I think the way saving works in games has to fundamentally change. Developers have to rethink how their save systems work, and consumers deserve clear upfront information about how they can use any games' save system. Why is this important? Because knowing upfront the information about the save system can directly affect whether you enjoy the game, whether you can finish it, and whether you can access all the content. The handful of recent titles that drove me to think this through were Metroid Prime 3: Corruption on the Wii, Rock Band 2 on the Xbox 360, Half-Life 2 on the Xbox 360, and Star Wars: The Force Unleashed on the Wii.

What is a saved game?
Wikipedia defines a saved game as:

A saved game is a piece of digitally stored information about the progress of a player in a computer or video game. This saved game can be reloaded later, so the player can continue where he or she had stopped. Players usually save games to prevent the loss of progress in the game (as might happen after a game over unless the game features permadeath, in which the save file is permanently deleted), especially when interrupting or ending a game session.

While that is a perfectly serviceable definition, a saved game is really a piece of the gamers' life. A saved game then allows the gamer to retain a portion of their life that they have chosen to share with you game designer by proxy through the game. Notice I didn't say "your game" to game designers. That's because once you release the product to the public, it is now a shared creation, because the game is nothing without an audience. But a saved game is also more than that, it is the gamer's key to the content which they have already bought! Video games have been using digital rights management (DRM) for years, and no one has been talking about it. Not only to protect a game disc from being copyable, but nearly all games disallow access to all their content unless the gamer has played through the game nearly exactly as the game designer said the gamer should. If the game doesn't allow gamers to save their progress at will and provide access to all content once bought, the game is broken because you game designer aren't valuing the gamers' time, and thus their life. Sorry if that sounds too dramatic, and I know it's only entertainment, but I can't think of another way to spin it.

A word about the kind of games
I am really only concerned with home video games where the gamer is involved with either a single-player or co-op experience. Traditional multiplayer or MMOs aren't addressed with this post because as a shared public experience, there is intentionally and intrinsically, the decision by each individual gamer to participate in that kind of experience. That said, I do over one piece of advice in the solution section for MMOs.

Time is all we have
Time is the most precious commodity any person has. When you engage with any form of entertainment, you want to know if it's worth your time. To make that judgement, you seek out reviews and opinions from people you trust. If you decide that something is worth your time, video games, as far as I can tell, are the only popular mass entertainment form where the consumer isn't in control of the content and the time required to finish the product is open ended. There is no information at the time of purchase, not even an estimate, about how much time it's going to take to finish the game. Movies have running times and the viewer can skip chapters or fast forward and rewind. Songs have length, fast forward and rewind. Books have pages that the reader can randomly turn to. Even sports have a match time limit or set number of points. Concerts have expected length. Games, nothing. You literally have no idea what you are getting yourself into. How can we be 30+ years into home video game systems and still not have such a basic piece of information, duration, easily communicated to consumers? How can gamers still not be allowed to choose what parts of the game to play or not?

What's wrong with save game design?
Simply, the gamer is not in control of the experience. It seems game designers have gone to great lengths to not allow users to have control over the game since there are actually numerous different kinds of save systems employed in modern video games. I am not presuming this is an exhaustive list, but in my experience:

  • Save Anytime. User can choose to save whenever they want, and that exact moment in the game is exactly where they return if they load that save game. There are actually a couple sub-variants on this.
    • Limited to a fixed number. Either through design or technical reasons (i.e. available memory)
    • Unlimited. User can save as much as they like up to the limits of storage
  • Checkpoints. At fixed points in the game, user progress is automatically saved. There are also sub-variants on this kind of save game system.
    • Checkpoints can only be returned to within a level. Once you hit a checkpoint, if the character dies between checkpoints, you return to the previously saved checkpoint. If you turn off the game, you return to the beginning of the level unless the user can also choose to save wherever they want. Another anti-feature to this system is that the current checkpoint replaces the last checkpoint. This is bad because if something is broken in your current checkpoint (e.g. You are stuck on the side of a cliff you can't climb *cough* Halo 3 Highway level) then you can't step back a checkpoint, you have to restart the whole level.
    • Checkpoints can be returned to on game load. Nicer, since intra-game sessions are not snapped to level.
  • Saving embedded in the game world. This is perhaps the worst save system because the game designer doles out the required resource with extreme scarcity. Worse, it makes no sense that a save mechanic is embedded in the game. It would be like you could only pause a movie at certain scenes in movies on DVD, which of course sounds insane.
    • Tokens. If you have ever played a Resident Evil game with its typewriter ribbons, you know what I am talking about.
    • In Game Save Stations. In Metroid Prime 3: Corruption the only chance for a user to save is at certain places in the game (sorry, can't remember the name)
Why are these save systems, excluding Save Anytime - Unlimited, in use today? Here are the reasons I have come up with:
  • Lack of confidence. I can't help but think game designers, perhaps due to the immaturity of the form, in someway fear that players won't want to play their game unless they are in some way artificially induced to progress.
  • Inability to save as a dramatic device. Game designers rely on the inability of the gamer to save progress to create tension. This is bad idea. The tension should come from the story.
  • Game challenge tied to limited save availability. I can hear the argument coming. If you give gamers the ability to save anywhere, what's left of the game? It is way past time to do away with this outdated thinking. For example, in Star Wars: The Force Unleashed, if I could save anywhere, it certainly wouldn't have prevented me from playing through the game. About the only thing it would have done is cut down my artificially inflated play time by about 15 minutes.
  • Masochism. I don't know if gamers or game designers, or both, have enjoyed this abusive relationship, perhaps so, but I for one have had enough. I have stopped playing games that don't respect my time. The reason why Half-Life 2 triggered my thoughts on this is because it's one of the better ones in recent memory allowing you to save whenever. It automatically saves at certain times, but you are limited to a certain number of chosen saves. Also, you don't really get enough information about the save on the load screen.

Solution: Saving is entirely at user discretion and should be a platform feature
This is the way saves should work:

  • Gamers should be able to save anytime, anywhere, as many times as they want. Game designers can continue to structure their games as a series of challenges, but it is up to the gamer to decide if they want to play through the challenges as designed.
  • Saving can be disabled during challenges, but they can't last longer than 15 minutes. A challenge is an uninterruptible task, liking fighting a boss. But at whatever difficulty level you are playing at, those encounters can't last longer than a set period of time. Based on my experience, 15 minutes is the mark. Any more than that, and it's no longer a fun challenge, it becomes a job.
  • Games should have the equivalent of chapter selection on Movies.The user should be able to randomly access any part of the game they want, even without having played through the game. Again, it's up to the user to decide if they want to play the whole game, or if they just want to show their friends a part of the game without local save files.
  • All game controllers should have a Save button. Seriously, 2008, and there is not a uniform way to trigger either a save game screen, or ideally a "Quick Save" option. Also, why not normalize some buttons with DVD+DVR controls? The "start" button on the Xbox 360 should just be labeled a play/pause button. The back button could easily be replaced with a Quick Save button.
  • Game system should standardize the UI for save games. No developer should have to spend time writing their own save systems. It would be like having to write the code for DVD player pause/play functionality every time you release a movie, insane.
  • Save games should be backed up by the platform (e.g. Xbox Live, Playstation Network) and synched to your other consoles No reason I shouldn't be able to start playing a game on the console under my big screen TV, make progress on it at a friends house, and then finish it at home again.
  • Access to game content in multiplayer modes should not be tied to progress/completion of single player content. I can't tell you how many now I buy a new game to play the multiplayer parts first, only to find it's crippled because I haven't played the single player part. Mario Kart Wii, Star Wars: The Force Unleashed Wii, Rock Band 2, the list goes on and on. And sorry, unlock codes are lame, a relic of a bygone era. If the industry wants to grow up, it has to stop doing this. Also, unlocking content is not a re
  • Save game files should contain information about the game at the point in time, so the gamer understands where in the game they are. Actual thumbnails from the game when you save are a must. More detailed information too, like any meters you can see on screen, you should be able to see the data about that in the save.
  • Games need to auto-reload to last save on launch. What happens when you watch a movie and turn off your DVD player, or watch a video in iTunes, then stop it and start playing again? It resumes from where you left off. All games should default to this! If this isn't the 90% case when playing through a single player game, I don't know what is. But this load also needs to be cancelable on the chance that its wrong. The current way most games work is just dumb. On Xbox 360, you have to:
    1. Start the game
    2. Click a button to get past the obligatory landing screen after the parade of logos
    3. Select Load Game and press button
    4. Select where you save game is stored
    5. Figure out which save game you want to load
    6. Wait for load
    Loading the last user saved or system saved game should be the default in all games until the user quits the game in a different mode (e.g. multiplayer), which it should then launch into.
  • Stop showing most publisher/studio/tech logos on launch. Take a cue from the iPhone, when the user or game saves progress, take a full screen snapshot of where in the game the player is. When the game is reloaded at launch, show that screenshot with a progress meter if its a long load, or just get the game running and make the content animated from that screenshot frame. You can even composite unobtrusive logos in a letterbox like fashion over top of the saved game screenshot. Animated logos with surround sound are only cute once, then despised every time after through the appearance of blocking the gamer from getting back into the actual game. I don't need to see the Havok logo anymore in a game, I get it. The equivalent would be like having to see that the filmmakers used Panavision or Kodak before the movie even starts, silly. Doesn't everyone hate having to sit through the FBI warning? That's one of the sweet things about movies from iTunes, no FBI warnings, trailers, or multiple studio banners, one on the film and one for the home video division. If you have to pay a few more dollars to get the engine credit to the end credits, please do so.
  • For MMOs with challenges (e.g. Raids/Dungeons) dependent on a group, use game telemetry to provide probable time estimates. I have done my fair share of raiding in World of WarCraft. I was never able to do a lot of raiding because I never had a good idea how much time any raid or dungeon run was going to take. WoW collects a tremendous amount of data about the game, which I call telemetry, and it should be used to provide gamers estimates based on past raiding/dungeon parties similar to your own.

Wrap-up
I am sure I have missed something, or there are holes in some of my arguments. This post was already long enough, covering every possible corner case would have made it ridiculously longer. I am more than happy to answer any comments, or if you want to send me an email you can through innerexception AT mac.com

Wednesday, October 15, 2008

iPhone app version and build numbers

I think every iPhone developer should know how to assign version and build numbers to their app. If you have come from another platform, like I have, the Apple way is the same but different. I am standing on the shoulders of Chris Hansen for a lot of this post. His post on Xcode: Build numbers and versioning with agvtool was the starting place for me on a lot of this information. Chris' post is nearly 3 years old now, Apple has moved some stuff around and it isn't iPhone specific. Plus, there are no screenshots :-)

Marketing or Build Version?
Apple's iPhone application templates create an Info.plist in the Resources group for you that is configured like this:

Highlighted is the Bundle version with a default value of 1.0. This was exactly how iTimeZone 1.0 was configured. For iTimeZone 1.1, I wanted to be able to show both the marketing version (Version 1.1) and the build number (Build 14), and toggle between them in the app, since I was going to distribute the app to beta testers. So i thought Bundle version was the marketing version because the templates fill it out with 1.0, but that is not the whole truth. Since the iPhone app templates don't really do anything with Bundle version, you have to look at a Cocoa OS X sample application to see the right behavior.

When you only have Bundle version, in a Cocoa OS X app you see a built-in About box that looks like this:

When you add a new key to Info.plist called Bundle version string, short, and flip your 1.0 into that key, and then put something more traditionally resembling a build number (14) back into Bundle version, the Cocoa OS X built-in About box looks like this:

So which keys you should use on the iPhone are pretty clear, Bundle version is really your build number key, and Bundle version string, short is really your marketing version. Now lets build something.

Build It
Whenever you hit Command-B in Xcode, you are creating a build. As a developer you are building all day long. But a developer build and a build you intend for distribution are two different things. When a build is distributed, you need to assign it a unique identifier so you can ask people what version they are on or for bug reporting purposes at a minimum. This is usually referred to as the build number. I am not talking about continuous integration here, only the manual process, but if you wanted to setup continuous integration, you just need to automate what I talking about.

Apple has a tool, called agvtool, to increment build numbers, the Bundle version in your Info.plist, as well as make that number a variable in your code. The tool is called agvtool for Apple-generic versioning tool for Xcode projects. In order for it to be usable, you have to change a few build settings in the Versioning section for All Configurations. Here is the screenshot of iTimeZone 1.1:

The key setting is Versioning System. This must be set to apple-generic. I don't know of any other possible setting except None. This does not mean that Xcode now automatically increments a build number for you, you have to take specific action to get the build number incremented. Now that those are set, you have to close your project, open Terminal, and do the following to increment your build number:
/Developer/usr/bin/agvtool next-version -all

This was one of differences with Chris Hansen's post, Apple moved the location of the tool. Also, I encourage you to hit man agvtool for all the options, like automatic check-ins to source control on running agvtool, but I haven't set those up yet. Now you have pretty much everything you need to use the build number system, but you need to be able to use this information in your iPhone app.

Using Build and Version Numbers In Your iPhone App
Unfortunately, there really isn't at the time of this writing a defined pattern for displaying version numbers or build numbers in iPhone applications. In iTimeZone 1.1, I choose to put a dedicated About screen into the app. Not only to show version and build numbers, but a couple of links to give credit for usage of assets in the application, and double-tappable icons to the iTimeZone and Tangerine Element web sites.

When you tap on any whitespace, or directly on the version number, you see the build number. To show these properties in your app, you need to know what the real names of the keys are. If you right-click on any of the properties in the Info.plist view, click Show Raw Keys/Values to see a view like this:

I created an AboutViewController with a corresponding XIB. In the viewDidLoad method, I set the UILabel to the version number by doing this:

[NSString stringWithFormat:@"Version %@",[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]];

When the user taps the view, a BOOL is used to track what state the view is in. When the build number should be changed, the UILabel is set to the the other number, so for the build number:

[NSString stringWithFormat:@"Build %@",[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]];

Wrap Up
So I think that's it. Let me first say, I am not saying you have to do an About screen in your app, I didn't have one in iTimeZone 1.0. That said, unless I am just not thinking outside the box enough on this, I can't see how to conduct a beta test without being able to check the build number, and there is simply no facility for doing that built-in to iTunes or the iPhone. You can probably hide this in your app elsewhere, but it probably needs to be there.

Thursday, October 09, 2008

Refined the iTimeZone 1.1 Splash Screen

After I posted On iPhone Splash Screens, I started thinking that I should tweak the iTimeZone 1.1 splash screen just a bit. In 1.1 Beta 2, I have the map in the area that alternates between the map and the table view. The table view is going to be what users see well over 90% of the time, so I thought I was giving users the wrong idea by including the map on the splash screen, so I took it out. In 1.1 Release Candidate 1, I also added the copyright notice on the bottom toolbar. The iTimeZone splash screen is a bit of a hybrid, with some Twitterrific like splash elements (app name, copyright notice), as well as the UI elements that will be visible at launch, but I think it's now just the right mix between the two.

1.01.1 Beta 21.1 Release Candidate 1

One more point. I created the copyright text using Acorn. To get the shadow to look like the iTimeZone already in the image which was rendered on the iPhone, I used the following settings

On iPhone Splash Screens

Craig Hockenberry posted today about why Twitteriffic for iPhone/iPod touch uses a splash screen. I have considered the splash screen a number of times for iTimeZone 1.1, but ultimately decided to continue to include a screenshot of the app to make it appear like its starting fast. I actually added more to Default.png so that the illusion is perhaps better, here is the 1.0 to 1.1 side by side:

1.01.1

But it would be so much better if, as Craig suggest, the iPhone OS would save a PNG whenever asked, then load that instead. I don't think this is really voodoo, or something hard for Apple to do. Seems like the logic is just this easy:

  1. If Default.png exists in user's application document folder (i.e. the NSDocumentDirectory of NSUserDomainMask) load it
  2. Else, load Default.png from the bundle root
  3. No step 3
Should be a new option in Info.plist that can be set to automatically have iPhone OS create the user Default.png at application shutdown, or the app can do that itself if desired.

I spun up a quick sample project to test if this was already implemented in iPhone OS 2.1 undocumented, but it doesn't appear to be unless I stuck the user Default.png in the wrong spot. I used the same method from iTimeZone 1.1 to copy a user writable SQLite database, which itself was pretty much straight out of Apple's SQLite Books Sample, to copy a Default.png into the application specific user document folder:

- (void)createUserDefaultPNGIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableUserDefaultPath = [documentsDirectory stringByAppendingPathComponent:@"Default.png"];
success = [fileManager fileExistsAtPath:writableUserDefaultPath];

if (success) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultUserDefaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Default-users.png"];

success = [fileManager copyItemAtPath:defaultUserDefaultPath toPath:writableUserDefaultPath error:&error];
if (!success) {
NSAssert1(0, @"Failed to create user Default.png file with message '%@'.", [error localizedDescription]);
}
}

The variables at runtime look like this:

It doesn't work. If I change NSDocumentDirectory to NSApplicationSupportDirectory, I actually get an NSException that No such file or directory exists.. I didn't walk through the paths to figure out which one, Library or Application Support are not there, I suspect both. Here are my variables using NSApplicationSupportDirectory:

So I created the whole path doing this [fileManager createDirectoryAtPath:documentsDirectory attributes:nil]; and was then able to put a Default.png in the NSApplicationSupportDirectory. Still, iPhone OS did not load the user's Default.png instead of the bundle's Default.png.