Wednesday, December 22, 2010

iOS Game Center Icon Overlay

In case you missed my sample icon I used in the Icon Set Creation Tool, I was using a nice Game Center logo, like all the other social gaming providers use. Well to my dismay I found a post on the Apple developer forums that "we" are not allowed to the Game Center logo in our apps icon. Now I'm not sure its specific to the full size logo which would be pretty dumb, right?

<begin side discussion>
Apple really screwed-the-pooch on this whole Game Center branding... they are playing it like they are too cool for branding like OpenFeint and the others use... but lets face it, Apple is ALL ABOUT branding...
</begin side discussion>

Anyhow... got me thinking.

Here is my rendition of a Game Center overlay that you can use for your app, no credit required. If you want to make it better please just drop me a line and I'll share the PSD file with you.


Upper Left logo

Upper Right logo

Lower Left logo

Lower Right logo

You can also download a ZIP FILE HERE.





Saturday, December 18, 2010

iOS Icon set Creator

UPDATED HERE: View Post

I was updating the icon for Easy Lander and was annoyed every time I wanted to see the update in the Simulator or on my device because I had to take my new 512x512 icon and resize it, a few times.

<fanboy alert!>
This is why I love using a Mac! - AUTOMATOR to the rescue!
</fanboy alert!>

So here's what the Automator workflow does:
Asks for your 512x512 icon image then duplicates it, scales it and renames it, rinse and repeat until all five (5) icons are created.

Icon@2x.png = 114x114
Icon-72.png = 72x72
Icon-Small@2x.png = 58x58
Icon.png = 57x57
IconSmall-50.png = 50x50
Icon-Small.png = 29x29

The workflow WILL NOT overwrite any existing files so make sure to put your 512 image in its own folder.

1000 words.....

Test folder with 512 icon (can be named whatever you want)

Launch Automator app and click the Run button...
Browse to and select your 512 icon file
This is where the "magic" happens (lol!)

Completed folder with shiny new icons, yeah!


In the zip file is a second Automator "application" named "Create iOS Iconset Droplet". You don't run this application you simply drop your 512 icon onto it and the magic happens... sweet right? I know... :-]

Download link CLICK ME

Friday, December 17, 2010

iPad & iOS 4.2

Now that I have used iOS 4.2 on my iPad for quite awhile now, I can emphatically state that the iPad does NOT have enough system memory to fully support multitasking!

Yup, I said... :-/

More times than not I switch from one app to another and the app is not in the background and these are apps I know support multitasking.

Mark my words, the iPad 2 will have at least twice the memory, if not three times.

Thursday, December 2, 2010

iTunes Holiday Shutdown

Just noticed the part about any price changes... YIKES!

iTunes Connect will be temporarily shut down from Thursday, December 23 to Tuesday, December 28 for the winter holidays. Do not schedule any pricing changes to take effect during this time. Changes scheduled between these dates will make the app unavailable for purchase. Note that any app with an available date scheduled during the shutdown will not go live until iTunes Connect access resumes on December 29.

Monday, November 29, 2010

Game Center, oh game center...

how I loathe thee....

Sorry.... more to come. Just venting about all the extra work involved in getting GC up and running in Easy Lander....

Monday, October 11, 2010

Thoughts on Older Devices

So, lets put some "truthiness" (full credit to Stephen Colbert) down on paper about decisions, or better yet a "strategy" an indie developer has to make. The strategy I'm referring to is of course around supporting older devices. Well what does that mean? Thanks for asking Virginia, let me share my (recent) thoughts.

Most if not all indie developers need to make money. If you are an indie and this does not apply to you then stop reading now. Okay we got that out of the way, so we can openly admit to any and all that:
  1. We need to make money
Now we need to find out, given our target audience, how much users with a 2 or 3 year old iPod Touch or iPhone actually spend on apps in the App Store. Because that's how much the impact will be if we choose to NOT support older devices. But hang-on, if we can admit all this and move forward, guess what... we can actually develop BETTER apps! Yup, there you go, more "truthiness" for you! :-]

