Designers New to iOS

It’s nice to be back writing a new #iDevBlogADay post. I don’t have a lot of time to write a large and in-depth article as I’ve been really busy with some contracts, while burning the midnight petroleum on a new startup idea.

I’d like to quickly discuss an issue that has been nagging me over the past while.

Several times over the past year I’ve encountered graphic designers who are well-known for elegant websites or really well-designed desktop UI’s. However, they are relatively new to the new “medium” of mobile. This is fine and expected since mobile development is still somewhat new and everyone has to start out somewhere.

When you’re a small startup with little (or no) funding, you can’t afford the most experienced and talented designers to get your first prototype out the door (nor should you even consider it). You’re likely looking for students or people transitioning into the field.

I’ve compiled a quick list of some tips that all designers (AND devs) who are looking to break into the mobile space should review:

1) Get an iPhone/iPod touch, and an iPad

This is obviously a hefty investment (min. $800), but you NEED both the phone/touch and the iPad to really understand the behaviour of apps. Yes, buying games and other apps is research in this case. You must be doing this to understand the various common paradigms that apps in the store already use for UI/UX. You don’t need the latest iPad2. I highly recommend a 3rd or 4th gen touch or iPhone4. I mention 4th gen touch/iPhone4 because you also have to get used to cutting UI’s for retina displays.

I can’t stress the above point enough — it’s #1 for a reason. Don’t fool yourself and others into thinking you can design great UI’s and UX’s without knowing the device like the back of your hand. Pick up as many apps as you can afford. Analyze the good and the bad. This is part of your research into what really works and what doesn’t!

2) Get comfortable with the published iPhone/iPad Human Interface Guidelines (HIG)

http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.html

3) Get used to wire-framing & quick mockups for iOS apps

Either using a notepad and pencil, or one of the many wire-framing apps for the desktop or iPad. Wire-framing allows you to quickly mock up the UI for the various use cases of the app. If you have any suggestions for YOUR fav wire framing software, leave a comment!

4) Use flash for mockups

I haven’t done this before, but lots of designers have mocked up the complete app using flash first. If you are proficient in Flash/Actionscript you can pump out some UI prototypes really quick. This allows you and your client to get a feel for the flow of the app and you can quickly realize what’s going to work and what won’t.

5) Get used to LiveView

http://www.zambetti.com/projects/liveview/ Many designers swear by it.

6) Talk to Developers

This is fairly dependent on the context, but work with the developer to figure out the most efficient way to cut up your table cell designs, backgrounds, stretchable buttons, etc.

7) Read, Read, Read

Search around some of the previous iDevBlogADay posts and find some of the many posts recommending books on the subject of design. I encourage you to leave a comment with your favourite design reference book.

All said and done, creating a sharp and effective UI is no trivial task. Be ready to iterate and ask for loads and loads of feedback on the design and app. Find some iPhone loving friends.  Ask around on Twitter!

If you know of any other great tools that a designer can use for UI/UX design, please leave a reference in the comments.

This post is part of iDevBlogADay, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Posted in Blog, Business, iDevBlogADay | 1 Comment

Make Your App Easy to Rate

One very important aspect that may help boost sales of your app is the App Store’s Ratings and Reviews section associated with your app’s description.

Apple App Store Ratings and Reviews introduces a decent amount of “deal breaker” potential. Once the user has reached your app’s description, screenshots and the reviews are the main guides that a casual user would check before making the decision to dig real deep into their pockets and fork over the buck or two for your app.

With that in mind, why not politely ask the user for a couple of minutes of their time to review your app. You can even make it really easy for them, as I’ll show in this post.

The Objective

The objective with this technique is to “ease” the user into a feedback loop. How would one “ease” the user? It’s recommended to ask the user to leave a rating AFTER they have experienced a good amount of the functionality in your app. If you have a game, this might mean after they complete a level or two, or after they beat some achievements or goals. If it’s a utility app, perhaps ask them after a certain number of uses of the app itself (i.e. from launch to resignActive).

Remember that asking the user to write a review is still a fairly disruptive action. You don’t want to prompt the user during a game sequence or ask them while performing some critical data crunching operation. Prompting them right after the app loads is a definite no-no.

If you aren’t sure of the best time to prompt the user for a review, go the less obtrusive route and simply add a nice big button in your Help or Settings view. The user has more of a chance to ignore it, but it might be the right way to approach this aspect for some apps.

Another important thing to remember is that Apple allows a buyer to leave another rating / review after an app update. This is something you should take advantage of.

The Implementation

The logic behind asking the user to review your app is fairly straightforward. You need the following machinery:

1) NSUserDefaults will store whether the user has elected to provide you with a rating or declined. It can also be used to track the version of the app that was last rated.

2) [[UIApplication sharedApplication] openURL:@”url”] will be used to launch the App Store app and directly link to your app’s description.

3) UIAlertView will be used to ask the user to provide a rating/review. Also allow them to gracefully decline.

[objc]

/*
Ask the user if they would like to rate the app
Yes or No. Keep it simple. Users like simple.
*/
UIAlertView* alert = [[UIAlertView alloc]
initWithTitle:@"Review App"
message:@"Would you like to rate
APP_ NAME and leave us a
review?\n\nIt will only take a
couple of minutes and will
help make this game better
for everyone."
delegate:self
cancelButtonTitle:@"Rate It!"
otherButtonTitles:@"No Thanks", nil];
[alert show];

// if the user agrees to rate…
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:YES forKey:@"versionISRated"];
[userDefaults setObject:@"1.0" forKey:@"ratedVersion"];
[userDefaults synchronize];

/*
if the user declines to rate… also reset the counter
to detect how many iterations of use between the
next time the user is asked
*/
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:YES forKey:@"declinedRate"];
[userDefaults setInteger:0 forKey:@"countFromDecline"];
[userDefaults synchronize];

/*
if the user agrees to rate you will then
launch the link to your app’s App Store page.
tested in 4.2, the URL provided in the discussion
below should directly launch the App Store app
*/
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];

[/objc]

Rate it!

The best link (for an iOS device) that will directly launch the app reviews in the App Store app:

itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=##

The “##” is your app’s unique ID. This can be obtained from your app’s iTunes Connect profile.

@BusinessRan let me know that the above link doesn’t work for iPad only apps. i have also used the following URL for my iPad only app:

itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=##

Declines

If a user declines to review, it may simply be because they don’t have time right then, or they simply aren’t in a good mood. Be sure to track that they declined. Give them a break and don’t ask them again for another series of “uses”.

