Monday, November 21, 2011

Check list for all future projects

I like to slowly build up some sort of template/check list which I can follow and gradually improve on every future projects to make sure I don't miss anything important and sort of maintain a standard for the quality of work.

Things I can think of at the moment listed as below, will keep updating this list:

1. Handle device rotation properly
2. Test for memory leak
3. Handle different devices correctly - including icon, launch image, size of sprite, screen resolution, ...etc
4. Save game state/data on different scenario
5. with sound/audio
6. proper menu/high score
7. help/tutorial
8. [future] Game center support if applicable
9. [future] test in real device, not just simulator

This is definitely not a simple task....

Things learned from "iLabyrinth"

Was reading the code of iLabyrinth game by UD7 Studios and learned quite a few things worth written down even though only looked at a few files:

1)The way they handle the loading of different sprite/map files according to different device/resolution:


2) The "isDeviceIPad()" is a macro defined as below for detecting if the device is an iPad, very handy.

static BOOL isDeviceIPad(){
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
    if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
        return YES;
    }
#endif
    return NO;
}

3) The "hightRes()" part (shouldn't it be "highRes()" :-) ?) also worth a look, probably to differentiate between devices like iPhone 4 which has higher resolution from previous devices.

+ (BOOL)hightRes {
    if( [[CCDirector sharedDirector] contentScaleFactor] > 1 ){
        return YES;
    }
    
    return isDeviceIPad();
}

4) In my older projects, I always use lots of "#define" to define different game states, later learned to use "typedef enum" to just list out all of them and saved a lot of typing. Noticed as below they also assign each item a value using bit shift operation, which means may be these items can also be used for calculation/operation if required, which is quite cool.

typedef enum {
WalkPathWalk = 0,
WalkPathToTop   = 1 << 1,
WalkPathToRight = 1 << 2,
WalkPathToBottom= 1 << 3,
WalkPathToLeft  = 1 << 4,
WalkPathEntrance= 1 << 5,
WalkPathExit = 1 << 6,
WalkPathNoPath = 1 << 7,
} WalkPath;


typedef enum {
    ZeroPathToBottom= 1 << 7,
    ZeroPathToLeft  = 1 << 8,
    ZeroPathToTop   = 1 << 9,
    ZeroPathToRight = 1 << 10
} ZeroPath;


5) The way it handles game state saving is also new to me. It's called in "applicationDidEnterBackground" (shown below), "applicationWillResignActive" and "applicationWillTerminate" inside the AppDelegate code.

- (void)applicationDidEnterBackground:(UIApplication *)application {
[[CCDirector sharedDirector] stopAnimation];
[[CCDirector sharedDirector] pause];

// Save GameState
[NSKeyedArchiver archiveRootObject:[iLabyrinth sharedInstance] toFile:[iLabyrinth stateFile]];
}

6) Also a bit unclear about the concept of "Scene" and "Layer" at the moment, specially about how they interact with each other.

At first look, the game seems to only have one file called "UDGameLayer" which indicates it's a "Layer". But when I looked further down the code, inside quite a few "Scene" files (e.g. "UDGameEndScene.h" shown below), it actually includes a layer too.... hmmm.... that's a bit confusing...


@interface UDGameEndScene : CCScene {

}

@end


@interface UDGameEndLayer : CCLayer {
CCSpriteBatchNode *_backgroundLayer;
}

@end

7)This multiple build targets thing - already seen it in the Cocos2D sample project, but still worth mentioning and hopefully can later work out how to do it myself.

---------------------------------------------------

There's also a few other things I am still not very clear with Cocos2D and still looking for answers and trying to work out how it's been handled in iLabyrinth...

a) the concept of "storing multiple Sprites inside one big image file and then load the required part accordingly", specially if there's animation involved for each sprite.

b) the best way to structure the code if there's a main character (with different weapons?) and multiple levels to play - probably with different enemies/targets to fight with in each level.

