Cocosbuilder使用教程

前端之家收集整理的这篇文章主要介绍了Cocosbuilder使用教程前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

转自:http://article.ityran.com/archives/2544

转自:http://article.ityran.com/archives/2544

手把手教你使用CocosBuilder一次性导出Cocos2d-html5,Cocos2d-x和Cocos2d-iPhone的游戏资源文件。这个游戏90%的工作量是用工具完成。

这篇教程将会展示如何使用 CocosBuildercocos2d-iphone制作游戏的动作,地图场景和界面。CocosBuilder 已经被Zynga 使用在游戏 Dream PetHouse Zynga Slots开发中。目前,由于若干游戏使用CocosBuilder,Zynga 索性将其开源出来(MIT License)。未来必定有更多的游戏在开发中使用该工具。
这篇文章是建立在你很熟悉object-c以及cocos2d-iphone或者cocos2d-x的基础上的。如果你希望学习cocos2d, 泰然也有很多文章推荐给你。
在开始本文之前,确保你下载并安装了CocosBuilder 的最新版(本教程基于2.1beta版本)并且升级cocos2d2.0或cocos2d-x的2.03版本以上。

The Game

我们将创造游戏主角 CocosDragon。CocosDragon有一对很小的翅膀因此他飞不高,所以我们需要让他触碰金币来给他加速上升直到碰到炸弹为止。你可以到youtube看这个游戏的视屏: youtube

本游戏可以在iOS模拟器上运行,游戏通过触摸来操作方向。假如你希望把这个游戏设计运用到你的产品中,我推荐你用重力感应来替换触摸方式。

设置工程

建立新的xcode工程。工程名称CocosDragon。

下载本教程需要用到的 美术资源,解压并加到工程中。
现在我们需要建立游戏相应的CocosBuilder 工程。打开CocosBuilder 选择 File -> New Project。命名为 CocosDragon 保存并把资源文件放到xcode的 Resources 文件夹(CocosBuilder的资源在一个名为 ccbResources的文件)打开the HelloCocosBuilder.ccb文件.我们不会使用HelloCocosBuilder 文件,所以你可以在CocosBuilder文件系统中干掉他。

创建动画类型的主界面

我们将开始制作Cocos Dragon所有的界面文件,然后将界面链接到相应的代码中。首先,我们创建一个主菜单
在CocosBuilder打开的CocosDragon 工程中选择 File->New File。我们将让主界面只支持iPhone,所以在resolutions settings(方案设置)中勾选iPhone Portrait ,并确保 root object type(根对象类型)为CCLayer 并勾选 full screen (全屏)。

点击创建,然后命名为“ MainMenuScene ”并且保存到 Resources 文件夹。一个新的空文件MainMenuScene.ccb将在CocosBuilder中开启。

主界面我们会包含一个渐变的背景,一个logo,一个开始游戏的按钮,和几片云彩的动画。首先,让我们开始加入渐变的背景。在窗口顶部的工具栏点击CCLayerGradient按钮。

我们希望渐变层(gradient layer)充满整个屏幕。选择这个层,设置填充(content size)大小单位为“%”并且设置宽高为100×100.

让我们把颜色修改为其他值以遍更适合我们游戏的主色调。点击开始颜色(start color)和完成颜色(end color)以至RGB值为下图显示这样。

继续添加logo到主界面(menu scene)。在左边的工程视图(project view)中,拖拽logo.png到canvas区域。你添加的图片就会像如下那样显示:

当启动主选单场景时会有漂亮的动画,但是我们还需要在启动时增加logo的动画。首先,点击canvas区域下面的时间设置来指定动画的长度。这里我们把动画出现的时间线设置为2秒。

现在,我们把logo视为一个精灵,并设置logo精灵的关键帧(keyframes)。拖拽时间戳到动画完成的地方(我们这个工程就是之前设置的00:02:00),并且确保logo已经被选定。在动画菜单中选择插入关键帧位置(Keyframe /Position),或者使用快捷键’P’.在时间线界面(timeline view),logo精灵会折叠并显示刚才添加的关键帧。

一旦关键帧插入时间线的节点中,我们节点的位置既可以自动添加新的关键帧。首先,移动时间戳到原点(00:00:00的位置)。然后,拖拽logo到绘图界面(canvas area)的顶部可见区域(你可以在拖拽的时候按住shift按钮以便对齐)。当你正在做以上操作时,一个新的关键帧就被自动添加到时间线的原点处,并且我们在两个关键帧中间生成平滑过渡的所有帧。

你可以点击Play来测试一下这个动画。你也可以移动时间戳来看看每个帧的位置。

