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

Corel Painter - Digital art s...
Corel Painter lets you advance your digital art style with painted textures, subtle glazing brushwork, interactive gradients, and realistic Natural-Media. Easily transition from traditional to... Read more
iTubeDownloader 6.5.19 - Easily download...
iTubeDownloader is a powerful-yet-simple YouTube downloader for the masses. Because it contains a proprietary browser, you can browse YouTube like you normally would. When you see something you want... Read more
OmniFocus 3.8 - GTD task manager with iO...
OmniFocus is an organizer app. It uses projects to organize tasks naturally, and then add tags to organize across projects. Easily enter tasks when you’re on the go, and process them when you have... Read more
Hazel 4.4.5 - Create rules for organizin...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a familiar... Read more
Macs Fan Control 1.5.7 - Monitor and con...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
Acorn 6.6 - Bitmap image editor.
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
OnyX 3.8.2 - Maintenance and optimizatio...
OnyX is a multifunction utility that you can use to verify the startup disk and the structure of its system files, to run miscellaneous maintenance and cleaning tasks, to configure parameters in the... Read more
macOS Catalina 10.15.5 - An Operating Sy...
macOS Catalina gives you more of everything you love about Mac. Experience three all-new media apps: Apple Music, Apple TV, and Apple Podcasts. Locate a missing Mac with the new Find My app. And now... Read more
macOS High Sierra Security Updates 10.13...
macOS High Sierra introduces new core technologies that improve the most important functions of your Mac. From rearchitecting how it stores your data to improving the efficiency of video streaming to... Read more
Numi 3.28 - 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

Latest Forum Discussions

See All

