(译)cocos2d菜单教程:第二部分

原文链接地址:http://www.iphonegametutorials.com/2010/09/07/cocos2d-menu-tutorial-part-2/

如果你还没有阅读过第一篇教程的话,那么我建议你在继续之前,回过头去完成第一部分教程再回来。
今天,我们将在上一篇教程之上添加一些东西,同时,我们会用到动画和layer之间的切换效果(transition)。
这里有本教程的完整源代码。
好了,正式出发吧!第一步,就是整理一下我们将要实现些什么东西。如果在编码之前,你不做任何的计划的话,那么你什么也做不成!下面是我们这篇教程将要实现的功能特性列表:
  1. 为credit场景和play场景添加一个新的层
  2. 当从一个场景切换到另一个场景的时候,做一些transition。
  3. 用文本构建菜单系统。
我保证接下来的内容很直白,而且很容易。
让我们先创建两个新类“PlayerLayer”和“CreditLayer”--为什么要有Credit Layer?好吧,其实就是让别人知道这个游戏是你做的。我真的希望“PlayLayer”很清晰明了,其实就是我们游戏的GameScene或者MainScene,就是你实际玩游戏的场景。
因此,像之前添加“SceneManger”类一样,右键点击“Classes”分组,然后选择“Add”,再选择“New Files”,确保选择“Objective-c”选项,同时要保证同时创建.h文件被勾上,如下所示:
(译)cocos2d菜单教程:第二部分

同样的方法创建CreditsLayer:
(译)cocos2d菜单教程:第二部分

现在,我们有两个文件,但是里面啥也没有。。。别担心,我们马上会讲到如何添加里面的内容--首先是PlayerLayer.h文件:
#import "cocos2d.h" #import "SceneManager.h" @interface PlayLayer : CCLayer { } -(void) back: (id) sender; @end
现在是PlayerLayer.m文件:
#import "PlayLayer.h" @implementation PlayLayer -(id) init{ self = [super init]; if (!self) { return nil; } CCMenuItemFont *back = [CCMenuItemFont itemFromString:@"back" target:self selector: @selector(back:)]; CCMenu *menu = [CCMenu menuWithItems: back, nil]; menu.position = ccp(160, 150); [self addChild: menu]; return self; } -(void) back: (id) sender{ [SceneManager goMenu]; } @end

现在,CreditsLayer和PlayerLayer几乎差不多,除了名字不同以外。但是,为了教学的需要,我还是要展示出来--首先是CreditsLayer.h文件:
#import "cocos2d.h" #import "SceneManager.h" @interface CreditsLayer : CCLayer { } -(void) back: (id) sender; @end
然后是CreditsLayer.m文件:
#import "CreditsLayer.h" @implementation CreditsLayer -(id) init{ self = [super init]; if (!self) { return nil; } CCMenuItemFont *back = [CCMenuItemFont itemFromString:@"back" target:self selector: @selector(back:)]; CCMenu *menu = [CCMenu menuWithItems: back, nil]; menu.position = ccp(160, 150); [self addChild: menu]; return self; } -(void) back: (id) sender{ [SceneManager goMenu]; } @end

这些文件现在都只干一件事情----有一个“back”菜单按钮,当用户点击的时候,就通过SceneManager调转到MenuLayer。然后,如果你现在编译运行的话,也不会有任何问题,但是,你点back的时候,并不会跳转到任何场景去。。。我们马上就会来解决这个问题!
现在,我们回到SceneManager并作一些修改----添加两个方法“goPlay”和“goCredits”:
#import #import "MenuLayer.h" #import "PlayLayer.h" #import "CreditsLayer.h" @interface SceneManager : NSObject { } +(void) goMenu; +(void) goPlay; +(void) goCredits; @end

同时,我们要向SceneManager.m里面添加两个方法的实现,它让我们能够跳转到PlayerLayer和CreditsLayer中去。
+(void) goPlay{ CCLayer *layer = [PlayLayer node]; [SceneManager go: layer]; } +(void) goCredits{ CCLayer *layer = [CreditsLayer node]; [SceneManager go: layer]; }