Yes, if we don't have to worry about how our app runs on a 2nd Generation iPod Touch running iOS 4.x or even iOS 3.x then our development environment just got a whole lot smaller and more defined. If we draw the line at multitasking devices only then we double the amount of memory (and openGL texture size) for our apps. This is huge. In addition we can also target openGL ES2 instead of 1.1 and we can streamline our code (e.g. just use blocks instead to having to runtime check for support). Yeah, I see your eyes widening... its okay. You should at least consider it and NOT once you're half-way into your project, I mean right from the start.

So this is what my new strategy might look like:
We will fully support iOS 4.x users with devices that support multitasking, including 3rd generation iPod Touch and newer along with iPhone 3GS and newer devices.
Wow, that felt great... now the decent thing to do is to post this new strategy on your web site.

Thursday, October 7, 2010

Game Center Design

I've read numerous forum and blog posts recently and initial reactions to Game Center from Users is:
The login (UIAlertView) sucks and looks like the app is trying to steal my iTunes Account.
This is a good place for a pre-sign-on modal view or alert, asking if they want to use Game Center and explaining that the next dialog box is required to log into / authenticate with Game Center and is provided by Apple. If the user doesn't want Game Center then disable it and prompt them no more. Also let them know where to turn it (Game Center) back on should they want to use it in the future.

Just my $0.02 :-]

Wednesday, October 6, 2010

Taking Advantage of the RootViewController

that is now available in cocos2d 0.99.5

I mentioned in a forum post about how cool it is not that we have an actual view controller available to us to hang stuff off of. A few people have asked about what I was referring to, so here's a sample project.

This is just the cocos2d base template with the MessageUI framework added (required for in-app email) and a few bits of code.

First we'll add a menu to "Hello World", add this in the layer init;

CCMenuItem *emailItem = [CCMenuItemFont itemFromString: @"Email" target:self selector:@selector(emailCallback)];
CCMenu *menu = [CCMenu menuWithItems: emailItem, nil];
menu.position = ccp(50,50);
[self addChild:menu];


Now add the emailCallback method;

-(void) emailCallback
{
    [(BaseEmailAppDelegate*)[[UIApplication sharedApplication] delegate] sendEmail];
}

In our app delegate we need to create our sendEmail method;
In the .h file

-(void)sendEmail;

In the .m file

-(void)sendEmail
{
    [viewController displayComposer];  
}

In our RootViewController we need to create our displayComposer method;
In the .h file
Import the MessageUI header

#import <MessageUI/MessageUI.h>
and add MFMailComposeViewControllerDelegate
@interface RootViewController : UIViewController <MFMailComposeViewControllerDelegate> 
{
}

-(void)displayComposer;
@end

In the .m file

@implementation RootViewController


#pragma mark -
#pragma mark Setup Mail Alert
- (void)setUpMailAccount {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"System Error"
message:@"Please setup a mail account first."
delegate:self 
cancelButtonTitle:@"Dismiss"
otherButtonTitles:nil];
[alert show];
[alert release];
}

#pragma mark -
#pragma mark Compose Mail
// Displays an email composition interface inside the application. Populates all the Mail fields. 
-(void)displayComposerSheet {
if(![MFMailComposeViewController canSendMail]) {
[self setUpMailAccount];
return;
}
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;

[self presentModalViewController:picker animated:YES];
    [picker release];
}

-(void)displayComposer {
NSLog(@"pop-up email here");
[self displayComposerSheet];
}

// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSaved:
break;
case MFMailComposeResultSent:
break;
case MFMailComposeResultFailed:
break;
default:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Email" message:@"Sending Failed - Unknown Error :-("
delegate:self cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
}
break;
}
[self dismissModalViewControllerAnimated:YES];
}

Here is the LINK to the sample project.

Tuesday, October 5, 2010

iAd's in Universal App

In iOS 4.2, there is a change in the references to the ADBannerView size. We used to use:
ADBannerContentSizeIdentifier320x50ADBannerContentSizeIdentifier480x32

But now we need to use:
ADBannerContentSizeIdentifierPortraitADBannerContentSizeIdentifierLandscape

This allows iOS 4.2 to resize the iAd based on the device / window size.

