烦恼一般都是想太多了。

0%

Cocos2d-X-基本概念

游戏其实是对画面、文字、动作、剧情的展示。无论是MMORPG还是小小的游戏,都需要有这样的表达方式。而cocos2d就是通过你来给砖头,他来建房子的这样一个东西。当然,其实我喜欢Lua但是其对Lua的文档实在是太少,只能自己摸索了。

本文来自于官方的新手指导cocos2d-x基本概念,版权归其所有。

组件

精通cocos2d-x很难,但是上手很容易

下面是一个简单的游戏画面:

然后把他进行分解:

能看到一个菜单(Menu),几个精灵(Sprite),和几个标签(Label),观察一下喜欢的游戏,会发现这些组件以某种形式存在其中。

导演(Director)

其实就是你切换每个场景的逻辑而已。比如,传送新地图等等,但是更文字化的描述还要看官方的。

Cocos2d-x 使用导演的概念,这个导演和电影制作过程中的导演一样!导演控制电影制作流程,指导团队完成各项任务。在使用 Cocos2d-x 开发游戏的过程中,你可以认为自己是执行制片人,告诉 导演(Director) 该怎么办!一个常见的 Director 任务是控制场景替换和转换。 Director是一个共享的单例对象,可以在代码中的任何地方调用。

这是一个典型的游戏流程实例。当您的游戏设计好时,Director 就负责场景的转换:

你是你的游戏的导演。你决定着发生什么,何时发生,如何发发生。

场景(Scene)

看看刚才那个图片:

这是一个主菜单场景,这个场景是由很多小的对象拼接而成,所有的对象组合在一起,形成了最终的结果。场景是被 渲染器(renderer) 画出来的。渲染器负责渲染精灵和其它的对象进入屏幕。为了更好的理解这个过程,我们需要讨论一下 场景图

场景图(Scene Graph)

场景图(Scene Graph)是一种安排场景内对象的数据结构,它把场景内所有的 节点(Node) 都包含在一个 树(tree) 上。(场景图虽然叫做”图”,但实际使用一个树结构来表示)。而节点(Node)则是场景图的基本元素。所有场景图内的元素必须是 节点 或者 其衍生类。最常见的Node类是:Scene, Layer, Sprite, Menu, Label

听起来这好像很复杂,可能你会问,我为什么要关注这个技术细节,Cocos2d-x 值得我研究的这么深入吗?值得!这个对你真正了解渲染器是如何绘制场景的非常重要。

当你开发游戏的时候,你会添加一些节点,精灵和动画到一个场景中,你期望的是每一个添加的对象都能被正确的展示,可是如果有个对象没有被展示呢?可能你错误的把这个对象隐藏到背景中了。怎么办?别着急,这是个小问题,停下来,拿出一张纸,把场景图画出来,你肯定能很容易的发现错误。

既然场景图是一个树结构,你就能遍历它,Cocos2d-x 使用 中序遍历,先遍历左子树,然后根节点,最后是右子树。中序遍历下图的节点,能得到 A, B, C, D, E, F, G, H, I 这样的序列。

初步了解了场景图,让我们看一下这个游戏场景。

分解这个场景,看一下它有哪些元素,这些最终会被渲染为一个树。

另一点要考虑的是,z-order 为负的元素,z-order 为负的节点会被放置在左子树,非负的节点会被放在右子树。实际开发的过程中,你可以按照任意顺序添加对象,他们会按照你指定的 z-order 自动排序。

如上图,左侧的场景是由很多节点对象组成的,他们根据被指定的 z-order 相互叠加。在 Cocos2d-x 中,通过 Scene 的 addChild() 方法构建场景图。

self:addChild(title_node, -2)
self:addChild(label_node)
self:addChild(sprite_node, 1)

渲染时 z-order 值大的节点对象会后绘制,值小的节点对象先绘制。如果两个节点对象的绘制范围有重叠,z-order 值大的可能会覆盖 z-order 值小的。

精灵(Sprite)

不知你是否意识到,所有的游戏都有 精灵(Sprite) 对象,精灵是您在屏幕上移动的对象,它能被控制。你喜欢玩的游戏中主角可能就是一个精灵,我知道你在想是不是每个图形对象都是一个精灵,不是的,为什么? 如果你能控制它,它才是一个精灵,如果无法控制,那就只是一个节点(Node)。

看下面的图片,我们来指出一下,哪个是精灵(Sprite),哪个是节点(Node)。

精灵在所有游戏中都很重要,每个游戏都有这样的情景:一个舞台,上面站着一个某种形式的主角,那主角就是精灵。Sprite 很容易被创建,它有一些可以被配置的属性,比如:位置,旋转角度,缩放比例,透明度,颜色 等等。

