陈亦飞微博:iPhone cocos2d游戏开发-2

来源:百度文库 编辑:九乡新闻网 时间:2024/04/27 23:26:53

上一篇文章分析了游戏的结构,并做了基本的文档工作。这一篇文章,将完成游戏菜单的创建和显示功能。

本篇文章对应的源代码下载:My_Flight_Control_2010-06-16.zip

添加游戏菜单

启动XCode,新建一个基于“cocos2d Application”模版的新应用。应用名称为“My Flight Control”,后续文章里面就称我们的山寨版Flight Control为MYFC,而原版则称为FC。新建的应用除了显示cocos2d的logo和一个hello,world外,什么功能也没有,我们就在此基础上逐步实现MYFC。

游戏菜单具备几个条目,例如“开始新游戏”、“查看积分榜”、“查看帮助信息”等。除非是极其简单的游戏,否则添加一个游戏菜单是很有必要的。MYFC的菜单很简单,只有“Start Game”和“Scores”两项。

虽然菜单很简单,但我们还是将菜单分为MenuScene和MenuLayer两个对象。MenuScene包含一个菜单背景图和MenuLayer对象。MenuLayer对象则显示菜单项目,并响应玩家对菜单项目的点击。

创建MenuScene和MenuLayer对象

在XCode中新建文件,并选择cocos2d模版“CCNode class”,Subclass则设定为“CCLayer”。文件名输入MenuScene。

新增的文件MenuScene.h和MenuScene.m会出现在Classes群组中:

接下来重复上述步骤,再建立一个MenuLayer对象。

显示菜单背景

iPhone的分辨率是480×320,所以我们要做一个同等尺寸的png图片作为菜单背景图。做好的图片名为MenuBackground.png,拖入XCode中的Resources群组即可。

注意:拖入Resources群组时,如果MenuBackground.png原本没有存放在MYFC的目录中,则导入时需要选中“Copy items into destination group’s folder(is needed)”选项。

有了资源,我们就可以进行编码了。

打开MenuScene.h文件,将:

@interface MenuScene : CCLayer

修改为:

@interface MenuScene : CCScene

然后再打开MenuScene.m文件,加入下面的代码:

