基础的cocos2d-x概念
cocos2d-x的核心概念包括Scene,Sprite,Menu以及Action对象。
让我们看看下面这幅图:
这张图虽然简单却包含了一个游戏中的大部分元素。
我们能够看到图片(Sprites),文字(Labels),以及菜单(Menu)。
Director
我们在使用cocos2d-x的API的时候,会经常与一个叫做Director的类打交道。我们可以把它看作电影里的导演,而我们就是制片人,让它做啥就做啥。我们经常会用这个类来完成场景的切换,他是一个单例类,所以我们能够在任何地方非常方便的使用他。
这是典型的游戏流程图,我们用Director来控制整个流程。
Scene
在我们的游戏中会有很多个场景,比如主菜单界面,选择关卡界面,游戏界面等,那么我们用什么东西来将他们分别组织好呢,答案就是Scene类了。想想看我们的常玩的游戏中是不是都有很多场景呢?
Scene Graph
我们用一种叫做Scene Graph的数据结构来组织我们的场景。Scene Graph用树这种数据结构来管理我们的Node对象。
听起来貌似是什么难以理解的东西。可能您会问既然cocos2d-x已经为我们处理了所有的繁重的工作,为毛我还要理解这个技术的细节?因为这会让我们对场景中
的物体是如何显示出来的有一个清晰的认识。
一旦我们在游戏中添加node,sprite或者aniamtion的时候,我们当然希望他能够直接显示出来,以便我们确认我们确实是正确添加了我们需要的对象。不过有时候,我们添加的对象并不一定会显示出来,他们有可能会被场景中的其他的物体遮住了。那要怎么调整才能看到我们添加的东西呢?
这个Scene Graph是一种树形结构,那么我们是按照一种什么样的顺序去遍历这棵树上的节点的呢?我们使用中序遍历的方式来遍历的,具体的顺序如下图:
我们从虚线的方块那头开始,直到箭头的那头。顺序靠前的节点先渲染,顺序靠后的节点后渲染,也就是说,后渲染的物体会遮住先渲染的物体。在实际使用API的过程中,我们会使用一个叫做z-order的变量来控制渲染的先后顺序,z-order值越小则越先被渲染。
比如:我们可以将上面的那个场景分成若干个对象,如下:
start game的开始游戏菜单最先显示,然后是3个小怪,然后是那个水平台,最后是游戏的logo。
在实际的API使用过程中,我们通常会使用一个叫做addChild()的API来构造我们的scene graph。
在c++代码中:
scene->addChild(title_node, -2);
在js代码中:
scene.addChild(title_node, -2);
第一个参数是我们要添加到scene graph中的对象,第二个参数就是我们设定的z-order数值。
Sprite
所有的游戏都是有sprite的,那么什么是Sprite呢?通常他会是一张图片。当然你可能会将所有的图片都认为是sprite,但是只有动的图片才能是sprite,不动的只能算是一个node。
像下面这张图说明的那样:
通常我们用如下的方式来使用一个Sprite:
c++
// This is how to create a sprite
auto mySprite = Sprite::create("mysprite.png");
// this is how to change the properties of the sprite
mySprite->setPosition(Vec2(500, 0));
mySprite->setRotation(40);
mySprite->setScale(2.0); // sets both the scale of the X and Y axis uniformly
mySprite->setAnchorPoint(Vec2(0, 0));
js
// This is how to create a sprite
var mySprite = new cc.Sprite(res.mySprite_png);
// this is how to change the properties of the sprite
mySprite.setPosition(cc._p(500, 0));
mySprite.setRotation(40);
mySprite.setScale(2.0); // sets both the scale of the X and Y axis uniformly
mySprite.setAnchorPoint(cc._p(0, 0));
我们用create函数来创建一个sprite,然后用setPosition()来设定他的位置,用setRotation()来设定他的旋转角度,用setScale()来设定他的缩放,用setAnchorPoint()来设定他的锚点。
啥是锚点呢,锚点就是设定sprite位置时的参考点,设置缩放时的缩放中心点,设置旋转时的旋转中心点。如图:
如果锚点的值为(0,0)说明我们将Sprite的左下角作为设定位置的基准点,而(1,1)则是将sprite的右上角作为设定位置时的基准点。这三张图其实向setPosition()传入的都是一样的值,只是sprite的锚点不同,所以就有了不同的表现。
Action
为了让sprite动起来, 我们还得为他加上Action这种对象才行。
c++
auto mySprite = Sprite::create("Blue_Front1.png");
// Move a sprite 50 pixels to the right, and 10 pixels to the top over 2 seconds.
auto moveBy = MoveBy::create(2, Vec2(50,10));
mySprite->runAction(moveBy);
// Move a sprite to a specific location over 2 seconds.
auto moveTo = MoveTo::create(2, Vec2(50,10));
mySprite->runAction(moveTo);
js
var mySprite = new cc.Sprite(res.mySprite_png);
// Move a sprite 50 pixels to the right, and 10 pixels to the top over 2 seconds.
var moveBy = new cc.MoveBy(2, cc._p(50,10));
mySprite.runAction(moveBy);
// Move a sprite to a specific location over 2 seconds.
var moveTo = new cc.MoveTo(2, cc._p(50,10));
mySprite.runAction(moveTo);
这里有两种类型的action,一种是moveTo另一种是moveBy。moveTo的意思是让我们的sprite移动到moveTo设定的位置,而moveBy的可以让我们移动moveBy中设定的x的距离和y的距离。
Squences and Spawns
这两个类,前者让我们的action按顺序执行,后者会融合我们的action,让他们一通执行。
c++
auto mySprite = Node::create();
// move to point 50,10 over 2 seconds
auto moveTo1 = MoveTo::create(2, Vec2(50,10));
// move from current position by 100,10 over 2 seconds
auto moveBy1 = MoveBy::create(2, Vec2(100,10));
// move to point 150,10 over 2 seconds
auto moveTo2 = MoveTo::create(2, Vec2(150,10));
// create a delay
auto delay = DelayTime::create(1);
js
var mySprite = new cc.Node();
// move to point 50,10 over 2 seconds
var moveTo1 = new cc.MoveTo(2, cc._p(50,10));
// move from current position by 100,10 over 2 seconds
var moveBy1 = new cc.MoveBy(2, cc._p(100,10));
// move to point 150,10 over 2 seconds
var moveTo2 = new cc.MoveTo(2, cc._p(150,10));
// create a delay
var delay = new cc.DelayTime(1);
Parent Child Relationship
如果一个物体是另一个物体的子物体,那么父物体的运动会影响子物体的运动,反之,子物体的运动并不会影响父物体的运动,而这种父子关系是通过addChild建立起来的。
如图,白色和灰色的怪物是蓝色怪物的子物体,我们使用setRotation()来改变蓝色怪物的角度,那么就会变成下面这样。