So how do you create a universal app that uses iAd's AND will run on iOS 4.0? Here's what I did (based on some help from Rincewind on the Dev forums; I didn't know how to check for an NSString. Now I do! You use &<string> and if that doesn't equal nil, you are good to go).

Overview: I chose to create two new string values and then based on whether or not the app was running on iOS 4.2, set them to the appropriate identifier.

In .h file (view controller)
{
     NSString *PortraitBanner;
     NSString *LandscapeBanner;
}
@property(nonatomic, retain) NSString *PortraitBanner;
@property(nonatomic, retain) NSString *LandscapeBanner;
@end

In .m file
@synthesize PortraitBanner;
@synthesize LandscapeBanner;

in my createBannerView method:
//If true then we're on iOS 4.2 (or newer) and we can use the identifiers
//If not true then we use the old identifiers
if (&ADBannerContentSizeIdentifierPortrait != nil) {
     PortraitBanner = ADBannerContentSizeIdentifierPortrait;
     LandscapeBanner = ADBannerContentSizeIdentifierLandscape;
     NSLog(@"Running on iOS 4.2 or newer.");
} else {
     PortraitBanner = ADBannerContentSizeIdentifier320x50;
     LandscapeBanner = ADBannerContentSizeIdentifier480x32;
     NSLog(@"Running on Pre-iOS 4.2.");
}

//Don't forget to release
in dealloc:
[PortraitBanner release];
[LandscapeBanner release];


Note: If you haven't checked out the Apple sample code iAd Suite, that's where my createBannerView method came from.

Then pretty much wherever you'd use one of the "ADBannerContentSizeIdentifier*" strings, use either PortraitBanner or LandscapeBanner. I've tested my app on iOS 4.1 and iOS 4.2 on several devices and my iPad and it is working fine.

Friday, October 1, 2010

It's Official!

Supporting multiple iOS versions is a real pain!

The last update for Hyper WARP (iPhone v2.7) has a problem only on iOS 3.x - ARG!! I tested the update several times but failed to test the final build (<- yup I know, what a dummy!). Even after I posted THIS PAGE on our site... double ARG!

Makes me reconsider supporting pre-iOS 4 at all... When we started both iOS 2.x and iOS 3.x were available but almost all of our apps only supported iOS 3.x. Man that kept things very nice for testing, no need for a 2.x test device. Now with a bunch of devices still running iOS 3.x, I've really got to give this some thought.

:-/

Tuesday, September 28, 2010

Minimum Requirements For Your Game

I think at a minimum, a game should provide:

  • Menu:
    • logical structure
  • Pause option:
    • have some way for the player to pause
  • Save and resume:
    • have some way to resume a saved game
  • User options: 
    • sound / music adjustment
    • controls adjustment (if applicable)
  • Credits:
    • developer info w/email
    • link to website / other games

So what are your minimum requirements for a game?

Wednesday, September 22, 2010

Stable or Cutting Edge?

So... when you are developing your next awesome cocos2d game / app which approach do you use?

[stable approach]
1. Take the stable release and never look back (forward).

[cutting edge approach]
2. Take the newest release and revise your application and always look forward.

I've been using the cutting edge approach on LoH and it's been okay but I'm sure I'd be further along if I took the (easier) path. You end up refactoring your code when and if things change but we are so close to version 1.0 that I think it's easier to keep up incrementally vs one huge update later on.

Cutting Edge
PROS:
* Use the newest features and functions (like easily integrate UIKit stuff, e.g. Email / Game Center)
* Quick support on bug fixes and patches
* Enhances code

CONS:
* Slower / longer development cycle
* Re-factor code
* Fix errors and debug

Is there a third option I have overlooked?

Friday, September 17, 2010

Batch Transform (transparent) Images

I used the following to remove the backgrounds from around 32,000 sprites in about 4 hours. My sprites are also now all in English with no spaces (only way I could get the Automator shell script to work).

Requires ImageMagick, an open source command line image processing utility. The easiest way to install it is by using MacPorts.