Still lots of things to learn :-( ....

Tuesday, November 15, 2011

Malware detected in iphonedevsdk.com forum by chrome 14.0.835.202

I got a chrome session with iphonedevsdk.com forum left overnight, and this morning when I look at it, Chrome says "Warning: Something is not right here!" and the content talks about malware. The chrome version is 14.0.835.202, wonder if the forum admin guys aware of this, probably some sort of injection attack?

Monday, November 14, 2011

5th Open Source Game (1st in Cocos2D) - Dice in Cup

Finally got 5th Open Source Game (1st in Cocos2D) "Dice in Cup" all done (or in other words - sick of working with it and wants to start another new one :-) ). The source link is at the end of this post.

As I mentioned before, I purposely picked this simple game idea to have a chance to get familiar with Cocos2D.

A high level flow of the game from code's point of view is as below:

1. Game first started, "init" calls "initialiseGameVariables" which set "GameState" to "kGameStateStarted"

2. "init" creates all cup/seeker objects, call "moveCupToRevealObject"

3. end of "moveCupToRevealObject" will call either "stateChange_startGame" or "stateChange_gameOverDisplay" depending on "GameState"

4. "stateChange_startGame" will reset all cups initial position, set "GameState" to "kGameStateMoveCups" then call "MoveCups"

5. "MoveCups" will move cups around, at the end of all cup move, calls "stateChange_CupMoveCompleted"

6. "stateChange_CupMoveCompleted" set "GameState" to "kGameStateUserActionStart"

7. after user clicked something, "observeValueForKeyPath" will set "GameState" to either "kGameStateIncorrectChoice" or "kGameStateCorrectChoice"

===== incorrect move

8. in "scheduleControl, if "GameState" is "kGameStateIncorrectChoice", it calls "moveCupToRevealObject", which same as #3 above at the end calls "stateChange_gameOverDisplay"