这个动画我们完成的很漂亮并且每帧的过渡很平滑,但是让我们再加点料。在关键帧之间右击插值线(译者注:interpolation line,就是插入了过渡帧的地方)并且选择弹出(Bounce Out)。

OK,我们让logo被覆盖了,但是我们依然需要一个启动游戏的按钮。我们将用CCMenuCCMenuItemImage来实现这个功能。那么,开始添加菜单功能,在工具栏中点击CCMenu按钮。如下图:

一个CCMenu将会添加到你的文件中。CCMenu保持选中状态,在工具栏点击CCMenuItemImage按钮(在CCMenu按钮右边)。CCMenuItemImage会在可是换编辑区域左下角显示一个占位符图像。

拖动这个图片到屏幕中间,也可以使用Cmd+方向键或者 Cmd+shift+方向键来精准拖动,检视器(inspector)中输入需要的值。选中CCMenuItemImage,选择你希望菜单显示的其他图片样式。通常情况,未按下时我们使用图片名称“play-button.png”,按下时我们使用“play-button-down.png”。

我们现在又一个带logo和play按钮的选择菜单场景,但是这还是感觉有点空荡荡的。所以我们加入一些云彩来充实一下。在工程界面,拖拽一些云 彩到可视化区域。你可以拖拽图片的边角来改变云彩的大小。要改变云彩的遮盖(z-order)可以在时间线区域将相应的时间线拖到上面或者下面,当然也可 以在对象选项中(Objectmenu)选择Arrange / Bring放到上层,选择Arrange / Send放到下层。

现在让我们添加云彩的介绍动画。这就像之前logo精灵那样做就好。把时间戳移动到动画的末尾。给每个云彩和play按钮添加一个关键帧。你可以选 中每个云彩然后点击快捷键‘p’。当关键帧已经被添加到所有对象的动画末尾后,把时间戳移动到动画开头。现在拖拽每个云彩,让底部

点击‘Play’来测试动画。我们现在有一个很漂亮的主菜单介绍动画。当动画播放完毕后,整个场景就是完全禁止的。这不是很好,所以后面我们还会完善。

CocosBuilder提供了多个时间线。在文件中,多个时间线可以连续或者不连续播放,也可以通过代码控制回放。两个不同动画的时间线可以实现平滑过渡。我们这个工程会实现多个时间线,当介绍动画的时间线播放完成后,会循环播放另一个动画。

在动画菜单选择编辑时间线(Edit Timelines)。在弹出框中,先将默认的时间线重命名为Intro。然后点击plus-sign添加一条时间线并命名为Loop,点击完成。

我们选择要编辑的时间线,点击drop-down按钮(图上已经标出),选中Timelines->Loop。

现在我们有一条未添加关键帧的时间线。这条时间线默认是10秒钟,我们的工程刚好就要这么长。为了方便看出完成后的长度,你可以拖动比例条(scale slider)到左边。

虽然只是一个很小的动画,但可以给场景带来生机。选择一片云彩。将时间戳拖到起点,点击快捷键’s'。这将会给比例属性添加一个关键帧。现在把时间 戳拖动到时间线末尾并再次点击快捷键‘s’。这将会在动画末尾添加一个关键帧。注意,这条线表示插入的view将会轻微淡出。这是因为两个关键帧是完全一 样的,所以没有动画产生。现在这个情况就已经不错了,因为我们希望动画的首尾相同,以便重复播放。

按住option键点击两个关键帧中间,就在时间线的开头和结尾之间添加一个新的关键帧。点击这个新建的关键帧让它出于选中状态,通过调整比例值,或者拖动云彩,让云彩稍微变大一点。

回放动画,你可以看到一片云彩慢慢变大,然后再变回原始大小。让我们给每片云彩做相同的操作。点击所有的关键帧让选择框包含他们。你也可以用shift来选中。选中后,在Edit菜单选择 复制。把时间戳移动到时间线原点,选择另一片云彩点击粘贴。并重复在所有云彩中操作(并没有添加关键帧)。

再次回放动画。你可以看到所有的云彩都按比例做放大缩小动作了,但是他们是在同时放大缩小,这很古怪,不是吗?点击每片云彩,延伸时间线,并移动中间那个关键帧的位置。这样就会让云彩在不同时间播放动画了。多试几次你就会有经验调整到合适的长度了。

最后,我们要让动画在我们需要的时候自动循环,就要用到链式时间线功能(chain timeline)。点击时间线编辑器左下角的文本,这里显示没有链式时间线。弹出框中点击 循环(loop)。这就会让动画自动循环了。