The idea is to track how many “events” that would normally cause a ratings request to occur. After N iterations of events (N = five or six?), ask them again!

Remember that being persistent can be important (to a point). Since you are selling the app at such a low price point, the user really shouldn’t complain (although, if they do, that’s also their right) that they are asked to do something SO hideous as to leave a review of your app.

Even if the user outright declined to rate the first or second time, maybe by the third time they’ll have understood the value of your app.

Ask After an Upgrade

Don’t forget that after the app has been upgraded, you absolutely need to ask them again to get their feedback on all the new features.

Testing

PLEASE, make sure you test this feature adequately. For example, make sure you delete your test app from the device a few times to be sure you start fresh with the defaults cache.

The last thing you need is the app asking the user for a rating EVERY time they launch it or play a level. Guaranteed that won’t help your ratings.

I haven’t provided all the logic you need — homework for the reader. There are a number of great snippets available online. Google will tell all and help you along the way. DO take heed of the advice given in this post!

This post is part of iDevBlogADay, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Posted in Business, Game Dev, iDevBlogADay | Tagged , , , , , , | 4 Comments

Chipmunk Physics Engine, Part 2

Using the Chipmunk physics engine in Star Fighter X2 was great as I got to learn something new and was able to flex some basic math muscles that I hadn’t had a chance to use in years.

I’d like to provide an overview of the basic structure and flow of how collisions and object relationships are setup and handled in Chipmunk.

In the beginning, there was

-(id) init;

  1. always remember to initialize the Chipmunk engine (cpInitChipmunk)
  2. initialize any required cpBody’s/cpShapes and associated Sprites
  3. setup the collision handler method (cpSpaceAddCollisionHandler)
  4. schedule the main [step:] loop

2) Bodies and Shapes and Sprites, Oh My!

There’s not much to say about point (1), just do it. ;) Moving on…

Some of the required bodies for SFX2 were two spaceships, randomly generated numbers of three different sizes of asteroids, and static shapes that defined the boundaries of the playable areas.

One important thing to consider is what bodies will be colliding and what bodies will simply ignore interaction. There is a collision_type property in cpShape that allows you to identify the category or type of body it is. You can eventually use that property to define the collision behaviour.

A cpShape also allows you set a void *data object that you can use to carry important data for later processing in callback methods. For example, with each asteroid or ship, I would set a new data object that would track the associated sprite(s), projectile type, and asteroid rock type.

3) Collision Handler

Chipmunk’s collision support is handled via the method:

[objc]
void cpSpaceAddCollisionHandler(
cpSpace *space,
cpCollisionType a, cpCollisionType b,
cpCollisionBeginFunc begin,
cpCollisionPreSolveFunc preSolve,
cpCollisionPostSolveFunc postSolve,
cpCollisionSeparateFunc separate,
void *data
);
[/objc]

The fourth parameter is the callback function that you would use to handle the collisions as they happen.

Here is an example of a ‘begin’ callback:

[objc]
static int begin(cpArbiter *arb, cpSpace *mainSpace,
void *ignore) {

// use this macro to declare two shapes and call
// cpArbiterGetShapes which uses the cpArbiter
// which contains info on the collision such as
// the shapes involved, contacts, normals, etc.
CP_ARBITER_GET_SHAPES(arb, a, b);

// use the data property of the cpShape to pull
// out your custom data object
SpaceData * shapeDataA = a->data;
SpaceData * shapeDataB = b->data;

if ( /* a should collide with b */ ) {
return TRUE;

} else if ( /* a should avoid b */ ) {
return FALSE;
}
}
[/objc]

Collisions would be checked via this callback at every step iteration.

One important thing to consider is how to manage your bodies during collisions. Say, for instance, you would have an asteroid and ship collide. After enough collisions, the asteroid might explode and go away. You might be tempted to try to remove the body and shape at this point, right from the begin callback. By design, changes to space aren’t able to be done safely in mid-step.

You would accomplish the removal of the element(s) by using a post-step callback.

Therefore, if ‘a’ should collide with ‘b’, and ‘b’ should go away, then you would call the following:

[objc]
cpSpaceAddPostStepCallback(space,
(cpPostStepFunc)postStepRemove,
b, NULL);
[/objc]

Your postStepRemove would then look something like this:

[objc]
static void postStepRemove(cpSpace * mainSpace, cpShape *shape,
void *unused) {

cpSpaceRemoveBody(mainSpace, shape->body);
cpSpaceRemoveShape(mainSpace, shape);

// remove the associated sprite from the main
// layer, won’t cover that here
cpBodyFree(shape->body);
cpShapeFree(shape);
}
[/objc]

This callback function would then be called after the step iteration finishes and it would then attempt to clean up the body, shape, and sprite for ‘b’.

4) Step Loop

As is typical for game loop processing, the step loop would iterate through all bodies involved in the system and allow you to respond to shifts in motion and behaviour as the bodies would interact.

General Concepts in Math & Physics

As is typical in physics simulations, you need to know your stuff about vectors and how to manipulate them. Think back to your high school physics and how to deal with normals, vector multiplication, cross products, addition and subtractions. That’s only a few of the operations you’ll likely need. Chipmunk does a lot of the dirty work for you, but you will still need to know how to apply the ops.

Check out cpVect.h and you’ll find a number of them already provided for you:

cpvadd, cpvsub, cpvmult, cpvdot, cpvcross… and many more.

Cocos2d also provides some convenience methods and macros that allow you to do some quick angle math.

CC_DEGREES_TO_RADIANS (also RADS to DEG)

ccpForAngle will convert an angle in rads to a unit vector of direction clockwise with respect to the x-axis

ccpToAngle takes a normalized vector and returns the angle between it and the x-axis

Check out the CGPointExtension header file to get a rundown of all the support available.

Thanks for reading! Hopefully this provides you with a bit of insight as to the general flow of managing your physics system in Chipmunk within the game loop.

If I’ve messed up a description or mis-interpreted how anything works, please let me know!


This post is part of iDevBlogADay, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Posted in Game Dev, iDevBlogADay, Star Fighter X2 | Tagged , , , , , | 1 Comment

The Chipmunk Physics Engine

While developing Star Fighter X2, I needed a way to handle a system of bodies that would interact with each other. This post will cover how I used the Chipmunk physics engine.

Background and Requirements

