又helloWorld了,为什么要说又呢?cocos2d的helloWorld相对别的语言来说稍微复杂一些,因为虽然很简单,但是涉及到了一些ios的语法和cocos2d的一些特征,所以我们要结合起来看这个东西,其实也没那么复杂了,下面开始吧;
构建一个cocos2d的helloWorld很简单,装上cocos2d后,在Xcode模板中选择cocos2d,就像之前的文章说的那样,然后直接运行,就可以生成一个helloWorld,我用的2d版本是2.0版本的,所以和大家在网上或者一些书上看到的helloWorld不太一样,区别就是helloworld字样下面有两个可点击的label,如下图
下面两个可点击的menu使用的是ios中game Center的协议,我们用不到,一会儿代码中会介绍,下面来看代码;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create the main window
window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Create an CCGLView with a RGB565 color buffer, and a depth buffer of 0-bits
CCGLView *glView = [CCGLView viewWithFrame:[window_ bounds]
pixelFormat:kEAGLColorFormatRGB565 //kEAGLColorFormatRGBA8
depthFormat:0 //GL_DEPTH_COMPONENT24_OES
preserveBackbuffer:NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
director_ = (CCDirectorIOS*) [CCDirector sharedDirector];
director_.wantsFullScreenLayout = YES;
// Display FSP and SPF
[director_ setDisplayStats:YES];
// set FPS at 60
[director_ setAnimationInterval:1.0/60];
// attach the openglView to the director
[director_ setView:glView];
// for rotation and other messages
[director_ setDelegate:self];
// 2D projection
[director_ setProjection:kCCDirectorProjection2D];
// [director setProjection:kCCDirectorProjection3D];
// Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices
if( ! [director_ enableRetinaDisplay:YES] )
CCLOG(@"Retina Display Not supported");
// Default texture format for PNG/BMP/TIFF/JPEG/GIF images
// It can be RGBA8888, RGBA4444, RGB5_A1, RGB565
// You can change anytime.
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
// If the 1st suffix is not found and if fallback is enabled then fallback suffixes are going to searched. If none is found, it will try with the name without suffix.
// On iPad HD : "-ipadhd", "-ipad", "-hd"
// On iPad : "-ipad", "-hd"
// On iPhone HD: "-hd"
CCFileUtils *sharedFileUtils = [CCFileUtils sharedFileUtils];
[sharedFileUtils setEnableFallbackSuffixes:NO]; // Default: NO. No fallback suffixes are going to be used
[sharedFileUtils setiPhoneRetinaDisplaySuffix:@"-hd"]; // Default on iPhone RetinaDisplay is "-hd"
[sharedFileUtils setiPadSuffix:@"-ipad"]; // Default on iPad is "ipad"
[sharedFileUtils setiPadRetinaDisplaySuffix:@"-ipadhd"]; // Default on iPad RetinaDisplay is "-ipadhd"
// Assume that PVR images have premultiplied alpha
[CCTexture2D PVRImagesHavePremultipliedAlpha:YES];
// and add the scene to the stack. The director will run it when it automatically when the view is displayed.
[director_ pushScene: [IntroLayer scene]];
// Create a Navigation Controller with the Director
navController_ = [[UINavigationController alloc] initWithRootViewController:director_];
navController_.navigationBarHidden = YES;
// set the Navigation Controller as the root view controller
// [window_ addSubview:navController_.view]; // Generates flicker.
[window_ setRootViewController:navController_];
// make main window visible
[window_ makeKeyAndVisible];
return YES;
}
同大部ios应用一样,代码端是从application:didFinishLaunchingWithOptions方法开始的,这里面的内容是自动生成的,需要注意的语句有以下几条director_ = (CCDirectorIOS*) [CCDirectorsharedDirector]; 生成一个导演类,从字面意思就可以理解,这个director是掌控游戏全局的,如果再深的看下源码的话会发现这是一个单一类,在CC中,以share开头的方法生成的对象,基本上都是单一类;
navController_ = [[UINavigationControlleralloc] initWithRootViewController:director_]; 从这条语句可以看出,cocos2d与普通的sdk开发真的很接近,director本质上更接近一个viewController;
[director_ pushScene: [IntroLayerscene]]; 这条语句指明了程序跳转的流程,跳向了IntroLayer;cocos2d是鼓励游戏有很鲜明的风格的,就是游戏介绍-菜单-关卡之类,这个就是游戏的介绍,至于scene,layer这种场景和层之间的关系我们下次再介绍,现在暂时不用理会,我们现在转向IntroLayer类;
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
IntroLayer *layer = [IntroLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
//
-(void) onEnter
{
[super onEnter];
// ask director for the window size
CGSize size = [[CCDirector sharedDirector] winSize];
CCSprite *background;
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ) {
background = [CCSprite spriteWithFile:@"Default.png"];
background.rotation = 90;
} else {
background = [CCSprite spriteWithFile:@"Default-Landscape~ipad.png"];
}
background.position = ccp(size.width/2, size.height/2);
// add the label as a child to this Layer
[self addChild: background];
// In one second transition to the new scene
[self scheduleOnce:@selector(makeTransition:) delay:1];
}
-(void) makeTransition:(ccTime)dt
{
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[HelloWorldLayer scene] withColor:ccWHITE]];
}
@end
从代码中我们可以看到只有几个方法,首先是一个静态方法,+( CCScene *) scene
里面生成了一个场景,并把当前类生成的层添加了上去;该层的动态效果就是在方法
-(void)onEnter
中定义的,里面将图片Default.png作为背景定义到了屏幕居中的位置,在2d里面,图片基本上都是以精灵spite存在的, 这些之后都会详细介绍,我们今天只看流程;往下看我们会看到延迟加载的makeTransition方法,里面生成了一个HelloWorld层并跳转;
在HelloWorldLayer.m中我们发现,在生成HelloWorld层后就将其添加到了我们之前生成的场景(Scene)上,另外我们看下非常重要的init方法,里面的内容定义了我们看到的helloWorld效果
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
// create and initialize a Label
CCLabelTTF *label = [CCLabelTTF labelWithString:@"Hello World" fontName:@"Marker Felt" fontSize:64];
// ask director for the window size
CGSize size = [[CCDirector sharedDirector] winSize];
// position the label on the center of the screen
label.position = ccp( size.width /2 , size.height/2 );
// add the label as a child to this Layer
[self addChild: label];
//
// Leaderboards and Achievements
//
// Default font size will be 28 points.
[CCMenuItemFont setFontSize:28];
// Achievement Menu Item using blocks
CCMenuItem *itemAchievement = [CCMenuItemFont itemWithString:@"Achievements" block:^(id sender) {
GKAchievementViewController *achivementViewController = [[GKAchievementViewController alloc] init];
achivementViewController.achievementDelegate = self;
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] presentModalViewController:achivementViewController animated:YES];
[achivementViewController release];
}
];
// Leaderboard Menu Item using blocks
CCMenuItem *itemLeaderboard = [CCMenuItemFont itemWithString:@"Leaderboard" block:^(id sender) {
GKLeaderboardViewController *leaderboardViewController = [[GKLeaderboardViewController alloc] init];
leaderboardViewController.leaderboardDelegate = self;
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] presentModalViewController:leaderboardViewController animated:YES];
[leaderboardViewController release];
}
];
CCMenu *menu = [CCMenu menuWithItems:itemAchievement, itemLeaderboard, nil];
[menu alignItemsHorizontallyWithPadding:20];
[menu setPosition:ccp( size.width/2, size.height/2 - 50)];
// Add the menu to the layer
[self addChild:menu];
}
return self;
}
很明显的看到,里面生成了一个CCLabel,并定义了内容“HelloWorld",设置了字体,位置等显示信息,之后定义了两个MenuItem,并将其添加到了menu上,这就是我们看到的helloWorld下面的两个可点击的菜单了,在定义菜单选项时,用到了block语法,很好理解,里面的内容就是点击之后的效果;我们可以尝试将第二个item作出如下修改尝试:
CCMenuItem *itemLeaderboard = [CCMenuItemFont itemWithString:@"holydancer's blog" block:^(id sender) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://blog.csdn.net/holydancer/"]];
// GKLeaderboardViewController *leaderboardViewController = [[GKLeaderboardViewController alloc] init];
// leaderboardViewController.leaderboardDelegate = self;
//
// AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
//
// [[app navController] presentModalViewController:leaderboardViewController animated:YES];
//
// [leaderboardViewController release];
}
];
这样就会变成如图的效果;
点击后会调用浏览器打开代码里给的链接;
另外,在该类中还有另外两个方法
-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
这是调用game center实现的委托方法,里面定义的是如果返回的话执行的效果,看代码我们知道如果点击done,会返回之前的画面;另外,我一直习惯用arc,cocos2d现在也很好的可以支持,所以内存管理上的纠结事我们就不管了,另外我们还可以发现代码中的好多注释,真是相当人性化啊;