Monday, August 12, 2013

Create a multi-plaform cocos2d-x 3.0 project

Step 1 - Download cocos2d-x

Download your cocos2d-x directory
As a pre step 1 I would uninstall some of the previous version of the cocos2d Xcode templates by following this stackoverflow post.

Step 2 - Download & Install Python

Since the script "cocos2d-x/" is a python script. You will need to download and install Python 2.7. Skip to Step 3 if you have already downloaded and installed Python. After you've downloaded your python-2.7-macosx10.6.dmg. Open it up and double click on "Python.mpkg". I use Pacifist to install the multiple package file. Python will be installed at the "/usr/local/bin" directory by default. Be sure that directory is in your environment search PATH.

Step 3 - Run the Cocos2d-x create script

Go into your Cocos2d-x directory and run the script below. Be sure to replace the project name and your project identifier to your own. I'm assuming that you are creating a C++ project, thus "cpp".

cd cocos2d-x
python ./ -p [ProjectName] -k [com.project.myproject] -l cpp

Step 4 - Open up your project

Your iOS Xcode project is now located at "cocos2d-x/projects/[ProjectName]/proj.ios"

Reference: How_to_create_a_multi-platform_project_in_one_command_line

Friday, April 26, 2013

Learn Shapes by Emplementation

This app was inspired by my nieces, nephews, friends and families who recently became parents. I’ve tried ALL of the shape learning apps available in the Apple App Store. None of them impressed me at all. With close to one billion apps in the app store today, I was ashamed as an app developer that the quality in the kids and education section in basic shapes and colors learning. 

Throughout the development of this game, I’ve worked with many of my champ toddler testers and tried to come up with the best experience for them.

Learn Shapes is made with your child in mind. Therefore, I've paid special attention on child privacy. There a child lock in placed for the parent to unlock in order to access social capabilities, other than that the entire app is child proof. No ads, No user behavior tracking, no in app purchases. This give you a peace of mind knowing it is safe and secure.

Privacy Policy for more details

Let's learn with Learn Shapes :)

Friday, April 19, 2013

Longcat 3D

A silly little kitty flying around in an endless running game. Fun for kids and cat lovers. Check it out.

Wednesday, December 12, 2012

The stage is now all yours...

PopStar Meter has launched on the Apple App Store this week. It was designed to determine the quality of your voice. It is one of its kind. This App was made with love and passion. If you haven't already done so, please support PopStar Meter.

The stage is now all yours...

Monday, July 23, 2012

Enabling Automatic Reference Counting (ARC) with Cocos2D

By following the post "Enable ARC in a Cocos2D Project: The Step-by-Step-How-To-Guide Woof-Woof!" by Steffen Itterheim, I was able to enable ARC using Cocos2D. However, I encountered a few issues along the way I thought I'd share with you fine folks.

I received six warnings: No previous prototype for 'get'...

To get rid of them search for "prototype" on the cocos2d-library target build settings. Make sure "Missing function prototypes" and "Treat missing function prototypes as errors" are both turned off to "No".

For some reason when I clicked on "Convert Objective-C ARC" it didn't convert anything, so I had to do it by hand. But it should be pretty intuitive. Comment out all the release calls and [super dealloc] calls and modify the main.m to use @autoreleasepool.
int main(int argc, char *argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppController class]));

In any case it is a good step-by-step guide to enable ARC using Cocos2D and I would also recommend reading the post "Busted! Eight Reasons not to use ARC" by Steffen Itterheim as well. Hope this will save you some time. Happy coding!!!

Thursday, December 1, 2011

Importing data into core data while preserving uniqueness: Find-or-Create implementation

The original documentation is located here:

The documentation describes how to implement "Find-or-Create" algorithm efficiently. This might not be intuitive at first, but core data does NOT have a unique insert feature. It is the developer's responsibility to implement Find-or-Create.

I implemented using blocks for three possible cases:
MatchedBlock - host and local matched objects
HostUnmatchedBlock - host objects that does not match any local objects
LocalUnmatchedBlock - local objects that does not match any host objects

typedef void (^objectOperationBlock)(NSManagedObjectContext *context,
                                     NSDictionary *hostObjectData,
                                     NSManagedObject *localManagedObject);
 * create NSManagedObject uniquely given the entity name and an array
 * of objects you want to create.