Steam Link Spotlight - Signs of the Sojo...
Steam Link Spotlight is a feature where we look at PC games that play exceptionally well using the Steam Link app. Our last entry was XCOM: Chimera Squad. Read about how it plays using Steam Link's new mouse and keyboard support over here. | Read more »
Steampunk Tower 2, DreamGate's sequ...
Steampunk Tower 2 is a DreamGate's follow up to their previous tower defence game. It's available now for both iOS and Android as a free-to-play title and will see players defending their lone base by kitting it out with a variety of turrets. [... | Read more »
Clash Royale: The Road to Legendary Aren...
Supercell recently celebrated its 10th anniversary and their best title, Clash Royale, is as good as it's ever been. Even for lapsed players, returning to the game is as easy as can be. If you want to join us in picking the game back up, we've put... | Read more »
Pokemon Go Fest 2020 will be a virtual e...
Niantic has announced that Pokemon Go Fest will still take place this year although understandably it won't be a physical event. Instead, it will become a virtual celebration and is set to be held on 25th and 26th July. [Read more] | Read more »
Marvel Future Fight's major May upd...
Marvel Future Fight's latest update has now landed, and it sounds like a big one. The focus this time around is on Marvel's Guardians of the Galaxy, and it introduces all-new characters, quests, and uniforms for players to collect. [Read more] | Read more »
SINoALICE, Yoko Taro and Pokelabo's...
Yoko Taro and developer Pokelabo's SINoALICE has now opened for pre-registration over on the App Store. It's already amassed 1.5 million Android pre-registrations, and it's currently slated to launch on July 1st. [Read more] | Read more »
Masketeers: Idle Has Fallen's lates...
Masketeers: Idle Has Fallen is the latest endeavour from Appxplore, the folks behind Crab War, Thor: War of Tapnarok and Light A Way. It's an idle RPG that's currently available for Android in Early Access and will head to iOS at a later date. [... | Read more »
Evil Hunter Tycoon celebrates 2 million...
Evil Hunter Tycoon has proved to be quite the hit since launching back in March, with its most recent milestone being 2 million downloads. To celebrate the achievement, developer Super Planet has released a new updated called Darkness' Front Yard... | Read more »
Peak's Edge is an intriguing roguel...
Peak's Edge is an upcoming roguelike puzzle game from developer Kenny Sun that's heading for both iOS and Android on June 4th as a free-to-play title. It will see players rolling a pyramid shape through a variety of different levels. [Read more] | Read more »
Clash Royale: The Road to Legendary Aren...
Supercell recently celebrated its 10th anniversary and their best title, Clash Royale, is as good as it's ever been. Even for lapsed players, returning to the game is as easy as can be. If you want to join us in picking the game back up, we've put... | Read more »

Price Scanner via

New 16″ MacBook Pros now on sale for up to $2...
Apple reseller DataVision is now offering new 16″ Apple MacBook Pros for up to $255 off MSRP, each including free shipping. Prices start at $2194. DataVision charges sales tax for NY, NJ, PA, and CA... Read more
Apple now offering Certified Refurbished iPho...
Apple is now offering Certified Refurbished iPhone Xr models in the refurbished section of their online store starting at $499. Each iPhone comes with Apple’s standard one-year warranty, ships free,... Read more
Sale! Get a 10.2″ 32GB WiFi iPad for only $27...
Walmart has new 10.2″ 32GB WiFi iPads on sale for $50 off Apple’s MSRP, only $279. These are the same iPads sold by Apple in their retail and online stores. Be sure to select Walmart as the seller... Read more
Apple resellers offer new 2020 Mac minis for...
Apple resellers are offering new 2020 Mac minis for up to $50 off Apple’s MSRP with prices available starting at $759. Shipping is free: (1) B&H Photo: – 2020 4-Core Mac mini: $759 $40 off MSRP... Read more
Sprint is offering the Apple iPhone 11 free t...
Did you miss out on Sprint’s recent free iPhone SE promotion? No worries. Sprint has the 64GB iPhone 11 available for $0 per month for new lines when you trade-in a qualifying phone in any condition... Read more
Apple has clearance 2019 13″ 1.4GHz MacBook P...
Apple has Certified Refurbished 2019 13″ 1.4GHz 4-Core Touch Bar MacBook Pros available today starting at $979 and up to $440 off original MSRP. Apple’s one-year warranty is included, shipping is... Read more
Apple restocks 2019 MacBook Airs starting at...
Apple has clearance, Certified Refurbished, 2019 13″ MacBook Airs available again starting at $779. Each MacBook features a new outer case, comes with a standard Apple one-year warranty, and is... Read more
Apple restocks clearance Mac minis for only $...
Apple has restocked Certified Refurbished 2018 4-Core Mac minis for only $599. Each mini comes with a new outer case plus a standard Apple one-year warranty. Shipping is free: – 3.6GHz Quad-Core... Read more
Apple’s new 2020 13″ MacBook Airs on sale for...
B&H Photo has Apple’s new 2020 13″ 4-Core and 6-Core MacBook Airs on sale today for $50-$100 off Apple’s MSRP, starting at $949. Expedited shipping is free to many addresses in the US. The... Read more
B&H continues to offer clearance 2019 13″...
B&H Photo has clearance 2019 13″ 4-Core MacBook Pros available for up to $300 off Apple’s original MSRP, with prices starting at $1149. Expedited shipping is free to many addresses in the US. B... Read more

Jobs Board

Security Officer - *Apple* Store - NANA (Un...
**Security Officer \- Apple Store** **Description** About NMS Built on a culture of safety and integrity, NMSdelivers award\-winning, integrated support services to Read more
Transition Into Practice Program (TIP) - Sept...
…Academy-Transition into Practice (TIP) Residency program at St Mary Medical Center in Apple Valley, CA. **We are seekingRegistered Nurses who are:** + New graduate Read more
Essbase Developer - *Apple* - Theorem, LLC...
Job Summary Apple is seeking an experienced, detail-minded Essbase developer to join our worldwide business development and strategy team. If you are someone who Read more
Senior Software Engineer @ *Apple* - Theore...
Job Summary Apple is looking for a seasoned senior software engineer to join our worldwide business development and strategy team. This is an opportunity to lead a Read more
Cub Foods - *Apple* Valley - Now Hiring Par...
Cub Foods - Apple Valley - Now Hiring Part Time! United States of America, Minnesota, Apple Valley Retail Operations Post Date May 18, 2020 Requisition # 119230 Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.