您的位置:首页 > 移动开发 > Cocos引擎

3.【cocos2d翻译系列】Beginner's Guide-Lesson3:Scene and menus

2013-06-19 10:47 731 查看
Lesson3:Scene and menus(场景和菜单)

在这篇教程中,你将会学习怎样使用"scenes"来安排(划分场景)你的游戏,并且怎样在scene和scene之间转换。

这些东西比较简单,我们也会涉及CCMenu及相关的一些类,用这些可以很简单地创建菜单scene。

这篇教程假设你已经学习过了Lesson1.Install & Test 和 Lesson2.Your First Game

Scenes(场景)

    Cocos2d中的"scene"就是指定类型的node(CCNode的子类),它可以作为基本的父容器用来盛放其他可见的node。
你可以根据你的喜好使用它,但是典型的用法一般是用一个scene作为你真正游戏的场景,用另一个scene显示游戏标题,
最高分列表,选项,等等。用CCScene类来描述一个scene。

    一个scene如果是可见的那么说明它正在运行,可以执行actions等等。在同一时刻只能有一个scene运行。然而有时,
可能需要运行另一个scene,那就暂停当前的scene;过后在恢复当前的scene。(原文说得比较麻烦:将另一个新的
scene入栈,它就会在原来那个scene的上面,然后暂停当前的scene,运行新的scene,过后在将运行的scene出栈,
恢复运行原来的那个scene)或者,你可以使用一个scene替代全部其他的scene(这种方法不错,因为它占用的内存更少)

这种入栈/出栈或者替换scene的事情都是由导演(CCDirector)做的。如果你浏览过工程模板的话,你应该见过入下得代
码。在应用代理appDelegate中(例如:在Lesson2AppDelegate.m或者其他类似的文件名)的函数
applicationDidFinishLaunching的末尾处,你将会发现如下的代码:

[[CCDirector sharedDirector] runWithScene: [HelloWorld scene]];


这行代码就是告诉导演开始运行给定的scene(HelloWorld)
用其他的scene替换当前正在运行的scene(例如:当用户点屏幕上的菜单“Play”按钮时,或者当游戏结束后你想回到主菜单时)
只需要调用导演的replaceScene函数:

[[CCDirector sharedDirector] replaceScene: [SomeOtherScene scene]];


这行代码就是结束当前的scene,并且运行指定的scene。你也可以通过再次调用replaceScene,重新运行原来的那个scene。
如果你仅仅是想暂时停止当前的scene,使用pushScene代替replaceScene。随后你可以通过调用popScene结束新的scene,
恢复原来的那个scene。但是要尽量少使用,因为iPhone的内存容量是有限的,并且所有的scene的堆栈都是在内存中的。
导演还能做许多事,像暂停/恢复当前的scene 。想要详细了解CCDirector 去官方网站查看CCDirector
reference

Fancy Transitions (转场特效)

场景和场景之间的转场特效支持由CCTransition*类支持