SFX2 used two main “actors” or “bodies” to represent the ships that players would control. I also had a number of other bodies and projectiles that would have to interact with my two ships, and themselves. For those of you who aren’t familiar with how to handle such interactions, you would normally make use of a Physics Engine.

Check out Wikipedia’s entry on what a physics engine is responsible for: http://en.wikipedia.org/wiki/Physics_engine.

Since I was using cocos2d, two popular 2D engines are available: Box2D and Chipmunk.

Box2D is open source (MIT), written in C++ and, from what I have read, is incredibly robust. It will provide all that you’ll ever need for 2D physics engine support.

Chipmunk is also open source (MIT), written in C (C99) and isn’t quite as feature-complete as Box2D. It is written by Scott Lembcke from Howling Moon software. I was fortunate to run into Scott and his colleague Andy at GDC 2010 and they are great, very intelligent guys.

How did I pick Chipmunk over Box2D?

Some points about Box2D:

  • written in C++ (sans STL)
  • reading through the documentation and APIs, I came to realize there would be quite the learning curve
  • large user base and community
  • memory management completely handled by the engine
  • frequently updated

Some points about Chipmunk:

  • written in C
  • docs and APIs seemed easy to understand
  • smaller user community than Box2D, but reading through both the cc2d-iphone and slembcke.net forums, there was lots of activity
  • handle all memory management yourself
  • frequently updated

I hadn’t done any physics programming before, so I needed to quickly ramp up on the concepts of how to represent the interactions. I tried both systems briefly, and I was able to get up and running quickly with Chipmunk.

None of the SFX2 code was written in C++, so I wanted to keep things straightforward and leave C++ objects out of it. I’m also a fan of having control of memory management.

There was still a decent learning curve, but I was able to find all that I needed from the Chipmunk docs and community forums. Chipmunk also shipped with a sample app that used relatively similar body interactions, so the decision was made to stick with it.

Integration

Getting started with cocos2d and Chipmunk is easy. Download the latest build from cocos2d.org, un-package, and run the install-templates.sh shell script. This will copy the supplied cocos2d project templates in place for new Xcode projects.

  1. From Xcode, go to File -> New Project
  2. From the New Project dialog, under the “User Templates” section on the left hand side, select the cocos2d item.
  3. The view on the right will switch to show the available templates. Double-click on the “cocos2d Chipmunk” template.
  4. Enter in the name of your new project and press enter.

The template will automatically setup the cocos2d headers and sources for you. Open your main AppDelegate source and you’ll see that it generated a bunch of basic cocos2d code for you to manage and initialize the Director and other necessary settings.

Important Concepts

Discussions on the concepts below are available in the official Chipmunk documentation, but I would like to relate them to how I used them.

Spaces

Spaces contain the physical bodies that you are modelling. You would initialize the primary space of your physics engine and add bodies to it. SFX2 had a single space that I would initialize at the beginning of a new game.

(see cpSpace in the Chipmunk API)

Bodies

A body, or rigid body, is an object that has physical properties such as mass, position, and velocity. Bodies do not represent a specific shape. SFX2 uses bodies for all objects during gameplay, from the two spaceships and asteroids to every power-up. I wanted to make sure that all objects had physical properties to allow collisions to be detected.

Bodies can also be static, meaning that they can be constructed to stay put. Assigning an infinite mass and moment of inertia to a body will make sure it obtains no velocity from collisions or effects from gravity. You could use these static bodies as boundary objects which could block other bodies from passing through.

SFX2 uses static bodies around the four sides of the main gameplay area and across the middle of the space to make sure players stay on their side.

(see cpBody in the Chipmunk API)

Shapes

Shapes are associated to bodies. They represent the boundaries used for collision detection. Chipmunk allows you to define different types of shapes: circle, polygon, line segment. You can assign multiple shapes to a body (or add more vertices to your polygon) to define a more complex shape.

An important thing to remember is that circle to circle collisions are more efficient to process. Poly to poly collisions get more expensive as the number of vertices increase. The simpler the shape, the faster collisions will be processed.

Another important thing to note is that a shape or body in Chipmunk really has nothing to do with a Sprite from cocos2d. The only thing you need to do is make sure your shape has similar dimensions to the sprite, and that the sprite has a similar position and rotation to the body. Sprites are only how you visualize your new physical bodies.

(see cpShape in the Chipmunk API)

Constraints and Joints

Constraints and joints define how bodies are connected to each other. You would apply a constraint that would contain a joint applied to specific bodies.

(see cpConstraint in the Chipmunk API)

Mmmmm… Code

After you created your new project in Xcode, there was likely a default CCLayer class created from the template (i.e. HelloWorldScene). View the layer source and you’ll see a whole bunch of good stuff. Let’s dive in with a quick overview.

[objc]
-(id) init {

….

// setup Chipmunk and prepare it to start
// processing collisions

cpInitChipmunk();

// create the main space

space = cpSpaceNew();
cpSpaceResizeStaticHash(space, 400.0f, 40);
cpSpaceResizeActiveHash(space, 100, 600);

space->gravity = ccp(0, 0);
space->elasticIterations = space->iterations;

// define a single static body
cpBody *staticBody = cpBodyNew(INFINITY, INFINITY);

cpShape *shape;

// static shape for a bottom boundary,
// use these as needed
shape = cpSegmentShapeNew(staticBody, ccp(0,0),
ccp(wins.width,0), 0.0f);
shape->e = 1.0f; shape->u = 1.0f;
cpSpaceAddStaticShape(space, shape);

….

// next define the sprites that would be
// associated to the shapes in the system
CCSpriteSheet *sheet = [CCSpriteSheet spriteSheetWithFile:
@"grossini_dance_atlas.png"
capacity:100];
[self addChild:sheet z:0 tag:kTagAtlasSpriteSheet];

// add a single body to the system at (x,y)=(200,200)
[self addNewSpriteX: 200 y:200];

// schedule the step method to start firing as
// fast as it can (no interval)
// check out the step definition below
[self schedule: @selector(step:)];

….

}
[/objc]

Use a helper method like this one to define the bodies required in your system.

[objc]