- (void) insertUniquely:(NSArray *)rawDataArray 
                    entity:(NSString *)entity 
                     error:(NSError **)outError {
    if (rawDataArray) {
        //object primary key
        NSString * primaryKeyString = [self mappingLookup:entity key:kDefaultObjectID];
        //Raw data primary key mapping look up e.g. SONG_ID
        NSString * rawDataPrimaryKeyString = [self mappingLookup:entity key:primaryKeyString];
        //sort the raw data array using its primary key ascending order
        NSArray *sortedRawDataArray = [rawDataArray sortedArrayUsingDescriptors:[self aSortDescriptor:rawDataPrimaryKeyString ascending:YES]];
        //grab the keys only
        NSArray *insertingIDs = [sortedRawDataArray valueForKey:rawDataPrimaryKeyString];
//        NSLog(@"rawKey: %@, key: %@, SongIDs: %@", rawDataPrimaryKeyString, primaryKeyString, insertingIDs);

        if (insertingIDs.count > 0) {
            //initiate a fetch that finds existing primary keys
            //get the current context
            NSManagedObjectContext *context = [self managedObjectContext];
            //fetch unmatching objects
            if (localUnmatchedOperation != nil) {
                NSError *error = nil;
                NSArray *localUnmatchedArray = [self fetchRequestContext:context
                                                               predicate:[NSPredicate predicateWithFormat:@"NOT (%K IN %@)", primaryKeyString, insertingIDs]
                                                         sortDescriptors:[self aSortDescriptor:primaryKeyString ascending:YES]
                if (error != nil) {
                    *outError = error;
                    NSLog(@"error fetching local unmatched objects: %@", error);
                //perform desinated operation for fetched localUnmatchedArray                
                for (NSManagedObject * object in localUnmatchedArray) {
                    localUnmatchedOperation(context, nil, object);
            //fetch matching objects
            NSError *error = nil;
            NSArray *matchedArray = [self fetchRequestContext:context
                                                    predicate:[NSPredicate predicateWithFormat:@"(%K IN %@)", primaryKeyString, insertingIDs]
                                              sortDescriptors:[self aSortDescriptor:primaryKeyString ascending:YES]
            if (error != nil) {
                *outError = error;
                NSLog(@"error fetching local matching objects: %@", error);

            //calculate host unmatched objects and matched objects
            NSArray *matchedIDs = [matchedArray valueForKey:primaryKeyString];            
            if (matchedIDs.count > 0 && (matchedOperation != nil || hostUnmatchedOperation != nil)) {    
                //implementing Find-or-Create algorithm described at the apple documentation link below
                NSUInteger i = 0;   //index of matched ID
                for (NSDictionary *rawData in sortedRawDataArray) {

                    //rawData Primary ID
                    NSString *oneID = [rawData objectForKey:rawDataPrimaryKeyString];
                    if (i < matchedArray.count && [[matchedIDs objectAtIndex:i] isEqualToString:oneID]) {
                        if (matchedOperation) {
                            matchedOperation(context, rawData, [matchedArray objectAtIndex:i]);
                    } else {
                        if (hostUnmatchedOperation) {
                            hostUnmatchedOperation(context, rawData, nil);

Sunday, November 6, 2011

How to setup your own Git Server using Gitolite?

Gitolite's documentation is very well written and informational. Below are basically a step by step version of it.

1. Create a Gitolite user on the server: This is the account of which Gitolite will perform git commands on the server. The users will be interacting with this account using the SSH Server. Please be sure SSH daemon is installed and configured on the server.

2. Install Git on server: Download and install the binary from git. To make life easier please copy git to "/usr/bin/" for later installation usage.
sudo cp /usr/local/git/bin/git /usr/bin/

3. SSH Public key: Generate & copy your public key to the server. It is suggested to re-name your public key on the server to $YourPublicKey = that way it can be easily identify in the future.
scp $YourPublicKey gitolite@gitserver:$YourPublicKey
ssh-copy-id -i $YourPublicKey gitolite@gitserver
4. SSH to Server: Login to server
ssh gitolite@gitserver
5. Clone Gitolite:
git clone git://
6. Install Gitolite:Make sure "setenv PATH $PATH\:/Users/docchang/bin" is in your .cshrc or equivalent.
7. Install your public key:
./gitolite/src/gl-setup $YourPublicKey
8. Your will be prompt to edit .gitolite.rc: Insert the absolute Git path to $GIT_PATH