cocos2d-x萌新指南(一)——制作主界面:图片、按钮

DinS          Written on 2016/4/26

第一话:启程

“当人生的中途,我迷失在一个黑暗的森林之中……”

——《神曲》 地狱篇1:1-3

第零话我们简要学习了基础知识,从第一话开始正式启程。题图就是我们要制作的主界面,同时欢迎各位下载我制作的这个app,方便学习时查看效果。

(注:现在在市面上应该已经看不到这个app了,可以在本站的Game专区找到这款app)

进入正题,上一话我们了解了HelloWorldScene.h声明了一个HelloWorld场景类,然后在.cpp中进行实现,而AppDelegate负责调用该场景类中创建场景的函数createScene(),最终得到了运行效果。现在我们要对HelloWorldScene.cpp进行魔改。

先来看Scene* HelloWorld::createScene(){}这个函数,对于这个函数没什么能动的,其作用就是生成一个场景,而具体的场景是什么样子的则在函数bool HelloWorld::init(){}中完成,Init即initial的意思,翻译过来为初始化,我们把注意力集中到这个初始化函数上去。

Cocos2d-x的制作方很用心,在这个示例中已经替我们把初始化函数分成了3个部分,用注释的方式分隔,首先来看第一部分,具体代码见下:

很简短就5行,前3行if{}不必管,后两行当时可把我整得不行不行的,一直不知道怎么解释, 后来大胆尝试发现可以直接删了,用另一种方式摆放对象, 这里暂时先留着不动。解释一下c++里如何创建变量并初始化,语法可以概括为:

关键词 变量名称 = ……;

例如int a = 10;这句代码就创建了一个类型为整型的变量a,其值是10。int表示整型,是一个c++内置类型,用于存放整数。以上两句代码创建了一个类型为Size的变量visibleSize和一个类型为Vec2的变量origin,并进行了初始化。Size和Vec2都是cocos2d-x定义的类型。这么说还是很玄乎,继续往下走就能明白这两个变量的功能了。

直接进入第三部分,看代码:

注意红框和蓝框圈出的变量,这一部分定义了两个变量label和sprite,并对这两个变量进行了一系列操作。关键字auto是c++的一个特性,可以自动推断声明类型,这样就不用写int/Vec2/Size之类的,全部用auto代替即可。这两个变量的声明句型都很相似,区别在于label后面使用了LabelTTF::,而sprite使用了Sprite::,如果还记得上一话中讲解HelloWorld::就应该明白这些都是类,又遇到了类,不过目前对于咱们来说只要会使就可以了。LabelTTF::表明创建了一个Label类,而Sprite::表明创建了一个精灵类。后面都是create(),里面的“”不同,参数个数也不同。

分析了这么半天赶紧动手改一改,进入Example文件夹里的Resource文件夹会发现如下情况:

里面有一张图,其名字刚好是Sprite::create(“…”)里面的名字,而图片的样子刚好是运行成功的界面,如此说来Sprite::create(“”)的作用就是将resource文件夹里面的一张图加入场景。那么完全可以找一张图,然后把create(“”)里面的名字改成新图的名字,经过测试如下图:

是不是很简单的感觉?本来就不难嘛! 不过记住要加.png,不然报错。那么后面一句:

sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

是什么意思?从setPosition的名字可以看出是把sprite这个对象放置到一个位置,具体的位置就是()里面的内容。这里出现了visibleSize和origin这两个第一部分定义的变量,然而非常费解,并不直观。还记得在AppDelegate中定义的固定分辨率吗?没错,960X640,其实这里完全可以这么写

sprite->setPosition(480,320);

这两句在上述前提下是等价的。这里来说说cocos2d-x处理图片的一个方法。每张图片都有一个锚点(anchor),锚点默认是图片的中心,Main.png这张图是960X640,那么其中心就是(480,320)这个点。Cocos2d-x在处理图片位置时以锚点作为操作对象,所以sprite->setPosition(480,320)这句话的语义是将sprite的锚点放到(480,320)这个点。又因为在cocos2d-x中坐标系原点在左下角,因此(480,320)这个点就是屏幕中心,于是Main.png这张图就被放置到了屏幕中心。

补充一下->运算符,暂时理解为让sprite执行setPosition这个行动。

还剩下最后一句this->addChild(sprite, 0);什么意思?还记得使用Word放置图片时有置于顶层、置于底层吗?就是这个意思,这句代码决定了图片的显示层次,高层遮挡低层的图片。

总结一下图片基础代码:(加下划线的自行确定具体内容)

auto pic = Sprite::create(“picname.png”);

pic -> setPosition(x , y);

this -> addChild(pic, 0);

于是本例中有关图片的三句代码的作用是:1.使用Main.png创建了一个叫做sprite的精灵(放置图片的容器);2.将sprite置于屏幕中心;3.将sprite置于底层。很简洁地完成了任务,label同理。看到这里你已经掌握了如何将图片加入程序之中。


接下来研究一下稍微复杂一点的按钮。看看初始化函数的第二部分:

按钮的创建与sprite/label大同小异,本质性区别已经用红线画出来了。按钮被按下后要执行一个效果,这就需要函数来完成,这里就是为closeItem按钮绑定了一个函数,而这个函数就是HelloWorld类里声明的menuCloseCallback函数。这个函数的具体实现就不解释了,就是一个关闭程序效果,重要的是体会按钮绑定函数的过程,函数不同按钮的效果也就不同。

来看看底下的三行代码,至此读此类代码应该不成问题了,首先创建了一个对象menu,将closeItem加入其中,之后放置位置,确定图层。现在的问题是为何要创建一个menu?我试过删除menu直接将按钮加入图层,结果点击没反应,这应该是cocos2d-x设计人员有意为之。之后会介绍cocostudio,UI设计会大大简化。目前就按照范例给出的方式进行即可。

至此读者应该已经掌握了基础的图片和按钮代码,并且初步完成了主界面的制作,虽然只是替换了一张图片而已。 (其实内容是很丰富的,只不过都是PS制作的,由此可以看出掌握多种技能的必要性,一张图直接改变了整个程序面貌)。本话主要还是集中在讲解和体会上,下一话将真正进入范例中没有涉及到的内容:背景音乐和帧动画,见《cocos2d-x萌新指南(二)——背景音乐、帧动画、sequence》。