-(void) addNewSpriteX: (float)x y:(float)y {

int posx, posy;

CCSpriteSheet *sheet = // reference the sprite sheet

posx = (CCRANDOM_0_1() * 200);
posy = (CCRANDOM_0_1() * 200);

posx = (posx % 4) * 85;
posy = (posy % 3) * 121;

// create a new sprite from the sheet
CCSprite *sprite = [CCSprite spriteWithSpriteSheet:sheet
rect:CGRectMake(posx, posy,
85, 121)];
[sheet addChild: sprite];

sprite.position = ccp(x,y);

// IMPORTANT: define a set of vertices to be
// used for the new shape
int num = 4;
CGPoint verts[] = {
ccp(-24,-54),
ccp(-24, 54),
ccp( 24, 54),
ccp( 24,-54),
};

// Create a new body
cpBody *body = cpBodyNew(1.0f, cpMomentForPoly(1.0f, num,
verts, CGPointZero));

// setup the position of the body
body->p = ccp(x, y);

// add the body to the active set in the system
cpSpaceAddBody(space, body);

// define the shape using the set of vertices
// associate to the body and add to space
cpShape* shape = cpPolyShapeNew(body, num,
verts, CGPointZero);
shape->e = 0.5f; shape->u = 0.5f;
shape->data = sprite;
cpSpaceAddShape(space, shape);

}

[/objc]

Chipmunk uses iteration to solve the interactions between bodies. Each iteration is a step in time (think dt) and all constraints are analyzed to ensure smooth and accurate behaviour of elements in the system. The method below, step, allows you to track, control, and respond to action in the system.

step will be invoked as quickly as the timer can fire.

[objc]

-(void) step: (ccTime) delta {

int steps = 2;
CGFloat dt = delta/(CGFloat)steps;

for(int i=0; i>steps; i++){
cpSpaceStep(space, dt);
}

// iterate over the set of shapes in the system
cpSpaceHashEach(space->activeShapes, &eachShape, nil);
cpSpaceHashEach(space->staticShapes, &eachShape, nil);

}

[/objc]

The following method is invoked on each object in the system. You would use this to update the location and rotation of the sprite relative to the body.

[objc]
static void eachShape(void *ptr, void* unused) {

cpShape *shape = (cpShape*) ptr;
CCSprite *sprite = shape->data;
if( sprite ) {
cpBody *body = shape->body;

[sprite setPosition: body->p];

[sprite setRotation: (float)
CC_RADIANS_TO_DEGREES( -body->a )];
}

}
[/objc]

This far and we’re really only scratching the surface of Chipmunk. In a future post, I’ll delve into the aspects used the most in Star Fighter.

Depending on your experience with physics engines this might be a fair bit to absorb. I encourage you to spend some time with the sample code available for Chipmunk, check out the docs, and read through some of the forum posts on the Chipmunk forums.

This post is part of iDevBlogADay, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Posted in Blog, Game Dev, iDevBlogADay, Star Fighter X2 | Tagged , , , , | 1 Comment

What Apps Do You Use?

For this Friday #iDevBlogADay post I thought it would be fun to list some of the apps/games that I use/play frequently these days on my iDevices.

Below are the ones that I’m either playing or using now, or within the last few weeks. A number of others are not listed.

I find it interesting in that when I look back over the past year, I really don’t have too many games that would keep me coming back after four or five months of being on the device. That timeframe would even be generous for some. Therein lies the apparent general nature of these “consumable” games. That would make for an interesting, separate, blog post.

Let me know your favourites by leaving a comment! I know I’m missing some good ones.

iPad Utilities / Services

iBooks included in iOS 4.0
Twitter Twitter - Twitter, Inc.
Instapaper Instapaper - Marco Arment
Netflix Netflix - Netflix, Inc.
Articles Articles for iPad - Sophiestication Software
iSSH iSSH - SSH / VNC Console - Zinger-Soft

iPad Games

Smule’s Magic Piano Magic Piano - Smule  So fun to play. Great for kids.
Chopper 2 Chopper 2 - Majic Jungle Software  Gotta have this game. Perfect on the iPad.
Words HD Words With Friends HD - Newtoy Inc.  Good way to kill time and exercise those brain muscles.
Cut the Rope Cut the Rope HD - Chillingo Ltd  Cute and lots of fun.
Beyond Ynth HD Beyond Ynth HD - FDG Entertainment  Incredible.
Tunnel Shoot Tunnel Shoot Pro - Backflip Studios  A game that MUST be played on the iPad.
The Incident The Incident - Big Bucket Software  8bit goodness.
Minigore HD Minigore HD - Chillingo Ltd
Harbor Master Harbor Master HD - Imangi Studios, LLC
Air Hockey Air Hockey - Acceleroto
Trundle HD Trundle HD - mobile bros., LLC  Neat game. Did a great job on the atmosphere and gameplay mechanics.
Dizzypad HD Dizzypad HD - NimbleBit  One of the first games I bought. Usually show this game when demoing the iPad to people wondering what it’s all about.
Galcon Fusion Galcon Fusion - galcon.com
Asphalt 5 Asphalt 5 HD - Gameloft
Spider HD Spider:  Bryce Manor HD - Tiger Style
Highborn HD Highborn HD - Jet Set Games
Alice Alice for the iPad - Atomic Antelope  Incredibly well done interactive story book.
Star Fighter X2 Star Fighter X2 - Manic Networks Inc.  Best game EVAR! ;)

iPhone Utilities/Services

Twitter Twitter - Twitter, Inc.
JotNot Pro JotNot Scanner Pro - MobiTech 3000 LLC  Great for scanning in paper bills (that you tend to lose).
Yellowpages Canadian YellowPages.ca Business and People Finder - Yellow Pages Group Co.
Heritage Fotopedia Heritage - Fotonauts Inc.  Really neat app showing the heritage sites around the world.
Fonts Fonts - AppEngines  Useful reference app.
Netflix Netflix - Netflix, Inc.
JAZZ.FM91 JAZZ.FM91 - JAZZ.FM91 INC.  For when I’m in the mood for some Jazz.

iPhone Games