local mySprite = display.newSprite("mysprite.png")
:setPosition(500, 0)
:setRotation(40)
:setScale(2.0)
:setAnchorPoint(0,0)

让我们举例说明每个属性的含义,思考下面不同截图中精灵的区别:

设置位置::setPosition(500, 0):

现在这个精灵的位置就变成了,我们设置的新地方。

设置旋转角度setRotation(40)

设置缩放比例setScale(2.0)

看到了精灵的大小,由于我们设置缩放而变化了。

我们再来说一下 锚点(anchor point) ,所有的节点(Node)对象都有锚点值,Sprite 是 Node 的子类,自然也具有锚点。锚点是节点对象在计算坐标位置时的一个基准点。

以我们刚才的展示的精灵为例,设置锚点(0,0):

setAnchorPoint(0, 0)

精灵的左下角就变为了 setPosition() 调用,计算坐标的基础。再看看其它的锚点效果:

注意每张图片中的红点,红点表示锚点的位置。

正如你所看到的那样,锚点对于确定节点对象的位置是非常有用的,你可以在你的游戏中动态的调整锚点值以实现你想要的效果。

现在我们可以静态调整精灵的各个方面,但是你要想这些属性按照时间自动变化该如何做呢? 继续阅读,很快你就会有答案。

动作

创建一个场景,在场景里面增加精灵只是完成一个游戏的第一步,接下来我们要解决的问题就是,怎么让精灵动起来。动作(Action) 就是用来解决这个问题的,它可以让精灵在场景中移动,如从一个点移动到另外一个点。你还可以创建一个动作 序列(Sequence) ,让精灵按照这个序列做连续的动作,在动作过程中你可以改变精灵的位置,旋转角度,缩放比例等等。

有示例是这样的:

5s 后,精灵移动到了一个新的位置:

Action对象的创建:

local mySprite = display.newSprite("mysprite.png")
local moveBy = cc.MoveBy:create(2, cc.p(50, 10))
mySprite:runAction(moveBy);


local moveTo = cc.MoveTo:create(2, cc.p(50, 10))
mySprite:runAction(moveTo);

序列(Sequence)

能在屏幕上移动精灵,是制作一个游戏所需的一切,是吗?不是的,至少要考虑一下如何执行多个 Action。Cocos2d-x 通过 序列(Sequence) 来支持这种需求。

顾名思义,序列就是多个动作按照特定顺序的一个排列,当然反向执行这个序列也是可以的,Cocos2d-x 能很方便的完成这项工作。

让我们来看一个通过序列控制精灵移动的例子:

创建 Sequence :

local mySprite = cc.Node:create() -- display.newNode()
local moveTo1 = cc.MoveTo:create(2, cc.p(50,10))
local moveBy1 = cc.MoveBy:create(2, cc.p(100,100))
local moveTo2 = cc.MoveTo:create(2, cc.p(150,10))
local delay = cc.DelayTime:create(1)

mySprite:runAction(cc.Sequence:create(moveTo1, delay, moveBy1, delay:clone(), moveTo2, NULL))

这个例子执行了一个动作的 Sequence 序列,那要是想让所有的特定动作同时执行呢?Cocos2d-x 也支持!通过引擎中的 Spawn 对象,你能让多个动作同时被解析执行。可能不同动作的执行时间不一致,在这种情况下,他们不会同时结束。

local node = cc.Node:create()
local moveTo1 = cc.MoveTo:create(2, cc.p(50,10))
local moveBy1 = cc.MoveBy:create(2, cc.p(100,100))
local moveTo2 = cc.MoveTo:create(2, cc.p(150,10))
node:runAction(cc.Spawn:create(moveTo1,moveBy1, moveTo2, NULL))

节点关系

Cocos2d-x 的 节点关系,是被附属和附属的关系,就像数据结构中的父子关系,如果两个节点被添加到一个父子关系中,那么父节点的属性变化会被自动应用到子节点中。想一下处于父子关系中的精灵有什么特性。

这三个精灵被添加到了一个父子关系中,当父精灵(被其它精灵附属的精灵)设置了旋转角度之后,子精灵也会自动做同样的改变:

local myNode = cc.Node:create()
:setRotation(50)
:setScale(2.0)

需要注意的是,不是所有的父节点属性都会被自动应用到子节点,如改变父节点的锚点只会影响转换效果(比例缩放,位置变化,角度旋转,变形等),不会影响子节点锚点,子节点的锚点总会是左下角 (0,0)