Friday, December 9, 2011

New way to declare private methods

Normally I would put private methods in the header file. But noticed from "Learn Cocos2D 2nd Edition" book a different way been used.

The header file is quite simple:


#import "cocos2d.h"

@interface HelloWorld : CCLayer
{
}

// returns a Scene that contains the HelloWorld as the only child
+(id) scene;

@end


The private methods are however declared in the .m file as shown below with "(PrivateMethods)" added behind "@interface":


#import "HelloWorldScene.h"

// private methods are declared in this manner to avoid "may not respond to ..." compiler warnings
@interface HelloWorld (PrivateMethods)
-(void) onCallFunc;
-(void) onCallFuncN:(id)sender;
-(void) onCallFuncND:(id)sender data:(void*)data;
-(void) onCallFuncO:(id)object;
-(void) createLabelWithOffset:(int)offset;
@end

@implementation HelloWorld



This is completely new to me and indeed quite interesting!

Sunday, December 4, 2011

ARM CPUs of the iOS devices don't support division operations in hardware?

Read in the "Learn Cocos2D 2nd Edition" book Chapter 4 that "since the ARM CPUs of the iOS devices don't support division operations in hardware, multiplications are generally a bit faster."

So instead of divide by 2, you should use multiple by 0.5 - this is interesting...

Saturday, December 3, 2011

uDevGames 2011 result published

In case you are not aware, the result of uDevGames 2011 is available here. Although most of the games are for Mac OS X, you should be able to learn something there, as most importantly - there's quite of few of them with both source code and binary available for download!

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