Angry Birds Angry Birds - Clickgamer.com
Tilt to Live Tilt to Live - One Man Left  Loads of fun. Can get very challenging.
Ragdoll 2 Ragdoll Blaster 2 Lite - Backflip Studios  The graphics here are fantastic.
Minigore Minigore - Chillingo Ltd  Get yer fix of bullets.
Tunnel Shoot Tunnel Shoot Pro - Backflip Studios  This is what I remember the arcade to be like.
Fruit ninja Fruit Ninja - Halfbrick Studios
Carcassonne Carcassonne - TheCodingMonkeys
Castle Warriors Castle Warriors - GameResort LLC
Helsing’s Fire Helsing's Fire - Clickgamer.com
Words With Friends Words With Friends - Newtoy Inc.  Play this against my wife on the iPad version.
Mega Worm Super Mega Worm - Deceased Pixel LLC
Trainyard Trainyard - Matt Rix  Awesome UI and great original gameplay concept.
NinJump NinJump - Backflip Studios
Canabalt Canabalt - Semi Secret Software
Eyegore’s Eye Blast Eyegore's Eye Blast Lite - Clickgamer.com
QuickHook Super QuickHook - Rocketcat Games
GravBot GravBot - Team Phobic
Sword of Fargoal Sword of Fargoal - Fargoal, LLC  Retro dungeon crawler. Gotta be the best one out there.
GD Swarm geoDefense Swarm - Critical Thought Games LLC  Great tower defense.
HarborMaster Harbor Master - Imangi Studios, LLC
Big Bad Flower BIG BAD Flower - BIG BAD BRUSH inc.
StarDunk StarDunk - Godzilab
Linkoidz Linkoidz - Retro Dreamer  Fast paced, challenging and super fun.
Pocket God Pocket God - Bolt Creative
Sneezies Sneezies - Chillingo Ltd  Really fun and the graphics are super cute.
Space Miner Space Miner: Space Ore Bust - Venan Entertainment, Inc.
Silverfish Silverfish - Chaotic Box  Totally addicted to this one.
Hungry Helga Hungry Helga - Grid Monsters  Hilarious game play concept.
Tickle Tap Toddler Pack Tickle Tap Toddler Pack - Preschool Learning Games - zinc Roe  Great set of games tailored for the younger gen.
Toki Tori Toki Tori - Chillingo Ltd

This post is part of iDevBlogADay, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Posted in Blog, Game Dev, Gaming, iDevBlogADay | 1 Comment

Thoughts on the Mac App Store

Apple’s announcement on October 20th about the forthcoming release of their Mac App Store (MAS) did a great job to help shake up the desktop app development and sales market segments.

With the MAS, Apple is able to close the loop on providing the end-user a sleek, painless, and fully integrated hardware and software solution.

I don’t think there has ever been a better time for consumers and developers. It’s wonderful to see that the push with today’s tech is all about ease of use, integration, and efficiency. Think for a second as to how it used to be (still is) for Windows and Macs.

The Early Days

Back between 1995-98 when the web was first becoming really popular (at least for me), we saw the introduction of Tucows, C|Net, and various other sites where people could browse amongst the list of free and paid software available. The user still had to completely manage sourcing out, downloading the binary, running the installer, deal with installation issues, and last but not least, make sure that no other shareware came along with it.

These services still exist today, but they have become extremely poor with annoying ads, bundling deals with download sites, and the annoyances go on. I’m sick of all that BS.

For the Mac platform, alternatives would be apps listed on the Apple.com store, or free services like Bodega. Unfortunately, you still have to deal with downloading, installing, and managing the apps in a relatively “loose” fashion. However, Bodega HAS done a good job with simplifying this a little. I certainly know what I’m doing in order to manage this myself, but my wife’s grandmother or even my parents couldn’t be bothered.

However, observing my parents use my iPad, they see the app store and they understand that they can tap to view details, tap again to install, and boom, done. They exit the app store and they can start using the software. It’s even easier to uninstall. That’s the ease-of-use that needs to, and will, come to the Mac desktop platform.

Challenges From Web Apps and Existing Channels

Browsers and scripting technologies have improved leaps and bounds over the past few years. Web applications are becoming more and more useful and relevant, especially since cloud services can be much cheaper (if not free) and easier to use. Web apps aren’t suitable for everything, yet. However, we’re certainly going to see more and more apps that were typically desktop-centric have some, if not all, components moved to the cloud. The MAS isn’t going to help the user there.

This will likely be purely a personal consumer / small-business service. Businesses still like to be coddled with account specialists and one-to-one support. I don’t see how the MAS will reach that part of the market. Remains to be seen on how this will influence pricing.

Enticing for Smaller Developers

The mobile space absolutely exploded due to how it eased the barriers of market entry and sales for smaller developers. Everyone developing iOS apps starts out on a relatively level playing field. It should be the same case for the MAS and I believe that those apps not entirely falling under a “mobile” use-case can have a great chance at success on the MAS.

Although, from the iOS “community” that I am involved in, I haven’t noticed too many people talking about converting their apps for the MAS. I’ve noticed perhaps a handful. Maybe others are simply waiting to see how it works out before investing that much more time and energy in porting their app.

Gaming

One aspect I’m really excited about is how the indie game dev community will respond. I don’t use my Mac to game at all. Not a single game installed. I think that takes major discipline since Steam rolled out the Mac port of their service this year (or was it last year?).

I’m curious to see how much focus the MAS will place on games and other entertainment. If it’s as seamless as the mobile App Store and the quality games carry over, I think I’ll have to start stressing out my iMac’s graphics card with something other than Photoshop.

Sustained Growth

Ultimately, this will help attract new customers and retain existing users. For those who are on the fence of switching over to the Mac: “If there are some killer apps available for this new MacBook Pro, damn, that makes the thought of investing $2000 on a laptop even easier! SOLD!” ;)

Thanks for reading.

This post is part of iDevBlogADay, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Posted in Blog, Business, iDevBlogADay | 1 Comment

Simple Secure Storage in iOS

For this week’s post I would like to switch gears to discuss how you, an iOS software developer, should consider HOW you are persisting sensitive user data that is manipulated by your app.

When you need to persist data to storage the first thing you might think about is simply marshalling that NSDictionary to an XML or binary file. However, what if you have some user passwords or other sensitive data to handle? You probably want to do more for your users than just leave it there on the device in plaintext (even IF only your app can access it).

Sure, there are many ways people can gain access to the data via the app itself, but you, a “software engineer”, should consider yourself ethically bound to ensure that you do your best to provide a robust and secure product.

A while back I was looking for an easy mechanism to securely store some data. I wasn’t interested in dealing with managing ciphers and keys and all that jazz (been there, done that, and I had other projects to complete!) so the next best thing is the available support for interacting with the iOS Keychain. Each app has it’s own dedicated segment or protected area of the Keychain.

I wrote up a simple class that provides an interface to automatically add/update/remove any data from the app’s Keychain. I would like to show it to you!

Headers for reference:

KeyChain.h

[objc]
#import <Foundation/Foundation.h>

@interface KeyChain : NSObject {

NSMutableDictionary * data;

}

@property (nonatomic, retain) NSMutableDictionary * data;

// determine if a Keychain item exists, as
// mapped via the provided key
-(BOOL) keyExists:(NSString *) key;