现在回到介绍动画的时间线(点击时间线drop-down菜单,选择Timelines -> Intro)。在Intro右边完成的地方链接Loop时间线。当我们用代码调用这个场景时,会自动播放Intro动画,Intro完成后回循环播放Loop动画。

主菜单的大部分已经完成,我们剩下的仅仅是在代码中调用这个界面。要调用这个场景,我们要给根节点设置一个定制类。选择根节点(在文件document的CCLayer中)。设置类名为“MainMenuScene”。我们会在稍后在代码中创建MainMenuScene。

选择Play按钮。进入CCMenuItem下的pressedPlay:进入选择器的输入框,选择目标“Document root”。当我们点击按钮pressedPlay:文件根节点方法(MainMenuScene)就会被调用。

游戏场景

我们使用游戏场景来载入在实际游戏中需要的所有东西。同时它也用来显示分数。在file菜单中选择New File并选择和你MainMenuScene中选择的相同的选项(CCLayer,full screen,iPhone portrait),命名文件为GameScene并保存在文件夹。

对于这个游戏来说,我们会使用和菜单场景一样的背景梯度。或是再创建一遍,或是通过双击项目视图的MainMenuScene,选择CCLayerGradient,复制黏贴到你的新文件处。

点击工具栏上的CCLayer图标来给场景加一个层。稍后在代码中我们会使用这个空的层来加载一个关卡。

添加后,我们添加一个label用来显示当前游戏的分数。点击工具栏上的CCLabelTTF标签

如图所示,把位置设成(160,40),字体设置成oSystem Fonts / MarkerFelt-Wide,字号大小24,尺寸设成100*40,校准设成center,最后把文字设成“0”

这个游戏场景已经差不多完工了,唯一还差的就是和代码的连接。选择根节点并且设置自定义类为GameScene。然后选择文本标签,我们将要指派这个标签作为根节点类的一个成员变量。将左侧的下拉菜单中选择为Doc root var,并且设置那个变量的名字为scoreLabel。

我们也需要连接刚才创建的那个空层到代码。处理步骤同上并将变量明设为levelLayer。

现在我们已经完成这个游戏场景啦。让我们继续创建一些游戏对象。

增加游戏物体

我们这个游戏会用到4种游戏物体。游戏的主角:龙,以及钱币,炸弹,和爆炸效果。所有游戏物体都是我们稍后创建的GameObject类的子类。GameObject类是CCNode的一个子类。因此,CocosBuilder创建的游戏中的所有对象都继承自CCNode。(当然还有可能作为GameObject的插件程序存在,但是在本游戏中,我们并需要使用)。

让我们开始创建游戏中最复杂的物体—龙。在File菜单中选取New File,创建一个新文件。选择根节点对象为CCNode,反选全屏选项(full screen),选择分辨率选项为iphone。

选择根节点并设置自定义类为Dragon。

龙由几个不同的移动部件组成:身体和2个翅膀。首先我们先加入翅膀这样他们就会出现在身体的后面。在项目视图拖动gameobjects.plist/dragon-wing.png到画布区域。设置翅膀的位置为(-8,4),另一个锚点设为(0.84,0.094).

然后,增加身体部分。拖动gameobjects.plist/dragon-body.png到画布区域。设置身体的位置为(0,0)。你的文件看起来就会是这样:

我们将龙的单个翅膀做动画,然后复制翅膀并翻转成一对做动画的翅膀。首先,设置时间轴长度为1秒。然后,选择翅膀,将时 间轴标记(timeline)移到开始处并按R键来增加一帧,以做翻转。将时间轴(timeline)标记移动到结束处,再增加一帧翻转。现在移动到中部 (00:00:15)。朝下旋转翅膀—-你可以通过按住option键,并拖曳其中一个选择选择点来快捷旋转它。旋转这个翅膀差不多80度左右。

我们现在有了扑腾的翅膀啦,但是通过增加Bounce Out缓冲,我们可以让它显示的更加自然。在第一帧和中间帧之间右键,选择Bounce Out.。在中间那帧和最后一帧也做同样的设置。

现在来创建另外一只翅膀。首先确保没有帧被选中,然后选择翅膀。在edit菜单中选择Copy,并Paste.第二个翅膀就被复制到龙的身体前面了,因此我们需要使用Object菜单中的Arrange /Send Backward选项请 确保新的翅膀在检查器中FilpX选项有被选中。这只会翻转图像,我们同意需要设置它的位置和锚点,设置位置为(8,4),锚点 (0.16,0.094)。这个翅膀的动画现在看起来不错了,但是选择的方向是错的。双击中间的那一帧来锁定它。你可以改变检查器(inspector) 中的旋转角度(大概80度左右)。继续播放动画,这时候,龙的两只翅膀应该都正常了。

