TweetFollow Us on Twitter

Game Development for iPad, iPhone and iPod Touch Using the cocos2d and Chipmunk Frameworks

Volume Number: 26
Issue Number: 03
Column Tag: Game Development for iPad, iPhone and iPod Touch

Game Development for iPad, iPhone and iPod Touch Using the cocos2d and Chipmunk Frameworks

Tools for building 2D games

by Rich Warren

Let's Get These Engines Running!

Last time, we looked at the cocos2d for iPhone graphics framework, and the Chipmunk Physics Engine. If you followed the instructions from Part 1, you have already installed both libraries and played around with the examples. If not, please check out Part 1, because we're going to hit the ground running.

In this article, we will build a simple pachinko game. When the user taps the screen, a ball will fall from the top, and bounce off a number of pins. If it goes into the target, a bell will ring. Otherwise, the ball simply exits off the bottom of the screen. We will try to keep this simple, and focused on the graphics and physics engines. There's no score. No ability to affect the ball once it is launched, and only very simple sound effects. Still, by the time we're done you should have a good handle on how to use cocos2d and Chipmunk in your own projects. So, without further introduction, let's jump right into the code.

Building a New 2D Game App

Launch Xcode, and create a new cocos2D Chipmunk application: File--> New Project...--> iPhone OS--> Application--> cocos2d-0.8.2 Chipmunk Application. Name the project Pachinko, and click the Save button. As I mentioned in Part 1, the current release of cocos2d defaults to the iPhone 2.2 SDK. Unfortunately, this version is not included in recent versions of Xcode. The simplest solution is to change the Active SDK in the Overview drop-down menu, and select an existing SDK. Usually, I select the most recent simulator release (as of writing, 3.1.3).

Create a New Cocos2D Chipmunk Application

Next, any game needs graphics and sound effects. Open up the Resources group. As you can see, the template already has four PNG files. Default.png is the splash screen that's displayed while the application launches. Icon.png is the application icon that appears on the iPhone's home screen. For simplicity's sake, we will leave these alone; however, you will want to replace them in your own projects. The fps_images.png image is used to display the frame rate while testing the application. We can use that feature as a quick and dirty performance test, so leave that image alone. However, the grossini_dance_atlas.png image is only used by the template's sample application. You can safely delete that file.

Creating artwork and sound effects is beyond the scope of this article. Instead, you should download the article's source code from Now copy the following files to the resource folder: bell.wav, tick1.wav, tick2.wav, right_bumper.png, left_bumper.png, back-ground.png, ball.png, pin.png and target.png. To add these files, right-click on the Resource group, then click Add Existing Files.... Select the desired files, and then click the Add button.

Wrapping Up our Entities

Our pachinko game will have a number of balls that can interact with other things on the screen: other balls, pins, bumpers and the target. As described in Part 1, a single game entity is a combination of graphical elements and physical attributes. These entities are represented by a number of cocos2d objects and Chipmunk structures. All of these need to be created, initialized and (when the time is right) destroyed properly. That's a lot of code just to get something on the screen. Fortunately, most of this code is identical from entity to entity. We'll take advantage of this by wrapping all the objects and structures in our own class, Entity. This class will encapsulate all the common creation and destruction code, properly handling the memory management for the underlying objects and structures.

A classic Object Oriented approach would involve encapsulating the common elements in a base class, and then create a number of subclasses to represent each of the different entity types. While that would work here, I've chosen a slightly different approach. We will use the Entity class for all our entities, and encapsulate the differences between the various types using a configuration source object. To do this, we first create the EntityConfigurationSource protocol. This protocol is similar to the DataSource protocols used throughout in the Cocoa Framework. If you've ever used a UITableViewDataSource to fill the contents of a table, you have the basic idea. There is one small, technical difference. Typically, to avoid reference loops, a Cocoa class does not retain its data source. However, following that convention would only add unnecessary complications to our code. Therefore, to avoid any confusion, we will call our protocol a ConfigSource, not a DataSource.