-(void) addToKeyChain:(NSString *) chainKey
withData:(NSMutableDictionary *) chainValue;

-(void) addValueToKeyChainItem:(NSString *) chainKey
itemValueKey:(NSString *) valueKey
itemValueData:(NSDictionary *) valueData;

-(void) removeKeyChainItem:(NSString *) chainKey
itemKey:(NSString *) valueKey;

-(void) removeKeyChainItem:(NSString *) chainKey;

-(NSDictionary *) getElement:(NSString *) key;

@end
[/objc]

SecurityService.h

[objc]
#import <Foundation/Foundation.h>

@class KeyChain;

@interface SecurityService : NSObject {

KeyChain * keychain;
NSMutableDictionary * genericQuery;

}

@property (nonatomic, retain) KeyChain * keychain;
@property (nonatomic, retain) NSMutableDictionary * genericQuery;

+(SecurityService *) getInstance;

// create and persist a NEW Keychain item to the device’s Keychain
-(void) addNewKeyToChain:(NSString *) entryName
label: (NSString *) label
description: (NSString *) desc
service: (NSString *) service
comment: (NSString *) comment
withData: (NSDictionary *) accountData;

// add or update a dictionary of data mapped by the valueKey
-(void) addNewValueDataToKey:(NSString *) keychainKey
withNewValueKey: (NSString *) valueKey
withNewValueData: (NSDictionary *) valueData;

// remove a specific key/value pair from the Keychain item
-(void) removeValueDataFromKey:(NSString *) keychainKey
valueKey:(NSString *) valueKey;

// return an NSDictionary for the specified Keychain item
-(NSDictionary *) getKeyChainItemData:(NSString *) keychainKey;

// remove the Keychain item from the Keychain
-(void) removeKeychainItem:(NSString *) settingsKey;

@end

[/objc]

The goal here is to provide a quick way to store and retrieve any string data to and from secure storage.

KeyChain encapsulates the data for specific Keychain items (with their mapped values) stored in the Keychain. You don’t need to interact with this object as everything is provided by the SecurityService, although I have exposed this property in the SecurityService.

The SecurityService is the main manager that controls the addition/update/removal of your Keychain data. Each Keychain item is identified by a unique key which maps to the data structure (NSDictionary) which gets encrypted. You can add as many Keychain items as you want. This implementation is useful so long as you are willing to handle formatting your data (or object members) into key/value pairs.

Note, I wrote the SecurityService to be a singleton and it works fine for my needs. There seems to be much debate as to how to properly write a singleton so feel free to modify as you see fit.

An example might be the best way to outline how this facility is to be used.

[objc]

/********************************************************
Store a new username and password to the keychain
********************************************************/

#import "KeyChain.h"
#import "SecurityService.h"

/// … blah blah… class / interface def… blah…

// keychainItemKey is used to help identify
// the specific Keychain item we’re using.
NSString * keychainItemKey = @"myAuthKeyItem";

// does our Keychain item exist yet?
if ( ! [[SecurityService getInstance].keychain
keyExists:keychainItemKey]) {

// setup the new ‘account’ details in the Keychain

// the method arguments are some of the standard
// data elements that Apple’s Keychain uses to help
// identify new "account details" that are stored in
// the Keychain
[[SecurityService getInstance]
addNewKeyToChain:keychainItemKey
label:@"MyAccountDetails"
description:@"Account Details"
service:@"My App"
comment:@""
withData:[NSDictionary dictionary]];
}

// update the account details in the keychain
NSDictionary * tmpData = [NSDictionary
dictionaryWithObjectsAndKeys:
@"new password", @"pwdKey",
@"my userid", @"uidKey", nil];

NSString * mainDataKey = @"accountDetails";

// The ‘withNewValueKey’ argument essentially
// allows you to provide multiple NSDictionary
// elements under a single Keychain element.
// A dictionary of dictionaries. how complicated!
// this method will automatically add and persist
// the data to the Keychain
[[SecurityService getInstance]
addNewValueDataToKey:keychainItemKey
withNewValueKey:mainDataKey
withNewValueData:tmpData];

// when i first wrote this i needed the convenience
// of specifying multiple "tiers" of dictionary data.
// you could easily rip this out and simplify it to a
// single dictionary that is stored under the Keychain
// item’s value key (see the .m)

// retrieve the data stored above.
NSDictionary * myAuthData = [[SecurityService getInstance]
getKeyChainItemData:keychainItemKey];
NSString * username = [[myAuthData objectForKey:mainDataKey]
objectForKey:@"uidKey"];
NSString * password = [[myAuthData objectForKey:mainDataKey]
objectForKey:@"pwdKey"];

[/objc]

While you are browsing through the SecurityService.m, I encourage you to take a look at Apple’s Keychain Services documentation to help provide the necessary background on what I am using. Some of the code I use to access and manipulate the Keychain was provided by Apple. Keychain Services

NOTE: to use the Keychain security APIs you will need to add the Security framework to your list of project Frameworks (Security.framework).

You are welcome to rewrite any of this code to your needs and clean up any bugs that you find along the way. Please respect the MIT License. Do let me know how this helped you, or if you can think of a way this can be improved (there are many!) ;)

Here’s the poorly commented code!! Enjoy. KeychainSecurity.zip

Posted in iDevBlogADay | 11 Comments

Push Notifications with the Manic Messenger

Hey everyone,

Aside from Star Fighter X2, over the past few months we have been very busy working on our core product. Recently rebranded, the Manic Messenger is a robust and highly performant Push Notification server. Version 5.0 has just been released!

In today’s post I would like to briefly cover the concept of Push Notifications and what we have been working on over the past months.

What Are Push Notifications?

First think about how, on your desktop computer, you find out you have new email or new Twitter updates.

You have an email client sitting open on your iMac. You typically have it configured to check for new mail every five minutes. The email client will trigger a new request to automatically log into your mail host and see if any new messages are available.

This is an OK method for a powerful desktop computer, but when you are on a mobile device with limited bandwidth and battery life, you don’t want to have a piece of software making N number of requests per hour with the majority of checks not returning any data.

It would be much better if the device could be notified that it has new data only when new data is available.

Enter Apple with iPhone OS 3.0. With the 3.0 release they announced the availability of their Push Notification Service (APNs). APNs allows for any iOS device to register with their remote server and allow short messages to be “pushed” to the device. The Android platform has recently introduced (with version 2.2) their Cloud to Device Messaging Framework (C2DM), and Blackberry has released their Push Notification support. Windows Phone 7 will also be releasing a similar service. All platform implementations follow a similar model of registering a device with an “official” remote service to receive notifications.