Phase One (prep all folders)
Pre-process Automator workflow to rename all sub folders from " " to "-" (eg "skel with sword" to "skel-with-sword"). This is required for the entire path all the way to (and including) the .png file, so to make it easy I moved my artwork folder to my desktop. This same workflow is also used to rename all the image files. Now that all the spaces have been removed the shell script inside the final Automator workflow will run without errors (yeah spent about 4 hours on that problem and if someone can get it to work with spaces in the path / file name, please let me know).

Phase Two (prep all sprites)
Using another Automator workflow, renamed all sprites to use English (e.g. Lauft = Running) words. I also used this script to update the base names (e.g. SkelSword, SkelStaff, SkelBow, etc). Note: this is not required at all but I figured while I was at it, might as well make the files easier for me to use.

Phase Three (individual sprite folders)
1: Copy one of the sprite images to the desktop, rename it "background.png" and then open in Pixen and make it a solid color using the existing background. This file is then used by the shell script with ImageMagick to remove itself, i.e. make transparent, against the other image(s).
2: To process we run a third Automator workflow and select all the images to be made transparent (that match background.png). Repeat steps 1 & 2 above for each folder of sprites.
Note: if you skip step 1 because the background looks really close to the previous one, you may end up with 3/4 sprites (I know I did!) and it wasn't worth the few seconds it takes to create the new background.png file.
Speed: On my 2.4GHz iMac it would take less than 2 minutes to process ~600 images. At this point if you have the folder displayed in Finder with preview on, you'll see the new transparent images as they are processed.

Okay now that I'm typing all this out I'm thinking, WTF is wrong with me? But it actually worked very well and fast! Now it is very easy for me to repeat this process and I have re-used these Automator workflows many times.

It was actually very good that I recorded the process while it was still somewhat fresh, in case I ever have the need to repeat the process.

Note: I have included a link to my Automator workflows for anyone that wants to use them. If you do happen to get it to work with files / path names with spaces in them, please let me know. Thanks

Testing Your Game Center Apps

Update: October 6th, 2010 - looks like there are some new Sandbox screens. I'll try and update the images.


So now that you can access Game Center on your (compatible) iOS device running 4.1 (or higher). Testing your own GC apps is now a bit of a snafu.

Here's what I have found: First, you'll need to get your app setup in iTunes Connect (see Apple Docs). You'll need to test a debug or ad-hoc build, I have found both of these builds will work (in case you see it posted elsewhere that you must use a debug only build). 

Once you install your test app on your device;
1. Launch Game Center and tap your email, select "Sign Out" and now close Game Center.
2. Open Settings, tap Store and tap logout (this helped me once and I still do it, not sure if it's required but it certainly won't hurt). 
3. Now launch your test app and sign-in with a sandbox test account OR (better still) create a new account. 
Note: I use a bogus email account since I don't have email addresses hanging around for testing purposes. I will try to grab and post a screen-shot because once you launch the sandbox version of GC you'll notice the new account setup screen is noticeably different.


First Clue: Login to sandbox:




Sandbox Signup:


Production Signup:



Tuesday, September 14, 2010

iOS Developer Utilities

Open Source iOS Add-ons

There are several open source iOS add-ons that I use and maybe there are some developers that do not know about them. Here's my listing:

* In-App Purchasing: Excellent blog post with source code to easily add In-App Purchasing to your app. The only thing that I have updated is to use the keychain and not NSUserDefaults. See Keychain Access below.

* Ask for Review: Add this to pop-up an alert after X-days or X-launches of your app and prompt the use for a review.

* Keychain Access: Add this to easily access (store and retrieve) data from the secure keychain. Use it in combination with In-App purchases for an increase in security.