因此,现在完整的SceneManager.m文件,看起来如下所示:
#import "SceneManager.h" @interface SceneManager () +(void) go: (CCLayer *) layer; +(CCScene *) wrap: (CCLayer *) layer; @end @implementation SceneManager +(void) goMenu{ CCLayer *layer = [MenuLayer node]; [SceneManager go: layer]; } +(void) goPlay{ CCLayer *layer = [PlayLayer node]; [SceneManager go: layer]; } +(void) goCredits{ CCLayer *layer = [CreditsLayer node]; [SceneManager go: layer]; } +(void) go: (CCLayer *) layer{ CCDirector *director = [CCDirector sharedDirector]; CCScene *newScene = [SceneManager wrap:layer]; if ([director runningScene]) { [director replaceScene:newScene]; }else { [director runWithScene:newScene]; } } +(CCScene *) wrap: (CCLayer *) layer{ CCScene *newScene = [CCScene node]; [newScene addChild: layer]; return newScene; } @end

现在,我们只需要在MenuLayer中添加一些调用就可以了!
首先,修改MenuLayer的头文件:
#import "cocos2d.h" #import "SceneManager.h" #import "PlayLayer.h" #import "CreditsLayer.h" @interface MenuLayer : CCLayer { } - (void)onNewGame:(id)sender; - (void)onCredits:(id)sender; @end

因为,我们创建了“onNewGame”和“onCredits”两个函数,在第一部分里,我们并没有在MenuLayer.h里添加任何方法声明。当然,不要忘了#imports PlayerLayer.h和CreditsLayer.h两个头文件。
最后,我们需要使用SceneManager来实现“onNewGame”和“onCredits”两个方法:
- (void)onNewGame:(id)sender{ [SceneManager goPlay]; } - (void)onCredits:(id)sender{ [SceneManager goCredits]; }
(译)cocos2d菜单教程:第二部分

哇!就这么多代码!现在编译并运行,你现在有一个菜单,可以从“Play”到“Menu”,以及“Credits”之间相互切换了。
但是,看起来有点生硬,不够生动---接下来,让我们做一些更有趣的事情吧---来玩一玩transitons怎么样?:)
———————– New Note
在2010年9月1日,cocos2d更新到0.99.5-beta2了,在Transition方面做了一此改变。一些名字被改动了,如果你之前使用的是0.99.4,如果更新到0.99.5的话,那么会有一些错误。
下面是你需要做的一些更改,如果你是从0.99.4更新到0.99.5的话:
Transitions 所有的Transition类都被重新命名了 Old New CCXXXTransition CCTransitionXXX Example: Old New CCFadeTransition CCTransitionFade
你可以从下面的链接看到完整的更改列表: http://www.cocos2d-iphone.org/wiki/doku.php/release_notes:0_99_5 ———————–
那么,我们怎么做呢?我们可以让SceneManager来完成所有的工作。好,我们先在“go”方法里面使用CCFadeTransition来replaceScene,如下所示:
[director replaceScene:[CCFadeTransition transitionWithDuration:1.2f scene:newScene withColor:ccWHITE]];

从下载下来的cocos2d 测试代码中,找到Transition.h/.m,那里面有所有的transition的用法:
以下是一些样例:
[CCFadeTransition transitionWithDuration:1.2 scene:newScene withColor:ccWHITE]; [CCZoomFlipXTransition transitionWithDuration:1.2 scene:newScene orientation:kOrientationLeftOver]; [CCFlipYTransition transitionWithDuration:1.2 scene:newScene orientation:kOrientationDownOver];

我们将封装一下我们的类,使之接收两个参数“delay time”和“new scene”的名字。。。为了从场景的字符串名字获得场景类,我们所要下面这个方法:
Class c = NSClassFromString(r);"