Back to the example above, instead of the mail client on the iPhone periodically checking for new messages, your mail host could send your device a new push notification when it recognizes that you have a message to download. Once notified, your mail app can then send a request to download the data. One thing to note is that push notifications are small messages that are meant to trigger a broader action to occur on the device, as determined by the app receiving the notification.

One nice thing about push notifications is that the app does NOT need to be running in order to receive the message. This was one of the main ways Apple got around the iPhone OS’s lack of multi-tasking support.

There is, however, a missing piece wherein Apple (et al) will only manage the relaying of “messages” from a trusted source (a remote web service) to one or more registered devices. App developers still need to create their own server software (acting as a “3rd party”) that manages the business logic of what, when, and how a message should be sent from a source to a destination iOS device.

3rd Party Solutions

Quickly, cloud based services ramped up for developers to use. Some services require a monthly fee which would only give you so many free messages per month, others are entirely free while you stay below a message count threshold. This can get very expensive if you have one or more very popular apps! A couple hundred thousand users generating a couple of messages per day adds up.

Considering the cloud service model, we realized that some developers might rather have a cheaper solution that provides full control over their service. Or, perhaps for security reasons data must be managed solely within trusted networks. We built the Manic Messenger to be a stand-alone Push Notification server software that you would install and run on your own Linux (or Mac OSX) system.

Cheaper?

Our tiered pricing model only involves a single payment to purchase the server software and includes a years worth of support. You then have the freedom you need to run it wherever you desire. You can set up a small Linux instance with Amazon’s EC2**, Rackspace, or you can even run it on a spare Linux system on your desk, and expose a port on your own high-speed connection.

** now is a great time to check out Amazon’s EC2 as as they have a HUGE deal for the first year of a new subscription!

For this one-time fee you have the ability to use the single server for multiple apps and send an unlimited number of messages!

Of course, there’s the cost of the time and effort to run and maintain the server, and whatever you have to pay for bandwidth. However, if you are fairly savvy with a unix command line or are willing to learn some basics you can really save money in the long run. Bandwidth is getting cheaper and cheaper as time goes on, and push notifications are, by design, very lightweight.

What Do I Need Push For?

There are many uses for push notifications!

From a gaming perspective, if you are playing a turn-based multiplayer game you can use push notifications to inform players that it is their turn, even when they are NOT playing the game!

Or if you have a scheduling or task-oriented application you can use push notifications to update the user when they need to be leaving for an appointment, or that it’s their brother’s birthday.

Or you can simply use push notifications to update your users that a new feature or service is now available. Needless to say, the possibilities are endless.

What are Manic Messenger’s Features?

  • Cross platform: The server now supports APNs, Android’s C2DM, and Blackberry’s Push Notifications.
  • Multiple Protocols: You can communicate directly with the server using either HTTP(S) requests or XML over TCP/IP. We can also provide you with an Objective-C library to easily handle communication from your iOS app to the server.
  • Scheduled and Recurring Notifications: You can configure notifications to be sent at a specific time and date AND have them repeat.
  • Performance: Written in C/C++ the server is incredibly efficient with load testing and benchmarking indicating a single server can handle hundreds of millions of messages per day. Multiple servers can be deployed for massive messaging installations.
  • Easy Installation: As described below, you can be up and running in minutes.

How Do I Get Started?

We provide a 20 day free trial which gives you full server functionality for handling push notifications for four of your apps. Once you register, download the installer binary, create a trial license key and you can get started!

Don’t forget to download the Installation and Reference guide, available under the Documentation tab.

Server Installation

Copy the file onto your server, ftp or scp will do the trick. With an ssh session to your linux system, start the setup process:

Make the file executable by running the following command: chmod 755 install_messenger_5.0.bin

To run the installer, type in: ./install_messenger_5.0.bin

Note: make sure you have the necessary user permissions to install in the directory you want to use for installation.

During the installation process, the permitted options are shown in square brackets at the end of the line. If only a single option is provided in the bracket, this is a “default” entry, and you can press enter to use it. Otherwise, you need to type in one of the available options that are separated by a “/” and press enter.

Type in ‘Y’ to proceed with the installation and go through the provided license agreement. Press the space bar to proceed by a page.

You’ll be asked for the following info:

  1. path to the base install dir
  2. whether you would like to automatically generate the config files by automatically running “configure”
  3. your company name (should match what you registered with)
  4. IP address the server should run on, default of 0.0.0.0 will bind on all addresses
  5. port to use, the default should be fine (make sure the firewall on your connection has port forwarding setup for this)
  6. whether you would like to auto-configure an init script for your system. This allows the services to start automatically upon server reboots. Accept this and use the default init script directory by pressing “enter” when asked.

Once completed you will see the path to the init scripts. You can use these to manually start, stop, and restart the two available daemons.

Two processes will be started: messenger, and scheduler. messenger is the main process that receives and dispatches new messages to the remote Push Notification services. scheduler is used to coordinate the sending of all scheduled notifications.

If the servers do not startup properly, you can take a look to see if there are any entries found in the logs under the logs/ directory.

Configuring your iOS Apps

This is a very quick outline of what must be done to setup your app for push notifications. I’ll go more in depth into this process in a future entry.

  1. From the Apple iOS Provisioning Portal, you need to configure your app to have Push Notifications enabled. Under each App ID you can enable Development and Production push services. When you click on the “configure” link for each App ID listed, you can generate and download the Development and Production Push SSL Certificates.
  2. When you download the certificates, you should already have the private keys for both in your Keychain Access. Open Keychain Access and drag and drop the two public certificates onto the private key entries. Now you need to export the public/private key pairs. Select both public/private keys, right click and select the “Export 2 Items” as a .p12 file.
  3. Next you need to convert the .p12 to a PEM format. Here’s a sample openssl command:

    openssl pkcs12 -in devKeyCert.p12 -out devKey.pem -nodes

    Repeat this for both the development and production .p12 files.

  4. Editing the devKey.pem files, you should edit them down so you only see the start and end headers of the key and certificate content. For example:

    —–BEGIN CERTIFICATE—–
    MIIFeDCCBGCgAwIBAgIIEN7bQ1fvRFEwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV
    BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
    —–END CERTIFICATE—–
    —–BEGIN RSA PRIVATE KEY—–
    MIIEowIBAAKCAQEAyRH4yrHzSBbzAHCZSfqjuNPXBvCzUU2WGDj0SLLybzFCtCPm
    TjlBLxTeIa4TK5kBOGHqmxl2ccqtuPrxon7yLTry+dC6ytIBdr0U78vNdqrmmL3r
    —–END RSA PRIVATE KEY—–

  5. Once edited to the format above, upload the dev and production .PEM files into the messenger/appinfo/ directory.
  6. The appinfo/ directory, by default, is used to contain all of files for each of the apps the server will send push notifications to. Each app must have it’s own APPNAME.app file.
  7. Using the sample apple.app file, rename it to YOUR_APP_NAME.app, edit it and change the lines for ProductionCert= and SandboxCert= to point to the new .PEM files that you just uploaded.