[[CCDirector sharedDirector] replaceScene: [CCTransitionFade transitionWithDuration:0.5f
scene:[SomeOhterScene scene]];  


一些常用的转场类:
CCTransitionFade (逐渐变淡)
CCTransitionFlipAngular  (对角立体旋转)
CCTransitionShrinkGrow (缩放效果)
CCTransitionMoveInB  (从下方出现)
CCTransitionMoveInT  (从上方出现)
CCTransitionMoveInL  (从左边出现)
CCTransitionMoveInR  (从右方出现)
CCTransitionFadeTR  (从左下方向右上方碎片化变淡)
CCTransitionFadeUp  (从下向上横栏翻转式变淡)
CCTransitionFlipX  (左右立体翻转)
CCTransitionFlipY  (上下立体翻转)
CCTransitionPageTurn  (翻页效果)
CCTransitionCrossFade  (逐渐变淡)

ff60

想知道更多地转场类可以查看API文档

Menu

菜单提供了一条用户和游戏交互的途径,这里使用了一个GUI(图形用户界面)概念:“按钮”。人们常常通过菜单告诉导演
切换scene,但是菜单也是一种方便灵活的控制游戏的方法。
创建菜单,仅需创建一个CCMenu的实例:

CCMenu * myMenu = [CCMenu menuWithItems:nil];


这段代码创建一个空的菜单,没有菜单项(按钮)。为了使菜单能用,你需要添加一些菜单项。

这里有几种菜单项可供选择:


CCMenuItemAtlasFont
CCMenuItemFont
CCMenuItemImage
CCMenuItemLabel
CCMenuItemSprite
CCMenuItemToggle 

    这些菜单项之间有细微的不同,但是从本质来说,它们都允许你指定一个目标对象(target)和一个selector
(当按钮被触摸的时候会调用)。

    其中最简单的一个创建菜单项的方法就是用CCMenuItemImage,只需使用一个指定的图片作为菜单项的“触摸区域”。

CCMenuItemImage *menuItem1 = [CCMenuItemImage itemFromNormalImage:@"myFirstButton.png"
                  selectedImage: @"myFirstButton_selected.png"
                  target:self
                  selector:@selector(doSomething:)];


itemFromNormalImage就是你想当做菜单项的图片
selectedImage就是当按钮被触摸时的按钮图片
target指定了哪个对象处理菜单项的触摸事件(此处使用self,代表了菜单所处的那个scene)
selector就是要被调用的目标函数

注意:@selector(doSomething)和@selector(doSomething:)是不一样的(注意那个多出来的冒号)。带着那个冒号,这个菜单项
会作为参数传递过去。这个函数被调用时,你给它传过去这个附加的数据是非常有用的。例如,你可以使用菜单项的'tag'属性决定
怎样开始。你甚至可以选择用子类扩充添加一些额外的信息,然后在被调用的函数中访问。

一旦你创建了你的菜单项,你可以添加它们到菜单中,添加的方法和添加“东西”到CCNode中是一样的。

[myMenu addChild:menuItem1];


 二选一就行,你还可以一次性创建几个菜单项并且添加它们到菜单中,用那个创建菜单时用到的函数menuWithItem构造函数,

就像这样。。。(在这个例子中,记住一点构造函数参数列表要以nil结尾)

CCMenu *myMenu = [CCMenu menuWithItems:menuItem1, menuItem2, menuItem3, nil];


 CCMenu当然也提供了一些方便的函数来布局你的菜单,就像“alignItemsVertically” 和“alignItemsInRows”,可以这样用: 

[myMenu alignItemsVertically];


 如果放在一起做的话,看起来应该像下面的样子:

// Create some menu items(创建一些菜单项)
CCMenuItemImage * menuItem1 = [CCMenuItemImage itemFromNormalImage:@"myfirstbutton.png"
selectedImage: @"myfirstbutton_selected.png" target:self selector:@selector(doSomethingOne:)];

CCMenuItemImage * menuItem2 = [CCMenuItemImage itemFromNormalImage:@"mysecondbutton.png"
selectedImage: @"mysecondbutton_selected.png" target:self selector:@selector(doSomethingTwo:)];

CCMenuItemImage * menuItem3 = [CCMenuItemImage itemFromNormalImage:@"mythirdbutton.png"
selectedImage: @"mythirdbutton_selected.png" target:self selector:@selector(doSomethingThree:)];

// Create a menu and add your menu items to it(创建菜单,并将菜单项添加到菜单中)
CCMenu * myMenu = [CCMenu menuWithItems:menuItem1, menuItem2, menuItem3, nil];

// Arrange the menu items vertically(安排菜单项的位置竖直排列)
[myMenu alignItemsVertically];

// add the menu to your scene(添加菜单到你的scene中)
[self addChild:myMenu];


这里有6个图片供你测试显示的结果













为了使用这些图片你需要下载它们,并且把它们放在你工程得根目录下,然后添加它们到你Xcode中的资源文件夹中。
你会注意到每一个菜单项都有一个单独的回调函数,所以你需要添加上它们:

- (void) doSomethingOne: (CCMenuItem *) menuItem
{
NSLog(@"The first menu was called");
}

- (void) doSomethingTwo: (CCMenuItem *) menuItem
{
NSLog(@"The second menu was called");
}

- (void) doSomethingThree: (CCMenuItem *) menuItem
{
NSLog(@"The third menu was called");
}


 
查询更多关于menus的用法,请通读CCMenu文档。
完成最初的三篇教程你的代码可能看起来和下面的类似,注意下面创建按钮被分开了。

// HelloWorldLayer.m
// Lesson1
//

// Import the interfaces
#import "HelloWorldScene.h"
#import "CCTouchDispatcher.h"

CCSprite *seeker1;
CCSprite *cocosGuy;

// HelloWorld implementation
@implementation HelloWorld

+(id) scene
{
  // 'scene' is an autorelease object.
  CCScene *scene = [CCScene node];

  // 'layer' is an autorelease object.
  HelloWorld *layer = [HelloWorld node];

  // add layer as a child to scene
  [scene addChild: layer];

  // return the scene
  return scene;
}

// set up the Menus
-(void) setUpMenus
{
// Create some menu items
  CCMenuItemImage * menuItem1 = [CCMenuItemImage itemFromNormalImage:@"myfirstbutton.png"
selectedImage:@"myfirstbutton_selected.png"
                     target:self
selector:@selector(doSomethingOne:)];
  CCMenuItemImage * menuItem2 = [CCMenuItemImage itemFromNormalImage:@"mysecondbutton.png"
selectedImage: @"mysecondbutton_selected.png"
target:self
selector:@selector(doSomethingTwo:)];

  CCMenuItemImage * menuItem3 = [CCMenuItemImage itemFromNormalImage:@"mythirdbutton.png"
                    selectedImage:@"mythirdbutton_selected.png"
                    target:self
                    selector:@selector(doSomethingThree:)];

  // Create a menu and add your menu items to it
  CCMenu * myMenu = [CCMenu menuWithItems:menuItem1, menuItem2, menuItem3, nil];

  // Arrange the menu items vertically
  [myMenu alignItemsVertically];
 
  // add the menu to your scene
  [self addChild:myMenu];
}

// on "init" you need to initialize your instance
-(id) init {
  // always call "super" init
  // Apple recommends to re-assign "self" with the "super" return value
  if( (self=[super init] )) {
    // create and initialize our seeker sprite, and add it to this layer
    seeker1 = [CCSprite spriteWithFile: @"seeker.png"];
    seeker1.position = ccp( 50, 100 );
    [self addChild:seeker1];

    // do the same for our cocos2d guy, reusing the app icon as its image
    cocosGuy = [CCSprite spriteWithFile: @"Icon.png"];
    cocosGuy.position = ccp( 200, 300 );
    [self addChild:cocosGuy];

    // schedule a repeating callback on every frame
    [self schedule:@selector(nextFrame:)];
    [self setUpMenus];

    // register to receive targeted touch events
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
  }
  return self;
}

// on "dealloc" you need to release all your retained objects
- (void) dealloc {
  // in case you have something to dealloc, do it in this method // in this particular example nothing needs to be released.
  // cocos2d will automatically release all the children (Label)
  // don't forget to call "super dealloc"
  [super dealloc];
}

- (void) nextFrame:(ccTime)dt {
  seeker1.position = ccp( seeker1.position.x + 100*dt, seeker1.position.y );
  if (seeker1.position.x > 480+32) {
    seeker1.position = ccp( -32, seeker1.position.y );
  }
}

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
  return YES;
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
  CGPoint location = [touch locationInView: [touch view]];
  CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];
  [cocosGuy stopAllActions];
  [cocosGuy runAction: [CCMoveTo actionWithDuration:1 position:convertedLocation]];
}

- (void) doSomethingOne: (CCMenuItem *) menuItem
{
NSLog(@"The first menu was called");
}
- (void) doSomethingTwo: (CCMenuItem *) menuItem
{
NSLog(@"The second menu was called");
}
- (void) doSomethingThree: (CCMenuItem *) menuItem
{
NSLog(@"The third menu was called");
}

@end


菜单项也可以使用block语法替代selector语法 

// Create some menu items
CCMenuItemLabel *mi1 = [CCMenuItemLabel itemWithLabel:someLabel block:^(id sender) {
  [theDirector pushScene:[SceneGame node];
} ]; 


你可以在这里找到Objective-C的blocks语法。Blocks语法帮助消除那些只使用一次的函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2d cocos2d iOS 游戏 翻译
相关文章推荐