不管是多么华丽,多么耐玩的,与第的往往却是.在cocos2d里,了专门的CCMenu和CCMentem帮助这快捷 的实现游戏菜单.并且,借助各种动画效果,把游戏菜单做得很酷.
这次,依然是从cocos2d的官方例子入手.官方的MenuTest例子,提供了4个层来展示各种菜单效果和的实现.我们逐个来一下关键代码.已经学习cocos2d好几天了,所以有些重复出现的代码,在学习里会省略掉,只分析关键代码. @implementation Controller - ( void ) applicationDidF ishLaunching : (UIApplication * )application { // 以上省略了大量初始化代码 CCScene *scene = [CCScene node ]; // 这里是关键要学习的部分. // 既往我,放在同一个Scene里的多个Layer,同时按不同的z-order显示 // 存在先后显示顺序的Layer,应该放入不同的Scene里显示. // 而这个,在发现CCMultiplexLayer的使用后,才得以真正理解. // 利用switchTo,可以改变激活显示的Layer,在Scene里改变显示的Layer CCMultiplexLayer *layer = [CCMultiplexLayer layerWithLayers : [Layer1 node ], [Layer2 node ], [Layer3 node ], [Layer4 node ], nil ]; [scene addChild : layer z : 0 ]; [ makeKeyAndVisible ]; [ [CCDirector sharedDirector ] runWithScene : scene ]; } //以下省略了大量代码 @end @implementation Layer1 - ( id ) init { if ( (self = [super init ] ) ) { //设置默认的菜单项属性 [CCMenuItemFont setFontSize : 30 ]; [CCMenuItemFont setFontName : @ "Courier New" ]; //创建一个菜单项 //这个菜单项完全使用精灵完成. //与其说是菜单项,不如说是个按钮,它像按钮一样,提供普通状态,点中状态和禁用状态三种不同状 态下需要显示的Site //并且,与UIButton类似的,点击事件通过对target的回调方法来实现. CCSprite *spriteNormal = [CCSprite spriteWithFile : @ "menuitemsprite.png" rect :CGRectMake ( 0, 23 * 2, 115, 23 ) ]; CCSprite *spriteSelected = [CCSprite spriteWithFile : @ "menuitemsprite.png" rect :CGRectMake ( 0, 23 * 1, 115, 23 ) ]; CCSprite *spriteDisabled = [CCSprite spriteWithFile : @ "menuitemsprite.png" rect :CGRectMake ( 0, 23 * 0, 115, 23 ) ]; CCMenuItemSprite *item1 = [CCMenuItemSprite itemFromNormalSprite :spriteNormal selectedSprite :spriteSelected disabledSprite :spriteDisabled target :self selector : @selector (menuCallback : ) ]; //创建第二个菜单项. //这个菜单项与第一个类似,不同之处是直接使用完称,比精灵更简洁. CCMenuItem *item2 = [CCMenuItem itemFromNormalImage : @ "SendScoreButton.png"selectedImage : @ "SendScoreButtonPressed.png" target :self selector : @selector (menuCallback2 : ) ]; //创建第三个菜单项 //这个菜单项使用的是文本Label方式 //值得一提的是,cocos2d提供了超级方便的自字库调用方法. //如下方法中,设置好字库,并且以ascii字符排序顺序定义好字库的初始字符,就可以使用 字库创建文本Label. //以label方式创建的菜单项,会自动以点击放大作为菜单的操作效果来处理. //如果要求护理特殊的点中效果,也可以继承CCMenuItem之后复写selected方 法来实现 CCLabelAtlas *labelAtlas = [CCLabelAtlas labelAtlasWithString : @ "0123456789"charMapFile : @ "fps_images.png" itemWidth : 16 itemHeight : 24 startCharMap : '.' ]; CCMenuItemLabel *item3 = [CCMenuItemLabel itemWithLabel :labelAtlas target :self selector : @selector (menuCallbackDisabled : ) ]; item3.disabledColor = ccc3 ( 32, 32, 64 ); item3.color = ccc3 ( 200, 200, 255 ); // 创建第四个菜单项,这是一个纯文本的菜单项. CCMenuItem *item4 = [CCMenuItemFont itemFromString : @ "I toggle enable items" target : self selector : @selector (menuCallbackEnable : ) ]; // 创建第五个菜单项. // 这也是一个使用文本配合字库文件创建的菜单项. // 不同的是,这里使用了fnt格式的字库文件.关于fnt格式的字库描述文件,我们今后再做详细. CCBitmapFontAtlas *label = [CCBitmapFontAtlas bitmapFontAtlasWithString : @ "configuration"fntFile : @ "bitmapFontTest3.fnt" ]; CCMenuItemLabel *item5 = [CCMenuItemLabel itemWithLabel :label target :self selector : @selector (menuCallbackConfig : ) ]; // 创建第六个菜单项 // 这是一个最普通的文本菜单项,但是它搭配了一个动画效果.文本颜色,会一直变化 CCMenuItemFont *item6 = [CCMenuItemFont itemFromString : @ "Quit" target :self selector : @selector (onQuit : ) ]; id color_action = [CCTintBy actionWithDuration :0.5f red : 0 green :- 255 blue :- 255 ]; id color_back = [color_action reverse ]; id seq = [CCSequence actions :color_action, color_back, nil ]; [item6 runAction : [CCRepeat ever actionWithAction :seq ] ]; // 使用上述所有菜单项,菜单. CCMenu *menu = [CCMenu menuWithItems : item1, item2, item3, item4, item5, item6, nil ]; // 将菜单居中对齐 [menu alignItemsVertically ]; // 给菜单一个展现效果. // 以下的,实现了菜单项交叉从左右飞入的效果,还是很酷滴. // 关于cocos2d各种动画效果的使用,我觉得有必要单独开一篇学习笔记来学习,今天就先略过吧. CGSize s = [ [CCDirector sharedDirector ] winSize ]; int i = 0; for ( CCNode *child in [menu children ] ) { CGPoint dstPoint = child.position; int offset = s.width / 2 + 50; if ( i % 2 == 0 ) offset = -offset; child.position = ccp ( dstPoint.x + offset, dstPoint.y ); [child runAction : [CCEase Out actionWithAction : [CCMoveBy actionWithDuration : 2 position :ccp (dstPoint.x - offset, 0 ) ] period : 0.35f ] ]; i ++; } //将第三个菜单项设为禁用,用于演示toggle菜单项的 disabledItem = [item3 retain ]; disabledItem.isEnabled = NO; [self addChild : menu ]; } return self; } - ( void ) menuCallback : ( id ) sender { //点击菜单项时,将激活Layer切换为一个,相当于进入2级菜单 [ (CCMultiplexLayer * )parent_ switchTo : 1 ]; } - ( void ) menuCallbackEnable : ( id ) sender { //点击菜单项时,将某个菜单项禁用 disabledItem.isEnabled = ~disabledItem.isEnabled; } - ( void ) onQuit : ( id ) sender { //点击退出按钮的处理 //在SDK 3.0以上,不允许自己退出.所以,程序其实不应该有自己的Quit菜单项. // http://developer.apple./iph/library/qa/qa2008/qa1561. [ [CCDirector sharedDirector ] end ]; if ( [ [UIApplication sharedApplication ] respondsToSelector : @selector (terminate ) ] ) [ [UIApplication sharedApplication ] performSelector : @selector (terminate ) ]; else NSLog ( @ "YOU CAN'T TERMINATE YOUR APPLICATION PROGRAMATICALLY in SDK 3.0+" ); } //省略了其他代码. @end
/第四个层演示了比较经典的设置.主要通过CCMenuItemToggle来实现@implementation Layer4-(id) init{ [super init]; //创建一组开关菜单项,简单地说,就是on/of //这组菜单项由两部分组成 //title是显示用的,不可以接受 [CCMenuItemFont setFontName: @"American Typewriter"]; [CCMenuItemFont setFontSize:18]; CCMenuItemFont *title1 = [CCMenuItemFont itemFromString: @"Sound"]; [title1 setIsEnabled:NO]; //接下来的是可以接受用户点击的菜单项 //这个菜单项提供了两个item,在call时,可以根据选中的index切换显示 [CCMenuItemFont setFontName: @"Marker Felt"]; [CCMenuItemFont setFontSize:34]; CCMenuItemToggle *item1 = [CCMenuItemToggle itemWithTarget:self selector:@selector(menuCallback:) items: [CCMenuItemFont itemFromString: @"On"], [CCMenuItemFont itemFromString: @"Off"], nil]; //与上一个菜单项项相同,省略了两组共四个菜单项的代码 //这个菜单项与上面的相同 [CCMenuItemFont setFontName: @"American Typewriter"]; [CCMenuItemFont setFontSize:18]; CCMenuItemFont *title4 = [CCMenuItemFont itemFromString: @"Orientation"]; [title4 setIsEnabled:NO]; [CCMenuItemFont setFontName: @"Marker Felt"]; [CCMenuItemFont setFontSize:34]; CCMenuItemToggle *item4 = [CCMenuItemToggle itemWithTarget:self selector:@selector(menuCallback:) items: [CCMenuItemFont itemFromString: @"Off"], nil]; //不同的是,这个菜单项使用了subItems的addObjectsFromArray方法来设置更多 的可选项. NSArray *more_items = [NSArray arrayWithObjects: [CCMenuItemFont itemFromString: @"33%"], [CCMenuItemFont itemFromString: @"66%"], [CCMenuItemFont itemFromString: @"100%"], nil]; [item4.subItems addObjectsFromArray: more_items]; item4.selectedIndex = 2;//设置一个初选中的 // 设置第五组菜单项 [CCMenuItemFont setFontName: @"Marker Felt"]; [CCMenuItemFont setFontSize:34]; CCBitmapFontAtlas *label = [CCBitmapFontAtlas bitmapFontAtlasWithString:@"go back"fntFile:@"bitmapFontTest3.fnt"]; CCMenuItemLabel *back = [CCMenuItemLabel itemWithLabel:label target:self selector:@selector(backCallback:)]; //构建菜单 CCMenu *menu = [CCMenu menuWithItems: title1, title2, item1, item2, title3, title4, item3, item4, back, nil]; //共五组九个菜单项. //对齐菜单项 //这是一个比较独特的对齐方法,即让菜单项目以分列方式居中对齐. //第一组两列,会让前两个菜单项,将屏幕分为两列,在每列内居中. //最后设置为了列,使一个菜单项单独占据一行 [menu alignItemsInColumns: [NSNumber numberWithUnsignedInt:2], [NSNumber numberWithUnsignedInt:2], [NSNumber numberWithUnsignedInt:2], [NSNumber numberWithUnsignedInt:2], [NSNumber numberWithUnsignedInt:1], nil ]; // 2 + 2 + 2 + 2 + 1 = 共9个. [self addChild: menu]; return self;}-(void) menuCallback: (id) sender{ //选中菜单项的回调,切换显示选中项目 NSLog(@"selected item: %@ index:%d", [sender selectedItem], [sender selectedIndex] );}//省略部分代码@end