在游戏中,我们的小龙会在碰到炸弹的时候停止扑腾它的翅膀。当撞到炸弹的时候,我们会播放另一个剪短的动画,然后再扑腾翅膀。因此我们需要2个时间轴。选择Animation菜单的ChooseEdit Timelines…。重命名当前的时间轴为Flying,增加一个新的时间轴为Hit,然后点击Done

我们希望飞行的时间轴循环播放,所有点击No chained timeline并选择Flying。然后切换到新创建的Hit时间轴。设置它的长度为2秒并和Flying连接起来。当龙被击中时候,我们播放hit动画,播放完成后它自动继续Flying动画。

剩下还有要做的就是创建一个龙被击中的动画。移动时间轴的标记到末尾,选择每个翅膀并按R来增加旋转动画。现在移动标记到开头。将每个翅膀旋转向下,我分别设置了-123和123的值。为每个翅膀增加一个Bounce Out属性。

选择龙的身体部分,移动时间轴标记到00:00:15.处。按F来增加一帧。现在,移动标记到开头处并按F增加一个精灵帧。在检查器(inspector)中,设置精灵框为frametogameobjects.plist/dragon-body-hit.png。点击play按钮来试试hit动画怎么样。

Bomb

炸弹

在街机游戏中怎么可能会少了坏人?我们需要一些很酷的炸弹~创建一个新文件就像dragon文件一样(选项也一样)。命名文件为Bomb并保存。选择根节点并设置自定义类为Bomb。

我们现在要为我们的炸弹增加一些旋转的钉子。设置时间轴长度为2s。拖曳gameobjects.plist-bomb-spikes.png到画布处并设置位置为(0,0),同样的拖曳thegameobjects.plist/bomb-body.png。炸弹身体会在尖刺的上方。

为了让炸弹看起来更邪恶一点,我们需要让钉子旋转。选择钉子精灵并移动时间轴标记至初始部分。按R来增加一帧旋转的关键帧。通过移动时间轴标记到末尾增加一个关键帧(按R键)并设置精灵的旋转角度是360度。播放动画,我们可以看到钉子绕着身体旋转了。

最后,请确保时间轴自动的循环播放,你可以动过点击No chained timelinetext并选择Default的时间轴。


Coin

硬币

在我们的游戏中我们会看到2种硬币,普通硬币和结束硬币。吃了普通硬盘会给与我们的龙一个短暂的加速,吃了结束硬币会结束当前关卡。我们可以使用相同的类对于这2种硬币,但是在其中加一个额外的属性以方便我们在代码中区分他们。

用和dragon,bomb文件一样的设置创建一个新文件。命名为Coin,设置自定义类为Coin。

拖曳gameobjects.plist/coin01.png到画布区并设置位置为(0,0)。现在我们想要增加一帧基于硬币的动画,设置时间轴的长度为00:01:06.确保时间轴标记在最前面而且硬币精灵被选中。现在选择项目视图中的coin01.png到coin18.png。

选择Animation菜单中的Create Frames from Selected Resources按钮。你将为硬币精灵添加一系列的关键帧。动画起了作用,但是好像稍微太快了点。拖动选择框包围他们来选择所有的关键帧,然后,选择Animation菜单中的Stretch Selected Keyframes按钮。设置拉伸率(stretch)为2.0并点击Done。这时关键帧时间被隔开,动画看起来就更慢了。

对于炸弹,通过设置默认的时间轴,完成这个文件,并保存。

现在我们开始创建“结束硬币”。打开Finder,复制Coin.ccb文件,并重命名为EndCoin.ccb。切回到CocosBuilder,双击项目视图来新建一个文件。为了区别这2种硬币,我们需要在根节点增加一个自定义的属性。选择根节点并点击检查器中的Edit Custom Properties。创建一个新的属性,命名为isEndCoin,设置种类为Bool并设置值为1.点击Done、

当文件在我们的app中载入的时候,这个自定义属性就会被设置进自定义的类里。为了使这个旋转的硬币视觉上有别于普通的硬币。选择硬币,并点击color well来弹出颜色选取器,设置如下所示的颜色,这样,我们就完成了2个不同的硬币。

Explosion

爆炸

当炸弹爆炸的时候,我们需要一些花哨的爆炸效果。我们可以使用粒子系统。每一个爆炸由2个粒子系统构成。

首先创建一个新文件,设置都同前面创建龙、炸弹和硬币的一样并命名文件为Explosion。设置时间轴长度为2秒,并定义根节点的自定义类名为Explosion。点击工具栏的粒子系统的图标2次,来增加2个粒子系统的文件。