Let's build the EntityConfigSource. Right click on the Classes group and then select Add New Group. Create a new subgroup named Entities. Now, right click on the Entities group and select Add New File... iPhone OS Cocoa Touch Class Objective-C Protocol. Name this protocol EntityConfigSource.h, and click the Finish button. Now modify the file as shown below:


This protocol encapsulates the differences between different types of Entities.

#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "chipmunk.h"
#import "Utility.h"
@protocol EntityConfigSource <NSObject>
-(enum SpriteType) spriteType;
-(int) depth;
-(BOOL) isStatic;
-(cpBody*) createBody;
-(NSArray*) createShapesGivenBody:(cpBody*)body;
-(CGPoint) initialLocation;
-(CGFloat) initialSpriteRotationForLocation:(CGPoint)location;
-(CGFloat) updatedSpriteRotationForLocation:(CGPoint)location;

This protocol contains a mixture of required and optional methods. spriteType returns a value that can be used to look up the appropriate image file name. depth determines the image's z-depth (higher numbers are drawn overtop lower numbers). isStatic returns YES if the entity is static (non-moving), or NO if it is mobile. createBody creates the entity's cpBody structure, and createShapesGivenBody builds an array of shapes associated with that body. As described in Part 1, the body defines the entity's mass and moment of inertia, while the shapes define how the entity interacts with other entities (typically by defining its surface geometry and characteristics that determine the effects of collisions).

The optional methods can be used to set the object's initial location and its initial rotation. Finally, the updateSpriteRotationForLocation: method is used to set the sprite's rotation based on its current location. We will use this to create fake 3D lighting effects later on.

Note: this class imports the Utility.h file. This defines the enumerations and a number of short helper functions used throughout this project. For the sake of saving time and space, I will not spend much time on those functions here. Simply copy Utility.h and Utility.m from the article's source code.

Entity Class

OK, let's look at the Entity class. Create a new Objective-C class in the Entities subgroup (right click Entities and select Add New File... iPhone OS Cocoa Touch Class Objective-C Class), and name it Entity. Now open Entity.h and modify it as shown below:


#import <Foundation/Foundation.h>
#import "EntityConfigSource.h"
@interface Entity : NSObject {
    id <EntityConfigSource> configSource;
    // cocos2D Graphical Features
    Layer* layer;
    Sprite* sprite;
    // Chipmunk Physics Features
    cpSpace* space;
    cpBody* body;
    NSArray* shapes;
@property (readonly, nonatomic) CGPoint position;
@property (readonly, nonatomic) NSArray* shapes;
// Init
 withConfigSource:(id <EntityConfigSource>)theConfigSource;
// Update
-(void) updateSprite;
// Convenience methods for creating different Entities
+(id) pinInSpace:(cpSpace*)space 
+(id) leftBumperInSpace:(cpSpace*)space 
+(id) rightBumperInSpace:(cpSpace*)space 
+(id) targetInSpace:(cpSpace*)space 
+(id) ballInSpace:(cpSpace*)space 

We'll look at the methods in more detail below. For now, focus on the instance variables. Notice how the Entity's appearance is described using a Sprite placed within a Layer, while the physical attributes are defined using a cpBody and one or more cpShapes placed within a cpSpace.

Note: cpShape is a C structure, not an Objective-C Object. As a result, we cannot place it directly into an NSArray. There are a few possible solutions to this problem. In this case, I chose to create a simple object called Shape that wraps the cpShape structure. We then place the Shape object into the NSArray. I'll leave the actual implementation of Shape as a homework assignment (or just grab a copy from the source code).

So far, everything looks simple enough. Lets move on to the implementation. We'll go slow and take this in bite-size chunks.

Defining an extension for Entity

#import "Entity.h"
#import "PinConfigSource.h"
#import "LeftBumperConfigSource.h"
#import "RightBumperConfigSource.h"
#import "TargetConfigSource.h"
#import "BallConfigSource.h"
#import "Shape.h"
@interface Entity()
 -(void) setPosition:(CGPoint)thePosition;
    -(void) setSpace:(cpSpace*)theSpace;
    -(void) setLayer:(Layer*)theLayer;

We start by creating an extension on Entity that declares a number of private methods. We will use these methods to initialize our Entitiy instances. We will look at the actual definitions in just a moment.

init and dealloc

@implementation Entity
@synthesize shapes;
withConfigSource:(id <EntityConfigSource>)theConfigSource {
    if( (self=[super init])) {
        // these methods must be called in this order.
        [self setConfigSource: theConfigSource];
        [self setPosition:location];    
        [self setSpace: theSpace];
        [self setLayer: theLayer];   
    return self;
-(id) init {
    [NSException raise:NSInternalInconsistencyException 
                format:@"Cannot initialize using init, use %@ instead",
    // we will never get here
    return nil;    
// remember: do not release during chipmunk callbacks (e.g. collisions).
-(void) dealloc {
    [layer removeChild:sprite cleanup:NO];
    [layer release];
    [sprite release];
    for (Shape* shape in shapes) {
        cpSpaceRemoveShape(space, shape.pointer);
    [shapes release];
    if (![configSource isStatic]) {
        cpSpaceRemoveBody(space, body);
    [configSource release];
    [super dealloc];

Next we synthesize the reader method for our shapes property. Notice, we do not synthesize the position property. We will provide a custom implementation instead. While synthesizing position won't cause an error, I prefer to use @synthesize only on properties actually managed by the compiler.

Next we define the initialization and deallocation methods. initInSpace:forLayer:atLocation:with-ConfigSource: is our default initialization method. It simply calls the private methods defined in our extension. Additionally, we want to prevent people from calling NSObject's init method by mistake, so our implementation overrides init and throws an exception. Notice that we dynamically generate the string for our method name, rather than hard coding it in our exception. This helps ensure that our message will still be relevant, even if we refactor our initialization methods.

The dealloc method is somewhat more complex. We remove our entity from the Layer and the cpSpace, then release or free all the components. Notice that we must handle the memory management of Chipmunk structures differently than standard Objective-C objects. Instead of calling retain and release, we must use Chipmunk's functions to allocate and free those structures.

Correctly managing both the Objective-C objects and the C structures is one of the more complicated aspects of using Chipmunk on the iPhone. Fortunately, our Entity class will hide all this complexity from us.

There is one small wrinkle with this code. We cannot release any Entities during a Chipmunk callback (e.g. when processing collisions). I believe this restriction may be removed in later versions of Chipmunk. Still, it is not hard to work around. Either make a list of objects to release, and then release them all once the callbacks have finished, or use performSelector:withObject:afterDelay: to schedule the release. Even setting the delay value to 0 will cause the method to be delayed until the run loop is empty, and you've moved safely outside the callback code.

Now lets look at the implementation of our private methods. Again, these do the bulk of the work involved in setting up our Entities. Notice that these must be called in the correct order. First set the config source. Then set the position. Finally set the space and the layer.


-(void) setConfigSource:(id<EntityConfigSource>)theConfigSource {
    // store the config source
    configSource = theConfigSource;
    [configSource retain];
    // and setup the sprite FILE_NAMES[[delegate spriteType]]
    sprite = [Sprite spriteWithFile: 
                 FILE_NAMES[[configSource spriteType]]];
    [sprite retain];

This method stores and retains the config source. Then it queries the source for the sprite type and uses that to determine the correct file name. It then initializes and retains the sprite. Note: FILE_NAMES is an array of NSStrings defined in Utility.h.


-(void) setPosition:(CGPoint)thePosition {
    sprite.position = thePosition;
    if ([configSource respondsToSelector:
             @selector(initialSpriteRotationForLocation:)]) {
         sprite.rotation = [configSource 

The setPosition: method sets the sprite's position. Then we check to see if our config source has implemented the optional initialSpriteRotationForLocation: method. If it has, we call that method and use the result to set our rotation.


-(void) setSpace:(cpSpace*)theSpace {
    space = theSpace;
    body = [configSource createBody];
    body->p = sprite.position;
    if (![configSource isStatic]) {
        cpSpaceAddBody(space, body);
    shapes = [configSource createShapesGivenBody:body];
    [shapes retain];
    for (Shape* shape in shapes) {
        // save the InteractiveObject in the cpShape's data field.
        [shape setData: self];
        if ([configSource isStatic]) {
            // only add the static shape
            cpSpaceAddStaticShape(space, shape.pointer);
        else {
            // add the non-static shape
            cpSpaceAddShape(space, shape.pointer);

This method is a bit more complex than the rest. As mentioned previously, the cpSpace structure holds references to a number of bodies and shapes. When we step the space forward in time, Chipmunk will calculate the new position and rotation for all the bodies, as well as checking for collisions among any shapes within that space. This method creates the body and the shapes needed for our Entity and add them to the given space.

First we store a reference to the cpSpace structure. Then we ask our config source to build our cpBody structure. We then set the cpBody's position equal to the Sprite's position. As mentioned in Part 1, both the cpBody and Sprite store the entity's position, and we need to keep them in sync. Finally, we query the config source to see if this entity is static (non-moving). If it is not static, we add the body to the space.

Note: Do not add the bodies of static objects to the cpSpace structure. Any bodies in the space will have the force of gravity applied to them each time we iterate the space. While the static objects won't move, the accumulated force will cause very odd bugs during collisions.

Next, we query the config source for a list of shapes associated with our entity. We store and retain the list of Shapes. Remember, we are wrapping the cpShape structure inside a simple Objective-C class, named Shape. The cpShape structure also has a data field that can be used to store pointers to arbitrary user data. In our case, we will store a reference to this Entity. That will allow us to find the correct Entity for a given cpShape.

Iterate over all the Shapes and call setData: to set the cpSpace->data field (see the source code for implementation details). Then add the shape to the space. Note: if the shape is a static shape, you will add it using the cpSpaceAddStaticShape() function. Otherwise add it using cpSpaceAddShape().

-(void) setLayer:(Layer*)theLayer {
    layer = [theLayer retain];
    [theLayer addChild:sprite z:[configSource depth]];

Finally, we add the Layer. First, we store a reference to the Layer and retain it. We then add the Sprite to the Layer. In many ways, the Layer is to cocos2D objects what the cpSpace is to Chipmunk structures.

Also note, we query our config source for our entity's z-value. Objects with a higher z-value will be drawn over objects with a lower z-value. In Utility.h we define an enumeration for all the z-values in ascending order for the background, bumpers, ball, target and pins. The background is drawn on the bottom, and the pins are drawn on the top.

Careful attention to the z-values is important for making the game look right. For example, we have designed the target's artwork so that when the ball goes into the target, it disappears behind the target. Getting the effect we want requires coordination between the art design, the z-values and the target's shape.


-(void) updateSprite {
    if (![configSource isStatic]) {
        sprite.position = body->p;
        if ([configSource
                respondsToSelector:@selector(updatedSpriteRotation)]) {
            sprite.rotation = [configSource 

The next method is used to update our sprite position and rotation. As mentioned previously, the Chipmunk physics engine will automatically update the position of our entitiy's cpBody every time we iterate the space. We then need to call this method to keep our sprite's position in sync with the cpBody.

First, we check to make sure our object is not static. Static objects will not move, so their Sprite positions never needs updating. Then we simply copy the cpBody's position over to the Sprite.

Typically, you would want to copy the cpBody's rotation as well, but we're going to do something a little different. We only have one type of moving object, the balls, and they are round, reflective, and largely featureless. Rotating them does not make a lot of sense. However, we have placed a highlight at the top of the ball image. If we assume this is the reflection from a single light source somewhere off the top of the screen, then we should to rotate the ball so that the highlight points towards this light source. This allows us to fake 3D lighting effects within our 2D game.

First, we check to see if the config source implements the optional upatedSpriteRotation method. If it does, we set the Sprite's rotation by calling this method. If not, we do not change the rotation at all (though, we could set it equal to the body's rotation if we had other moving objects where rotating the image made sense).

Next we implement the reader for our position property. This simply returns the body's position.

Entity Accessor Methods

-(CGPoint) position {
    return body->p;

Now we start building convenience functions. Remember, the goal of building the Entity class was to hide as much of the complexity as possible. By creating a convenience method for each Entity type, we further simplify the interface. Our code only needs to access the Entity class itself. It does not need to know about the different EntityConfigSources.

Below are the convenience methods for the ball and the left bumper. I leave the rest as homework.

Entity Public Convenience Methods

+(id) ballInSpace:(cpSpace*)space 
       atLocation:(CGPoint)location {
    id <EntityConfigSource> configSource = 
        [[[BallConfigSource alloc] init] autorelease];
    return [[[Entity alloc] initInSpace:space 
                       withConfigSource:configSource] autorelease];
+(id) leftBumperInSpace:(cpSpace*)space 
               forLayer:(Layer*)layer  {
    id <EntityConfigSource> configSource = 
        [[[LeftBumperConfigSource alloc] init] autorelease];
    return [[[Entity alloc] initInSpace:space 
                             atLocation:[configSource initialLocation]
                       withConfigSource:configSource] autorelease];

These methods simply create the correct config source, and then instantiate the Entity. Note, that ballInSpace:forLayer:atLocation: takes a location parameter, which is used to set the ball's initial location. leftBumperInSpace:forLayer: does not. The location is set by the config source's initialLocation method.

There is a design issue here worth discussing. This is not a truly general approach to creating cocos2d/Chipmunk objects. It works well for this particular game, but it would be easy to come up with situations where this approach is simply not appropriate. Partially, I did that to keep the Entity code relatively simple for the purpose of this tutorial. Writing truly general code is both complicated and hard. But, part of it is also just good software engineering. You shouldn't over-engineer your classes by adding a lot of features that you may never use. Instead, add new features as and when they are needed, refactoring your existing code as you go.

Config Sources

Of course, we're not quite done yet. We still need our config sources. I'll show you two. One for the ball and one for the target. Again, I leave the rest as homework.


#import "BallConfigSource.h"
#import "Shape.h"
@implementation BallConfigSource
-(id) init {
   if ((self = [super init])) {
      CGSize size = getSpriteSize(BALL);
      radius = size.width / 2.0f;
   return self;
-(enum SpriteType) spriteType {
   return BALL;
-(int) depth {
   return BALL_DEPTH;
-(BOOL) isStatic {
   return NO;
-(cpBody*) createBody {
   return cpBodyNew(10, cpMomentForCircle(10, 0.0, radius, cpv(0,0)));
-(NSArray*) createShapesGivenBody:(cpBody*)body {
   cpShape* shape = cpCircleShapeNew(body, radius, cpv(0.0, 0.0));
   shape->e = 0.75f;
   shape->u = 0.5f;
   shape->collision_type = BALL_COLLISION;
   return [NSArray arrayWithObject:[Shape shapeFromPointer:shape]];
-(CGFloat) initialSpriteRotationForLocation:(CGPoint)location {
   return getLightRotation(location);
-(CGFloat) updatedSpriteRotationForLocation:(CGPoint)location {
   return getLightRotation(location);

Most of this should be relatively straightforward. The init method simply calculates the ball's radius based on the sprite size. Both the BALL enum and the getSpriteSize() method are defined in Utility.h.

The createBody method creates a cpBody structure with a mass of 10.0 and a moment of inertia based on Chipmunk's cpMomentForCircle() function. The CreateShapesGivenBody: method creates a single circular shape, and then sets the elasticity to 0.75 and the friction to 0.5. It then sets the collision type. We will use the collision types later to correctly dispatch different collisions.

Finally, as mentioned earlier, the balls should be rotated so that their highlight points towards our imaginary light source. The initialSpriteRotationForLocation: and updatedSpriteRotationForLocation: methods handle this by calling the getLightRotation() function, also from Utility.h.


#import "TargetConfigSource.h"
#import "Shape.h"
Shape* buildShape(cpBody* body, cpVect start, cpVect end) {
    cpShape* shape = cpSegmentShapeNew(body, start, end, 0.0f);
    shape->e = 0.5f;
    shape->u = 0.5F;
    shape->collision_type = TARGET_WALL_COLLISION;
    return [Shape shapeFromPointer:shape];
@implementation TargetConfigSource
-(enum SpriteType) spriteType {
    return TARGET;
-(int) depth {
    return TARGET_DEPTH;
-(BOOL) isStatic {
    return YES;
-(cpBody*) createBody {
    return cpBodyNew(INFINITY, INFINITY);
-(NSArray*) createShapesGivenBody:(cpBody*)body {
    CGSize size = getSpriteSize(TARGET);
    CGFloat halfWidth = size.width / 2.0f;
    cpVect upperLeft  = cpv(-halfWidth, halfWidth);
    cpVect lowerLeft  = cpv(11.0f - halfWidth, -halfWidth);
    cpVect lowerRight = cpv(halfWidth - 11.0f, -halfWidth);
    cpVect upperRight = cpv(halfWidth, halfWidth);
    // These ball will bounce off these.
    Shape* left = buildShape(body, upperLeft, lowerLeft);
    Shape* bottom = buildShape(body, lowerLeft, lowerRight);
    Shape* right = buildShape(body, lowerRight, upperRight);
    // But this shape will trigger the target.
    Shape* goal = buildShape(body, 
                             cpv(15.0f - halfWidth, 4.0f - halfWidth), 
                             cpv(halfWidth - 15.0f, 4.0f - halfWidth));
    // Need to change the collision type
    goal.pointer->collision_type = TARGET_COLLISION;
    return [NSArray arrayWithObjects:left, bottom, right, goal, nil];

The left bumper is a little more complex, but not by much. Since this is a static object, we create a cpBody with an infinite mass and moment of inertia. We then define a complex shape. This starts with three lines (left, bottom and right) that define an open cup shape. We then define a fourth goal line at the bottom of the cup. Notice, fast-moving balls might penetrate the target's wall by a few pixels before a collision is detected. To prevent the ball from accidentally triggering the goal, we create a 4-pixel padding between it and the cup. Also notice that the coordinates for the shapes are all relative to the cpBody's position (or the center of the Sprite's icon). The target's walls are given a TARGET_WALL_COLLISION, while the goal is given a TARGET_COLLISION. This will allow us to process the collisions separately. When a ball hits the wall, it will just bounce off. But, when it hits the goal, we will ring a bell and delete the ball. We also gave the target's shapes a relatively low elasticity. When a ball goes into the cup, we don't want it to just bounce out again.

Believe it or not, most of the heavy work is now done. We just need to make our main layer, and then link everything together in our app delegate.

Fake It Till You Make It

The actual implementation of the Main Layer will have to wait until the next installation. Still, we want to see our Entities in action. So, lets make a few quick modifications to the existing HelloWorldScene.m file.

First, import our Entity class at the top of the file. Then modify the eachShape() function as shown below. This simply extracts the Entity from the shape data and calls our updateSprite function.


static void
eachShape(void *ptr, void* unused)
    cpShape *shape = (cpShape*) ptr;
    Entity *entity = shape->data;
    [entity updateSprite];

Now delete the following lines from the init method.


AtlasSpriteManager *mgr = [AtlasSpriteManager 
    spriteManagerWithFile:@"grossini_dance_atlas.png" capacity:100];
[self addChild:mgr z:0 tag:kTagAtlasSpriteManager];

Now modify the addNewSpriteX:y: method as shown below.


-(void) addNewSpriteX: (float)x y:(float)y
   double offx = (CCRANDOM_0_1() * 2.0 - 1.0);
   double offy = (CCRANDOM_0_1() * 2.0 - 1.0);
    [[Entity ballInSpace:space 
              atLocation:ccp(x+offx, y + offy)] retain];

Here, we simply create a ball at the given position. We add a slight random nudge to the position, to avoid adding multiple balls in the exact same location. The collision detection system doesn't work properly if their positions are exactly the same.

Notice how much simpler addNewSpriteX:y: has become. Our Entity class hides much of the complexity that the previous implementation had to manage manually. Of course, we're creating a memory leak here by retaining and never releasing all these Entity objects. But, that's OK for a quick test.

Compile and run the application. It should add a ball whenever you tap the screen.

Sample Ball Entities

Once everything works properly, go ahead and start playing around. Look through the HelloWorldScene.m file. Try changing the gravity vector. Add different Entity types. Play around with the code and get a feel for how things work. Don't worry about messing up the HelloWorldScene class. We won't be using it at all in Part 3. Instead, we will write our own layer, MainLayer, and use that to wrap up our Pachinko game.

Most importantly, until next time, have fun. This is supposed to be a game.

Rich Warren lives in Honolulu, Hawaii with his wife, Mika, daughter, Haruko, and his son, Kai. He is a software engineer, freelance writer and part time graduate student. When not playing on the beach, he is probably writing, coding or doing research on his MacBook Pro. You can reach Rich at, check out his blog at or follow him at


Community Search:
MacTech Search:

Software Updates via MacUpdate

Airmail 3.3.2 - Powerful, minimal email...
Airmail is an mail client with fast performance and intuitive interaction. Support for iCloud, MS Exchange, Gmail, Google Apps, IMAP, POP3, Yahoo!, AOL,, Airmail was designed... Read more
Numi 3.15.1 - Menu-bar calculator suppor...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
Airmail 3.3.2 - Powerful, minimal email...
Airmail is an mail client with fast performance and intuitive interaction. Support for iCloud, MS Exchange, Gmail, Google Apps, IMAP, POP3, Yahoo!, AOL,, Airmail was designed... Read more
Numi 3.15.1 - Menu-bar calculator suppor...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
TextSoap 8.4.1 - Automate tedious text d...
TextSoap can automatically remove unwanted characters, fix up messed up carriage returns, and do pretty much anything else that we can think of to text. Save time and effort. Be more productive. Stop... Read more
TextSoap 8.4.1 - Automate tedious text d...
TextSoap can automatically remove unwanted characters, fix up messed up carriage returns, and do pretty much anything else that we can think of to text. Save time and effort. Be more productive. Stop... Read more
Backblaze - Online backup servi...
Backblaze is an online backup service designed from the ground-up for the Mac. With unlimited storage available for $5 per month, as well as a free 15-day trial, peace of mind is within reach with... Read more
Numi 3.15 - Menu-bar calculator supports...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
EtreCheck 3.3.3 - For troubleshooting yo...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
BusyContacts 1.1.8 - Fast, efficient con...
BusyContacts is a contact manager for OS X that makes creating, finding, and managing contacts faster and more efficient. It brings to contact management the same power, flexibility, and sharing... Read more

Latest Forum Discussions

See All

The best new games we played this week
We were quite busy this week. A bunch of big mobile games launched over the past few days, alongside a few teeny surprises. There're lots of quality games to load your phone with. We've gone and picked out five of our favorites for the week. [... | Read more »
Magikarp Jump beginner's guide
Magikarp Jump is a mystifying little game. Part Tamagotchi, part idle clicker, there's not a whole lot of video game there, per se, but for some reason we can't help coming back to it again and again. Your goal is to train up a little Magikarp to... | Read more »
Goat Simulator PAYDAY (Games)
Goat Simulator PAYDAY 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: ** IMPORTANT - SUPPORTED DEVICES **iPhone 4S, iPad 2, iPod Touch 5 or better Goat Simulator: Payday is the most... | Read more »
GRID Autosport delayed until autumn
Sorry mobile racing fans -- GRID Autosport has been delayed a few months. The game is now expected to launch this fall on iOS. Feral Interactive announced that they wanted more time to work on the game's UI and overall performance before launching... | Read more »
Zombie Gunship Survival Beginner's...
The much anticipated Zombie Gunship Survival is here. In this latest entry in the Zombie Gunship franchise, you're tasked with supporting ground troops and protecting your base from the zombie horde. There's a lot of rich base building fun, and... | Read more »
Mordheim: Warband Skirmish (Games)
Mordheim: Warband Skirmish 1.2.2 Device: iOS Universal Category: Games Price: $3.99, Version: 1.2.2 (iTunes) Description: Explore the ruins of the City of Mordheim, clash with other scavenging warbands and collect Wyrdstone -... | Read more »
Mordheim: Warband Skirmish brings tablet...
Legendary Games has just launched Mordheim: Warband Skirmish, a new turn-based action game for iOS and Android. | Read more »
Magikarp Jump splashes onto Android worl...
If you're tired ofPokémon GObut still want something to satisfy your mobilePokémon fix,Magikarp Jumpmay just do the trick. It's out now on Android devices the world over. While it looks like a simple arcade jumper, there's quite a bit more to it... | Read more »
Purrfectly charming open-world RPG Cat Q...
Cat Quest, an expansive open-world RPG from former Koei-Tecmo developers, got a new gameplay trailer today. The video showcases the combat and exploration features of this feline-themed RPG. Cat puns abound as you travel across a large map in a... | Read more »
Jaipur: A Card Game of Duels (Games)
Jaipur: A Card Game of Duels 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: ** WARNING: iPad 2, iPad Mini 1 & iPhone 4S are NOT compatible. ** *** Special Launch Price for a limited... | Read more »

Price Scanner via

Memorial Day savings: 13-inch Touch Bar MacBo...
B&H Photo has the 2016 Apple 13″ Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 13″ 2.9GHz/512GB... Read more
Apple refurbished 13-inch MacBook Airs availa...
Apple has Certified Refurbished 2016 13″ MacBook Airs available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: - 13″ 1.6GHz/8GB/128GB MacBook Air: $... Read more
Apple restocks refurbished 11-inch MacBook Ai...
Apple has Certified Refurbished 11″ MacBook Airs (the latest models recently discontinued by Apple), available for up to $170 off original MSRP. An Apple one-year warranty is included with each... Read more
12-inch 1.2GHz Retina MacBooks on sale for up...
B&H has 12″ 1.2GHz Retina MacBooks on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: - 12″ 1.2GHz Space Gray Retina MacBook: $1449.99 $150 off... Read more
15-inch 2.7GHz Silver Touch Bar MacBook Pro o...
MacMall has the 15-inch 2.7GHz Silver Touch Bar MacBook Pro (MLW82LL/A) on sale for $2569 as part of their Memorial Day sale. Shipping is free. Their price is $230 off MSRP. Read more
Free Tread Wisely Mobile App Endorsed By Fath...
Just in time for the summer driving season, Cooper Tire & Rubber Company has announced the launch of a new Tread Wisely mobile app. Designed to promote tire and vehicle safety among teens and... Read more
Commercial Notebooks And Detachable Tablets W...
Worldwide shipments of personal computing devices (PCDs), comprised of traditional PCs (a combination of desktop, notebook, and workstations) and tablets (slates and detachables), are forecast to... Read more
Best value this Memorial Day weekend: Touch B...
Apple has Certified Refurbished 2016 15″ and 13″ MacBook Pros available for $230 to $420 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: - 15″ 2.6GHz... Read more
13-inch MacBook Airs on sale for up to $130 o... has 13″ MacBook Airs on sale for up to $130 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (sku MMGF2LL/A): $869.99 $130 off MSRP - 13″ 1.6GHz/256GB MacBook Air (sku... Read more
2.8GHz Mac mini available for $973 with free...
Adorama has the 2.8GHz Mac mini available for $973, $16 off MSRP, including a free copy of Apple’s 3-Year AppleCare Protection Plan. Shipping is free, and Adorama charges sales tax in NY & NJ... Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
*Apple* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
Best Buy *Apple* Computing Master - Best Bu...
**509643BR** **Job Title:** Best Buy Apple Computing Master **Location Number:** 001482- Apple Valley-Store **Job Description:** **What does a Best Buy Apple Read more
*Apple* Media Products - Commerce Engineerin...
Apple Media Products - Commerce Engineering Manager Job Number: 57037480 Santa Clara Valley, California, United States Posted: Apr. 18, 2017 Weekly Hours: 40.00 Job Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.