* Mobile App-Sales: Use this to track your iTunes Sales info (jonkean's branch works now).

* Three20: I personally don't use it but many developers do.

I will keep this post updated as I find new ones too.

Monday, August 30, 2010

iAd Tip

Posted this on my site but thought it was worth posting here too. When you are viewing an iAd sometimes the dismiss "x" doesn't seem to work.



No worries, just press the "Home" button. The iAd will exit and you'll return to your application.

Saturday, August 28, 2010

Info.plist Cheat Sheet

Updated: Nov 1, 2010

I routinely need to look up information about entries in an applications Info.plist. I even saved the Apple PDF to my hard drive. Still, I find myself looking for an example. Of course there is no one perfect Info.plist but here's a sample that I put together for a universal app that we want to only run on an iPhone 3GS or newer device. After reading a few threads on the Apple Dev forums it was pretty clear that the arm7 entry for the UIRequiredDeviceCapabilities key is NOT working. So, as a work around we can use opengles-2 (which of course requires an arm7 cpu).

BONUS TIP #1: Use Xcode to edit your Info.plist files. Why? Because it knows about all the entries and saves you from copying and pasting or typing the wrong one. Go ahead, try it now... I'll wait. Add a new row and look for "Icon Fi" and you'll see both "Icon File" and "Icon Files" in the drop down. :-)

Sample Info.plist
Let's highlight some entries:
  • UIPrerenderedIcon - turns OFF the gloss effect on your icon. Note you can still use a square icon and it will be rounded. This only effects the shine
  • Icon file - used by older iOS's to know the name of your icon. Yes you can name your icon "my_super_cool_app_icon.png", but why???
  • Icon files - used by iOS 3.2 (iPad) and higher. The tricky part is its an array of icon names and you really can't go wrong by following Apple's example. Each icon listed is for a different purpose and no you don't need them all for just an iPhone app but why not just get in the habit.
  • UIStatusBarHidden - Ever notice some games or apps launch and you can still see the statusbar and then once the app finishes launching it disappears, yeah me too. They didn't know about this entry, keeps the statusbar from showing.
  • UILaunchImageFile~ipad - Ah the iPad and its damned "you can hold it anyway you want" crap! Sorry... This entry says HEY iPAD! look for an image named "Default-<orientation>.png" e.g. Default-Landscape.png. For example, suppose you want to include portrait and landscape launch images for iPad using the base name MyiPadImage.png. You would include the UILaunchImageFile~ipad key in your Info.plist file and set its value toMyiPadImage.png. You would then include a MyiPadImage-Portrait.png file and a MyiPadImage-Landscape.png file in your bundle to specify the corresponding launch images. Which leads us to:
  • UIInterfaceOrientation - This tells the device, look I'm going to startup in THIS direction. See how it matches the above image.
  • UISupportedInterfaceOrientations - this array tells the device which orientations your app supports. And finally.
  • UIRequiredDeviceCapabilities - this array tells the device, here's what we need to run. If you don't meet these requirements, don't even install me. This of course works on the device via the AppStore and it works through iTunes. It will pop-up an error saying "MySuperCoolApp" cannot be installed on Greg's iPhone because it doesn't meet the requirements. So here is where we can limit our app to only run on arm7 devices by requiring opengles-2. 
Which now that I think of it makes perfect sense why using the cpu key isn't a good idea anyway. Who's to say Apple's next cpu won't be arm8 or something.

BONUS TIP #2: You can add your own keys to the Info.plist file and then pull them out using:

NSString *myKey = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"MyCoolKey"];

Have any other Info.plist tips or questions? Post a comment.

BONUS TIP #3: Use Xcode 4 beta to open and save your project and you'll get a bunch of these entries and more in your Info.plist

Thanks

Link to Apple Dev Docs


Friday, August 27, 2010

Mental Health Day

After about three weeks of hammering out code on Legends of Hylore and learning cocos2d at the same time, I literally heard one of my brain cells pop! Yup, scared the crap out of me.

So this was the perfect time to switch modes and do some.... more coding??? Yes, its what relaxes me and it was a project I'd been putting off for quite awhile. A Contact Lens Tracker.

I know, there's quite a few in the app store now and most of them are free... but they all pretty much suck. I wanted an app where I could tap a button when I started a new pack of contacts and then IT should remind ME when to change them. IT should also remind me to order more contacts before I run out and as a final touch it should even remind me when to call for an eye exam.



Well IT is called Lens Tracker and is now ready for sale.

So now that that's out of my system I can get back to Legends of Hylore, well rested and ready to go!

2nd try...

Well this is now my second attempt at blogging. Let's hope I do better this time 'round.