9. in "stateChange_gameOverDisplay", "Restart" been shown, wait for user click restart (calls "restartGame"

10. in restartGame", remove "Restart", then call "moveCupTorevealObject" and "initialiseGameVariables"

===== correct move

11. in "scheduleControl" if "GameState" is "kGameStateCorrectChoice", it updates score/level and then sets "GameState" to "kGameStateMoveOnToNextLevel"

12. also in "scheduleControl", it calls "updateDelayAndMoveNumber" and then sets "GameState" to "kGameStateStarted" - which then starts new level and repeats from #4 above

Did I confuse you? Hope not... I believe there should be other better/cleaner ways to handle the game logic, this is what I got so far. Welcomed to let me know if you got better ideas!

Also tested in iPad simulator, as below, might need to made some adjustment with the sprite size, other than that, it works perfectly.

A few other notes:
a. Same as previous game I used KVO to "observe" the correct/incorrect moves.
b. Tested rotation and Cocos2D handles that quite well, no extra code required.
c. Tested for memory leak in both Instrument 4.0 and 4.2, no leaking found.
d. Two places which I got stuck and spent most of the time is (1) the game state change which control the flow logic and (2) how to move the cups using the actions. As the CCSequence was mainly for running multiple actions on one Sprite, I end up creating 3 of them - one each! Let me know if you can think of better ideas!
e. As the main purpose of this exercise is just as a warm-up, to get familiar with Cocos2D, didn't try other stuffs like music/sound effect, menu, ...etc, will try to cover that in future projects.

Let me know if you found any problem with the code and hope you find this post interesting. Why not try one yourself and share it with everyone your better ideas!

Source for Dice in Cup V1.0

Strange error in Xcode 3.2.3 "texture_ undeclared"

While still working on the project, I copied the "Dice in Cup" project (with Cocos2D 1.0.1 and named "Cocos2dDiceInCup") from my MacBook Pro (which the project runs perfectly with Xcode 4.2/OS X 10.7.2) to a test VMWare box running Xcode 3.2.3 on OS X 10.6.4, strangely it won't compile at all. As shown below, keep complaining about "texture_ undeclared" error.

If I right click on "texture_" and select "Jump to Definition", as below you can clearly see "texture_" is properly defined in CCSprite.h", very strange...

I later copied the project to another box with Xcode 4.0/OS X 10.6.7 and it runs perfectly. May be Xcode 3.2.3 is just too old?

Also tried searching the net but can't anything relevant.

Sunday, November 13, 2011

Almost ready - 5th Open Source Game (1st in Cocos2D) "Dice in Cup"

Sort of "almost" finished my 5th Open Source Game (1st in Cocos2D), still working on code tidying at the moment - hopefully this won't break the code :-)...

Although I called it "Dice in Cup" - which is what I first intended to do - it now looks quite different. The "Dice" is now actually the "Seeker" image from Cocos2D, and the "Cup" is actually a ugly green rock image I created in Inkscape in 5 minutes.

It's a very simple game and everyone can easily understand it within seconds. Though it's quite slow and simple at the beginning, when you reached level 9 and above, the cups move really fast and it's quite difficult following it to work out which is the right one.

I purposely picked this game as my first Cocos2D game project and the result was quite good. I now have a better idea of how all the powerful "actions" works. Was stuck with the "Cup" moving logic and the game logic for a while. Although still not 100% clear on how some of the schedule and CCSprite class stuffs work yet, after this project I felt a bit more confident in dealing with it now.

Uploaded a short demo on YouTube as below.


Hopefully can finalise all the work in the next few days and will let you know when it's all completed!

Saturday, November 12, 2011

Strange behaviour when method in "@selector" missed a parameter

I was reading and trying some of the code from this article (Cocos2D iphone tutorial: Die, Grossini, Die! – Part I) about some basic Cocos2D stuffs. One of the things I have is to create a clickable "Restart" text as below:

-(void)stateChange_gameOverDisplay {
    
    CCLOG(@"inside stateChange_gameOverDisplay");
    
    [CCMenuItemFont setFontName:@"Marker Felt"];
    [CCMenuItemFont setFontSize:30];
    CCMenuItem *play_menu = [CCMenuItemFont itemFromString:@"Restart" target:self selector:@selector(restartGame:)];
    
    CCMenu *menu =[CCMenu menuWithItems:play_menu,nil];
    menu.anchorPoint=ccp(0,0);
    menu.position = ccp(280, 20);
    [self addChild:menu];
    
    CCLOG(@"end of stateChange_gameOverDisplay");
    
}

But when I run the code, there's nothing been displayed and it just keep looping and looping as below:

inside stateChange_gameOverDisplay
inside stateChange_gameOverDisplay
inside stateChange_gameOverDisplay
inside stateChange_gameOverDisplay
inside stateChange_gameOverDisplay
inside stateChange_gameOverDisplay
inside stateChange_gameOverDisplay

It took me a long time to work out it's because when I specify the selector, there's an extra ":" behind the method name.

@selector(restartGame:)


But I declared the method incorrectly as below:

-(void)restartGame {
    CCLOG(@"inside restartGame");
    //do something here
}


The correct way should be as below, with the "(id) sender" parameter

-(void)restartGame: (id) sender {
    CCLOG(@"inside restartGame");
    //do something here
}

I guess it's probably because the "@selector" thing can't find the correct method to call? But as there's no error or warning, it might be a bit difficult to relate the symptom to the root cause...

Back in June, I wrote in this post about crash caused by missing ":", I guess this one is also similar, but from different angle, somehow.

So one more tips for everyone if you get similar strange behaviour like this...

Monday, November 7, 2011

Cool! Face Detection in iOS5 works even with Johnny Deep's multiple eyes photo!

Was following this example from ManiacDev.com which as below quickly detects the eyes and mouth in a few seconds time and highlighted all of them.


I then quickly tried it with the Johnny Deep's multiple eyes photos and it sort of works too! Except the left side picked up the wrong one, not bad isn't it?