整个SceneManager类看起来如下所示:
#define TRANSITION_DURATION (1.2f) @interface FadeWhiteTransition : CCFadeTransition +(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s; @end @interface ZoomFlipXLeftOver : CCZoomFlipXTransition +(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s; @end @interface FlipYDownOver : CCFlipYTransition +(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s; @end @implementation FadeWhiteTransition +(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s { return [self transitionWithDuration:t scene:s withColor:ccWHITE]; } @end @implementation ZoomFlipXLeftOver +(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s { return [self transitionWithDuration:t scene:s orientation:kOrientationLeftOver]; } @implementation FlipYDownOver +(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s { return [self transitionWithDuration:t scene:s orientation:kOrientationDownOver]; } static int sceneIdx=0; static NSString *transitions[] = { @"FlipYDownOver", @"FadeWhiteTransition", @"ZoomFlipXLeftOver", }; Class nextTransition() { // HACK: else NSClassFromString will fail [CCRadialCCWTransition node]; sceneIdx++; sceneIdx = sceneIdx % ( sizeof(transitions) / sizeof(transitions[0]) ); NSString *r = transitions[sceneIdx]; Class c = NSClassFromString(r); return c; }

因此,最后修改一下“go”函数,首先,我们添加下面一行代码:
Class transition = nextTransition();

然后,我们把下面的语句:
[director runWithScene:newScene];
替换成:
[director replaceScene:[transition transitionWithDuration:TRANSITION_DURATION scene:newScene]];

最终SceneManger的go函数看起来如下所示:
+(void) go: (CCLayer *) layer{ CCDirector *director = [CCDirector sharedDirector]; CCScene *newScene = [SceneManager wrap:layer]; Class transition = nextTransition(); if ([director runningScene]) { [director replaceScene:[transition transitionWithDuration:TRANSITION_DURATION scene:newScene]]; }else { [director runWithScene:newScene]; } }
(译)cocos2d菜单教程:第二部分

很酷,对吧?
好像这个教程还不够,我们还可以调加更多的效果。。。最后,我还想在菜单文本上面添加一些效果。为了实现这个,我们需要修改MenuLayer.m文件。 首先,我们先把titleLeft和titleRight CClabel从下面的代码:
titleLeft.position = ccp(80, 345); [self addChild: titleLeft]; titleRight.position = ccp(220, 345); [self addChild: titleRight];
改在下面的代码:
titleLeft.position = ccp(80, -80); [self addChild: titleLeft]; titleRight.position = ccp(220, 520); [self addChild: titleRight];
然后为每一个菜单项添加一个动画:
CCAction *titleRightAction = [CCSequence actions: [CCDelayTime actionWithDuration: delayTime], [CCEaseBackOut actionWithAction: [CCMoveTo actionWithDuration: 1.0 position:ccp(220,345)]],nil];

oh!我的天,这在干嘛啊!
创建一个CCAction对象,它由于系列的事件组成。
这个事件序列首先等待0.3秒,然后移动到(220,345)的位置,时间间隔为1秒,同时用EaseBackOut修饰了,所以是先快后慢。
一旦我们创建了这个动作序列之后,我们在titleLeft上面运行这个action。
[titleLeft runAction: titleLeftAction];

我们同时要为titleRight添加类似的行为。
最后的动画就是Menu本身:
for (CCMenuItemFont *each in [menu children]) { each.scaleX = 0.0f; each.scaleY = 0.0f; CCAction *action = [CCSequence actions: [CCDelayTime actionWithDuration: delayTime], [CCScaleTo actionWithDuration:0.5F scale:1.0], nil]; delayTime += 0.2f; [each runAction: action]; }

你可以讲讲上面的代码是干嘛用的吗?我们又创建了一个“Action”变量,先停0.3秒,然后0.5秒缩放到1.0。因为我们开始之前把scale设置为0,这样就可以在0.5秒的时间内,慢慢放大到100%的尺寸。让我们运行一下代码,体验一下吧!
(译)cocos2d菜单教程:第二部分

再见!
Tags: 

延伸阅读

最新评论

发表评论