Now the server is setup to start processing requests! Next up is working with our protocols to communicate with the server.

There are numerous other settings and features that you can configure with the server. This was only a quick run-through with the bare minimum that you would need to get going. Please review the provided Setup and Reference PDF to review the additional features available.

In my next post I’ll go through how to create a simple solution that will connect to the Manic Messenger and be able to submit a new Push Notification.

In the meantime, I encourage you to sign up for the free trial and try out the server for yourself. If you have any questions or concerns, we’d be happy to hear from you!

Thanks for reading!

This post is part of iDevBlogADay, a group of indie iOS development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, Twitter or delicious.

Posted in Blog, Business, iDevBlogADay, Manic Messenger, Push Notifications | 4 Comments

Get Out There!

For my first post in the #iDevBlogADay series, I would like to discuss the importance of networking for indie developers.

I’m not referring to the Cat5 variety of networking, rather the “Hey, you’re in business for yourself now, so get your butt out of your home office and go talk with people” style of networking.

Why and What’s It All About?

If you are reading this, you are likely in the business of making mobile apps. Be it games, utilities, productivity, whatever. You are also passionate about what you do. If you aren’t passionate, how are you ever going to meet those goals?

However, even if you consider this to be your “hobby” or a part time gig, you need to think about it as a business. One of the objectives of a business is to grow and prosper. Obviously, there are many ways to do this, but I’ll only discuss one today.

One of the easiest ways to help grow your new venture is to build up a base of contacts. Also known as a “network of contacts”, which is obtained by interacting (networking) with fellow developers, designers, and even your customers.

How in the world is this done? You can accomplish this in many ways! The key is to simply become more involved. A good start would be attending your weekly local NSCoder Night or the monthly Cocoahead meetups. Be sure to also attend at least some of the many available iOS/mobile conferences. Here’s a good conference list.

Now that you have an idea of where to go, while you are out, make sure you bring along business cards. Don’t put off getting these made! Find out how to keep in touch with the people you encounter, be it a phone number, email, Facebook, or Twitter. By the way, you need to get a Twitter account and join the conversation.

The bottom line is that a set of contacts has one awesome side effect: new opportunities usually present themselves fairly quickly. Opportunities that can open many a door!

Not really my thing. I write code.

“I’m not really a small-talk kinda guy, so how could I possibly get out there and strike up a meaningful conversation with someone?”

If this sounds like you, don’t sweat it! The one thing I’ve learned over the years is that like-minded people always have lots to talk about. Let your passion take over here! The great thing about it is that the more you discuss your projects or passions with others, the easier it gets. Put a smile on your face, greet with a firm handshake, and just go for it.

The community of indie developers is a really special, inclusive group. Get over the hump of attending that first Cocoaheads meetup and you’ll understand that it’s akin to a big family.

A note to developers who are lucky enough to be working in small teams: you need to get EVERY member on board with this. There’s no excuse to not have everyone on board building relationships. Remember the old saying that when you are a small startup, everyone is in sales.

Benefits

It’s really difficult to put a price on the relationships you establish as the benefits can be enormous.

App Design & Development

Throughout the development process of your latest app, ask some of your acquaintances for feedback on your latest design, idea, or even what kind of frameworks would work best to solve a problem you are having. Maybe someone knows a guy who has a graphic designer genius as a friend and you can get a new UI that truly doesn’t suck. This is how the extra effort in building relationships all becomes worthwhile.

Remember that you are amongst developers, designers, and business people who have likely crossed similar hurdles, or may have more expertise, or may have a different approach to something, and can really help save you time and money.

Collaboration

Networking may also provide the ability to collaborate with other developers, designers, and other business professionals. Someone you meet might be interested in working on an idea like yours, or may not have the resources available to complete a new idea he or she has.

Frequently you find graphic designers with a great idea, but they don’t have the time to learn the necessary coding skills to execute. Vice versa, a developer may not have the artistic ability to produce a proper UI for his or her app.

You need to do your part to create opportunities to talk with such enterprising people; otherwise, you might just be missing out.

App Releases

Just as you’re rounding the bend on the massive amount of work to get your app submitted to the App Store, you realize how much work is left to do to get your app noticed. Contacts to the rescue!

Determine a set of email addresses from contacts who wouldn’t mind receiving updates on your product or service. Tweet about your new product by giving teasers! Upload some videos of your new game or app to Youtube. Create a Facebook page for your users to reach you. Word of mouth is still one of the best mechanisms to drive sales. Communicating your app’s release to as many people as possible is critical.

Self Promotion

The last point I want to make is that you are not just trying to sell apps, but you are also selling yourself along with your business identity.

Here’s the happy/gushy part of the message: be a nice person. You may know the in’s and out’s of XYZ library or software suite, along with being a network coding guru, but that’s no reason to be a jerk when talking with people. Life is too damn short. Be professional, open, honest, and courteous. It begets useful dialog and will take you much farther in your career.

Aim to be a superstar rather than a jackass, and when it comes time to call upon them, your friends will be there for you.

Just Do It

Share your passion, get out into your community, be a good person, and work tirelessly to establish new relationships. As discussed, these are some of the main ingredients for success in today’s new and exciting world of mobile development.

See you next week!

Posted in Blog, Business, Game Dev, iDevBlogADay | 2 Comments

Reviews for Star Fighter X2

Check out some of the recent articles and reviews for Star Fighter X2:

148Apps Star Fighter X2 for iPad Review

REVIEW: Star Fighter X2 (iPad) | AppVader

TUAW’s Daily App: Star Fighter X2

360 iDev – From Game Jam to App Store

Posted in Game Dev, Gaming, Star Fighter X2 | 1 Comment