两个粒子系统的参数设置如下图所示。如果想看一下效果,你可以点击检查器中的Start Particles按钮。

Creating a Level

创建一个关卡


我们完成了我们所有的游戏物体。唯一还没做的界面就是关卡地图了。创建一个新文件,请确保根节点中CCLayer和full screen的选项被选择,选择iPhone Portrait的分辨率,但是设置高度为4096.

将其保存为Level文件。设置根节点的自定义类名为Level。我们现在有一个很大的文件来放置我们这些游戏物体。首先先增加龙吧。将项目视图中的Dragon.ccb拖曳到画布区域。选择龙并设置位置为(160,40),如果你移动了龙,你可能需要滚动画布区域才能看到龙。我们需要向下滚动可视化编辑器,以便你在移动进入前能看到我们添加的龙。我们希望能够简便地在代码中加入龙,所以在下拉菜单总的代码连接选项(Code Connections)中选择Doc root var

现在,从项目视图中拖曳并放置更多游戏物体。在我这种情况下,第一关看起来像这样:

在关卡的顶部放置一个“结束硬币”。当龙接触到“接触硬币”的时候,关卡结束。当你很高兴的布局你的关卡的时候,请确保所有打开的文件要保存。现在,选择File菜单中的Publish按钮。这将会把你的文件打包成一个非常紧凑的二进制格式文件。

游戏编码

现在我们已经为游戏创建好了所有接口文件,下一步开始编码。

用Xcode打开项目,右键单击Resources文件夹并选择Add Files to “CocosDragon”…….确保“Create groups for any added folders”单选框被选中,并且“CocosDragontarget”也被选中。将所有的图片文件添加到资源目录下,包括plist文件 (sprite sheets)和所有ccbi文件。你不必添加以ccb为扩展名的文件进来,因为他们只在CocosBuilder下使用。

下一步,我们要添加CCBReader到项目下。CCBReader在示例代码的文件夹下。将他添加到“你项目 /cocos2d-iphone”。将CCBReader文件夹添加到你项目之后,确认Create groups for any added folders被选中,并且Copy items into destination group’s folder被选中。

Xcode下,打开Prefix.pch文件,它在Supporting Files组下。引入头文件的代码如下:

#ifdef __OBJC__ #import #import #import “cocos2d.h” #endif

MainMenuScene

我们现在开始编码。让我们一起创建一个主菜单(main menu)!选择File菜单下的New/File。选择Objective-C class,命名该类为MainMenuScene并设定该类为CCLayer的子类。

在MainMenuScene.m的最上部importCCBReader.h。我们也将实现play按钮的回调函数,这个play按钮是我们在ccb文件中加入的。在实现文件中(*.m)中加入如下代码:

- (void) pressedPlay:(id)sender

{

// Load the game scene

CCScene* gameScene = [CCBReader sceneWithNodeGraphFromFile:@"GameScene.ccbi"];

// Go to the game scene

[[CCDirector sharedDirector] replaceScene:gameScene];

}

当我们按下play按钮,我们将第一次通过ccbi文件加载游戏场景。然后通知CCDirector去用游戏场景 replace掉当前的场景。这部分的代码我们需要写到MainMenuScene里,而且需要在游戏开始时候加载。打开AppDelegate.m文 件,引入CCBReader.h,然后用下面的代码替换既存的引入初始场景的代码:

// Load the main menu scene from the ccbi-file

CCScene* mainScene = [CCBReader sceneWithNodeGraphFromFile:@"MainMenuScene.ccbi"];

// Then add the scene to the stack. The director will run it when it automatically when the view is displayed.

[director_ pushScene: mainScene];

然后,还是在AppDelegate.m文件,用如下代码替换shouldAutorotateToInterfaceOrientation:方法:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

return UIInterfaceOrientationIsPortrait(interfaceOrientation);

这将确保我们的游戏以竖屏模式运行。你可以在github上找到源文件:

MainMenuScene.m

MainMenuScene.h

AppDelegate.m

GameScene

当我们按下play按钮之后,GameScene.ccbi文件将会被加载,并创建GameScene的实例。现在我们需要创建GameScene类。创建一个新类命名为GameScene,让其继承自CCLayer。

在CocosBuilder里,我们添加了两个成员变量(levelLayer和scoreLabel)。我们需要添加它们到文件中去。并且也需要加载等级(Level)以及动态的记录当前的分数。在GameScene.h添加前面提到的两个成员变量:

@interface GameScene : CCLayer

CCLayer* levelLayer;

CCLabelTTF* scoreLabel;

CCNode* level;

int score;

为了从别的类里更好的管理分数,我们将在GameScene类里增加一个属性。我们也将增加方法去管理游戏结束以及升级的情况。