view sourceprint?01.- (id) init02.{03.self = [super init];04.if (self) {05.// 取得屏幕大小06.CGSize winSize = [[CCDirector sharedDirector] winSize];07.// 将 MenuBackground.png 载入一个 CCSprite 对象实例08.CCSprite *bg = [CCSprite spriteWithFile:@"MenuBackground.png"];09.// 设定菜单背景的显示位置10.bg.position = ccp(winSize.width / 2, winSize.height / 2);11.// 将菜单背景添加到场景中12.[self addChild:bg];13.}14.return self;15.}

CCDirector是cocos2d里面很重要的一个对象。这个对象充当游戏流程控制者的角色,让开发者可以根据需要切换不同的场景。由于CCDirector是一个单子模式实现,所以调用 [CCDirector sharedDirector] 可以获得CCDirector对象的唯一实例。

CCDirector除了控制流程,还有其他一些功能。此处我们用 [winSize] 消息来获得当前屏幕的大小。

接下来,使用CCSprite载入MenuBackground.png图片,并将这个Sprite添加到MenuScene的显示列表(显示列表的概念请参考本文后面部分)中。当MenuScene刷新画面时,MenuBackground.png的内容就会出现在屏幕上。

由于cocos2d载入一个图片后,会将图片的中心点做为原点。所以为了将图片显示在屏幕中央,需要设定图片的position属性。

如上图,CCSprite的中心点默认在图片的中间。所以要将某个图片显示在屏幕中央,代码就是:

sprite.position = ccp(winSize.width / 2, winSize.height / 2);

PS:ccp()是cocos2d定义的一个宏,是CGPointMake()的简写形式。

载入图片并调整好位置后,[self addChild:bg] 将包含背景图的CCSprite对象添加到MenuScene的显示列表中。

测试菜单背景

在编写MenuLayer的代码之前,我们先用MenuScene替换掉默认的hello,world。

打开My_Flight_ControlAppDelegate.m文件,将

#import "HelloWorldScene.h";

替换为:

#import "MenuScene.h";

再找到 applicationDidFinishLaunching 方法最后的

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

替换为:

[[CCDirector sharedDirector] runWithScene: [MenuScene node]];

确认无误后,运行模拟器即可看到菜单背景图了:

显示菜单项

菜单背景显示出来后,就该实现菜单项的显示了。这部分工作在MenuLayer对象中完成。这里我们使用cocos2d提供的CCMenuItem和CCMenu辅助类。这两个类可以创建一些简单的菜单,完全可以满足我们目前的需求。

打开MenuLayer.h文件,增加如下代码:

view sourceprint?1.- (void) startGame: (id)sender;2.- (void) scores: (id)sender;

打开MenuLayer.m文件,增加如下代码:

view sourceprint?01.- (id) init02.{03.self = [super init];04.if (self) {05.// 设定菜单项字体06.[CCMenuItemFont setFontName:@"Helvetica"];07.[CCMenuItemFont setFontSize:30];08. 09.// 创建菜单项10.CCMenuItem *start = [CCMenuItemFont itemFromString:@"Start Game"11.target:self12.selector:@selector(startGame:)];13.CCMenuItem *scores = [CCMenuItemFont itemFromString:@"Scores"14.target:self15.selector:@selector(scores:)];16.// 创建菜单17.CCMenu *menu = [CCMenu menuWithItems:start, scores, nil];18.// 设定菜单项为垂直对齐19.[menu alignItemsVertically];20. 21.// 添加菜单到显示列表中22.[self addChild:menu];23.}24.return self;25.}26. 27.- (void) startGame: (id)sender {28.// 开始游戏29.}30. 31.- (void) scores: (id)sender {32.// 显示得分记录33.}

与添加背景一样的道理,最后需要把创建好的CCMenu对象添加到MenuLayer的显示列表中。

完成了对MenuLayer的修改,我们还要修改MenuScene对象,将MenuLayer包含的菜单项显示在背景之上。

打开MenuScene.m,在头部增加:

#import "MenuLayer.h"

修改init方法,在最后增加:

// 添加菜单层[self addChild:[MenuLayer node]];

最终MenuScene.m中init方法的代码为:

view sourceprint?01.- (id) init02.{03.self = [super init];04.if (self) {05.// 取得屏幕大小06.CGSize winSize = [[CCDirector sharedDirector] winSize];07.// 将 MenuBackground.png 载入一个 CCSprite 对象实例08.CCSprite *bg = [CCSprite spriteWithFile:@"MenuBackground.png"];09.// 设定菜单背景的显示位置10.bg.position = ccp(winSize.width / 2, winSize.height / 2);11.// 将菜单背景添加到场景中12.[self addChild:bg];13. 14.// 添加菜单层15.[self addChild:[MenuLayer node]];16.}17.return self;18.}

这时再编译运行,就可以看到菜单项了:

点击菜单项,还可以看到菜单项的放大缩小效果。

什么是显示列表?

虽然cocos2d没有明确提到“显示列表”这个概念,但实际上cocos2d是使用类似的技术来决定哪些对象应该显示在屏幕上。

在cocos2d中,所有出现在屏幕上的对象以一个树型结构来组织,例如MenuScene包含背景图和MenuLayer,而MenuLayer又包含几个菜单项目。这个树型结构中每一个节点都会维护一个列表。

例如MenuScene的显示列表中包含了背景图和MenuLayer对象。那么当MenuScene显示在屏幕上时,cocos2d就会把MenuScene显示列表中包含的对象也显示出来。如果MenuScene的显示列表中没有包含MenuLayer,则显示MenuScene时就不会显示MenuLayer对象。

当cocos2d刷新屏幕时,只有在显示列表中的对象会被绘制到屏幕上。因此如果我们有些对象不需要显示,则应该从显示列表中移除。

实质上,切换场景等操作就是对显示列表的调整。例如将场景从MenuScene切换为LeveScene,实际上就是从显示列表中移除MenuScene对象,再加入LevelScene对象。