@property (nonatomic,assign) int score;

+ (GameScene*) sharedScene;

- (void) handleGameOver;

- (void) handleLevelComplete;

@end

下面我们来实现GameScene类的方法。打开GameScene.m。在头部importCCBReader.h。在开始实现该类之前,先定义一个静态变量以方便共享该类的实例。

staticGameScene* sharedScene;

在该类的类方法中返回这个共享实例。

+ (GameScene*) sharedScene

return sharedScene;

我也需要去synthesize这个分数属性

@synthesize score;

当一个ccbi文件被加载的时候,CCBReader将会调用创建每个节点的方法didLoadFromCCB。通过实现该方法,你将在文件加载完毕的时候收到一个回调函数。我们将会利用回调信息去设置当前场景以及加载等级。

- (void) didLoadFromCCB

// Save a reference to the currently used instance of GameScene

sharedScene = self;

self.score = 0;

// Load the level

level = [CCBReader nodeGraphFromFile:@"Level.ccbi"];

// And add it to the game scene

[levelLayer addChild:level];

这部分代码加载Level.ccbi文件并且将其作为一个子节点加到我们在CocosBuilder里创建的levelLayer上。在真实的游戏当中我们可能会有不止一个的等级文件,并且对应玩家在游戏中的进度选择不同的文件

当分数属性改变时,我们希望更新label上分数的显示。我们通过setscore:方法来实现。记住我们已经在CocosBuilder定义了scoreLabel。

- (void) setscore:(int)s

score = s;

[scoreLabel setString:[NSString stringWithFormat:@"%d",s]];

离开GameScene之前的最后一步是为控制游戏结束以及升级编码。在实际游戏中你可能做更多的事情在这些方法中,但是在该例子中,我们只是简单的返回主菜单场景。

- (void) handleGameOver

[[CCDirector sharedDirector] replaceScene:[CCBReader sceneWithNodeGraphFromFile:@"MainMenuScene.ccbi"]];

- (void) handleLevelComplete

你可以在github找到源码

GameScene.m

GameScene.h

GameObject

GameObject是一个抽象类,它是所有游戏对象的父类。他让我们可以等同对待所有的游戏对象。创建一个CCNode的子类,命名为GameObject。这个类包含一些基础属性的设置以及一些基础的方法,以便我们在游戏当中控制游戏对象。如果我们想移除一个对象那么可以设置isScheduledForRemove属性。这个更新方法会在每个框架更新游戏对象状态的时候调用一次。我们将在检测冲突的时候(在我们的游戏当中每一个游戏对象都视为圆形)使用radius属性。最后,如果两个游戏对象发生碰撞,两个发生碰撞的游戏对象的handleCollisionWith:方法将被调用。下面就是头文件的定义代码

@interface GameObject : CCNode

BOOL isScheduledForRemove;

- (void) update;

- (void) handleCollisionWith:(GameObject*)gameObject;

这个.m文件只是实现了一个空方法,因为他是一个抽象类。

@implementation GameObject

@synthesize isScheduledForRemove;

// Update is called for every game object once every frame

- (void) update

{}

// If this game object has collided with another game object this method is called

- (void) handleCollisionWith:(GameObject *)gameObject

// Returns the radius of this game object

- (float) radius

{return 0;

源码参见以下文件链接

GameObject.m

GameObject.h

Dragon

龙是我们游戏中最复杂的游戏对象。它控制着玩家将要控制的这个角色的行为,同时这也是游戏的主要行为。创建一个GameObject的子类命名为Dragon。

为了控制龙的运动,我们需要两个变量,纵向速度ySpeed,以及横向目标xTarget。xTarget将会在点击iPhone上的打击目标的时候被设置。之后变量将会被外部类设定,我们将会将他作为一个属性。下面是我们需要添加的头文件

@interface Dragon : GameObject

float ySpeed;

float xTarget;

.m文件将会更加有趣。首先,我们会整合一些其他的类进来,我们来引入他们。(我们将会在完成Dragon类之后,编写Coin和Bomb类)

#import “Dragon.h”

#import “Coin.h”

#import “Bomb.h”

#import “GameScene.h”

#import “CCBAnimationManager.h”

下面,我们来定义几个常量来方便对龙的行为的控制。使用常量是一个非常不错的选择,因为这样很方便我们去从感官上控制游戏。

#define kCJStartSpeed 8

#define kCJCoinSpeed 8

#define kCJStartTarget 160

#define kCJTargetFilterFactor 0.05

#define kCJSlowDownFactor 0.995

#define kCJGravitySpeed 0.1

#define kCJGameOverSpeed -10

#define kCJDeltaToRotationFactor5

实现Dragon类的第一步,我们需要synthesize属性xTarget。

@synthesize xTarget;

然后来到init方法,在这里我们将初始化我们的成员变量。xTarget的初始值为160,位于屏幕中心。

- (id) init

self = [super init];

if (!self) return NULL;

xTarget = kCJStartTarget;

ySpeed = kCJStartSpeed;

return self;

我们将使用update方法让龙在屏幕上平滑的移动。在每个frame下,update方法会被调用一次。我们将利用一 个计算原始点和目标点之间距离的过滤器方法来获得一个新的X坐标。我所说的目标点就是玩家在屏幕上触摸的点。Y坐标则是在原始坐标的基础上增加现有速度来 计算得出的。之后我们更新速度,我们不但可以通过增加常量的方式加快速度,也可以利用参数减慢速度(这将防止龙的攻击速度过快)。我们同时依靠水平速度翘 起龙的一侧。如果纵向速度向下过快,那么游戏结束。

// Calculate new position

CGPoint oldPosition = self.position;

float xNew = xTarget * kCJTargetFilterFactor + oldPosition.x * (1-kCJTargetFilterFactor);

float yNew = oldPosition.y + ySpeed;self.position = ccp(xNew,yNew);

// Update the vertical speed

ySpeed = (ySpeed – kCJGravitySpeed) * kCJSlowDownFactor;

// Tilt the dragon depending on horizontal speed

float xDelta = xNew – oldPosition.x;

self.rotation = xDelta * kCJDeltaToRotationFactor;

// Check for game over

if (ySpeed < kCJGameOverSpeed)

{

[[GameScene sharedScene] handleGameOver];

}

在Dragon类里我们也需要去控制碰撞。我们将通过判断是碰撞了哪种对象来相应的做出动作。如果碰到了钱币,我们增加 分数并且给龙一个向上增长的速度。如果我们碰到了炸弹,龙会降低速度并且播放在CocosBuilder里面制作的Hit动画。我们在 userObject里用CCBReader保存的CCBAnimationManager,之后调用 runAnimationsForSequenceNamed:方法

if ([gameObject isKindOfClass:[Coin class]])

// Took a coin

ySpeed = kCJCoinSpeed;

[GameScene sharedScene].score += 1;

else if ([gameObject isKindOfClass:[Bomb class]])

// Hit a bomb

if (ySpeed > 0) ySpeed = 0;

CCBAnimationManager* animationManager = self.userObject;

NSLog(@”animationManager: %@”,animationManager);

[animationManager runAnimationsForSequenceNamed:@"Hit"];

最后我们要实现radius(半径)属性。它将用于控制碰撞。

return 25;

完整的Dragon类,请参见:

Dragon.m

Dragon.h

Coin

金币有一个相当简单的逻辑,金币在碰到龙的时候会被移除。如果最后一枚金币碰撞到了龙,该等级的任务完成。创建一个名为 Coin的类,他是GameObject的子类。在CocosBuilder我们增加了一些自定义属性,isEndCoin是专门针对最后一枚金币的, 普通金币也使用相同的自定义类。我们需要实现这个属性在我们的类里,下文是头部文件

@interface Coin : GameObject

BOOL isEndCoin;

.m文件,我们首先要synthesize属性isEndCoin。

@synthesize isEndCoin;

我们不必移动金币,所以我们不用实现update方法。但是,当背龙碰撞的时候我们想移除它。并且,如果是最后一枚金币的话,我们想升级

if ([gameObject isKindOfClass:[Dragon class]])

if (isEndCoin)

// Level is complete!

[[GameScene sharedScene] handleLevelComplete];

self.isScheduledForRemove = YES;

最后,让我们来设定金币的半径。

return 15;

完整的代码,参见下方:

Coin.m

Coin.h

Bomb

炸弹是我们游戏当中的一个障碍物。创建名为Bomb的类,他是GameObject的子类。当炸弹碰撞到玩家的时候,它 会爆炸。这个效果是通过移除炸弹并且动态的加载爆炸效果来实现的。我们没有添加任何新的属性进来,所以头文件不需要修改。在.m文件中,我们需要实现 handleCollisionsWith:方法

// Collided with the dragon,remove object and add an explosion instead

CCNode* explosion = [CCBReader nodeGraphFromFile:@"Explosion.ccbi"];

explosion.position = self.position;

[self.parent addChild:explosion];

之后,我们需要设定炸弹的半径。

完整的代码,如下:

Bomb.m

Bomb.h

Explosion

最后一个游戏对象,我们将会实现爆炸(Explosion)。爆炸不会影响其他的任何游戏对象。但是我们会在它完成播放 之后移除调它。为此我们必须实现CCBAnimationManagerDelegate。在头文件,首先引入 CCBAnimationManagerDelegate.h,然后将其作为一个协议加进到Explosion。

@interface Explosion : GameObject

.m文件,我们将分配Explosion类作为CCBActionManager的代理,这步的创建将发生在爆炸加载的时候。我们将在didLoadFromCCB:方法来实现这步。

// Setup a delegate method for the animationManager of the explosion

animationManager.delegate = self;

至此,当动画播放完毕我们将收到回调函数completedAnimationSequenceNamed:,实现该回调并增加一个移除爆炸的定时器。

- (void) completedAnimationSequenceNamed:(NSString *)name

// Remove the explosion object after the animation has finished

完整的代码见下方:

Explosion.m

Explosion.h

Level

我们就还剩一个Level类没有完成。Level将会控制所有的玩家输入,并且负责更新和移除我们的游戏对象。创建名为Level的类,它是CCLayer的子类。在CocosBuilder里,我们添加了一个成员变量dragon,所以我们要把它加到头文件

@class Dragon;@interface Level : CCLayer

Dragon* dragon;

.m文件,我们将引入计划访问的类。

#import “GameObject.h”

我们也将定义两个常量用于层的滚动。因为龙需要是一直可见的。

#define kCJScrollFilterFactor 0.1

#define kCJDragonTargetOffset 80

我们使用onEnter方法,在每个frame之前,去提供一个回调函数update:。在onExit我们移除这个回调。

- (void) onEnter

[super onEnter];

// Schedule a selector that is called every frame

[self schedule:@selector(update:)];

// Make sure touches are enabled

self.isTouchEnabled = YES;

- (void) onExit

[super onExit];

// Remove the scheduled selector

[self unscheduleAllSelectors];

在update:方法我们将更新所有游戏对象。记住,在CocosBuilder里我们增加的游戏对象都是level的 子对象。之后,游戏对象更新以及发生位置改变的时候我们将检测是否有碰撞。在这个游戏里我们只检测与龙之间的碰撞,因为只有他是移动的。在其他的游戏里, 你可能需要写更多更复杂的代码去检测碰撞,或者有可能用到诸如Chipmunk,Box2d的物理引擎。因为所有的碰撞都是可控的,我们将会遍历游戏的所 有对象去看哪些对象被定时移除了。我们为这些对象创建一个数组,使用这个队列来移除他们。最后,我们调整层的位置,所以龙总是可见的。当调整位置的时候我 们使用过滤器代理去确保移动的平滑。

- (void) update:(ccTime)delta

// Iterate through all objects in the level layer

CCNode* child;

CCARRAY_FOREACH(self.children,child)

// Check if the child is a game object

if ([child isKindOfClass:[GameObject class]])

GameObject* gameObject = (GameObject*)child;

// Update all game objects

[gameObject update];

// Check for collisions with dragon

if (gameObject != dragon)

if (ccpDistance(gameObject.position,dragon.position) < gameObject.radius + dragon.radius)

// Notify the game objects that they have collided

[gameObject handleCollisionWith:dragon];

[dragon handleCollisionWith:gameObject];

// Check for objects to remove

NSMutableArray* gameObjectsToRemove = [NSMutableArray array];

if (gameObject.isScheduledForRemove)

[gameObjectsToRemove addObject:gameObject];

for (GameObject* gameObject in gameObjectsToRemove)

[self removeChild:gameObject cleanup:YES];

// Adjust the position of the layer so dragon is visible

float yTarget = kCJDragonTargetOffset – dragon.position.y;

CGPoint oldLayerPosition = self.position;

float xNew = oldLayerPosition.x;

float yNew = yTarget * kCJScrollFilterFactor + oldLayerPosition.y * (1.0f – kCJScrollFilterFactor);

self.position = ccp(xNew,229)"> 最后我们需要去做些事情来响应玩家的触摸。我们实现了ccTouchesBegan:withEvent:和ccTouchesMoved:withEvent:方法获取触摸位置,以及设定龙的xTarget属性

- (void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

UITouch* touch = [touches anyObject];

CGPoint touchLocation = [touch locationInView: [touch view]];

dragon.xTarget = touchLocation.x;

- (void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

完整的代码请参见:

Level.m

Level.h

总结

用所有的CocosBuilder文件为游戏创建的类,你应该可以在虚拟机或者真机上编译运行。很感谢花时间读这个教程,祝你编码愉快!

原文链接:https://www.f2er.com/cocos2dx/347098.html

猜你在找的Cocos2d-x相关文章