《Cocos2D-x权威指南》——3.1 节点类

简介: 本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第3章,第3.1节,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.1 节点类

节点类(CCNode)是Cocos2D-x中的主要类,继承自CCObject,继承关系如图3-2所示。

image


任何需要画在屏幕上的对象都是节点类。最常用的节点类包括场景类(CCScene)、布景层类(CCLayer)、人物精灵类(CCSprite)、菜单类(CCMenu)。
CCNode类包括的主要功能如下:
每个节点都可以含有子节点,这点本书也会在后面给出示例。
节点含有周期性回调的方法(Schedule、Unschedule等)。关于周期性回调方法,本章将会有一节单独讲解,如果现在不了解,可以跳过这段内容。
可以含有动作(CCAction)。
CCNode可以为它自己和它的子节点添加额外的功能。无论是CCNode运行的动作(CCAction),还是设置的旋转角度和位置等属性,父节点的设置都可以传递到子节点上,这点在一些游戏的开发中可以使我们的管理更轻松。比如某些纵版射击游戏,玩家控制的主角飞机需要携带子机,子机的移动位置要随着主机一起移动,我们就可以把子机设置为主机的子节点,这样,在设置位置的时候,只需要设置主机的位置就可以了,大大减少了程序员需要处理的内容,提高了代码的清晰度和可读性。
由于CCNode类不自带贴图,其实在屏幕上看不到任何节点类的效果,所以一般使用CCNode类的场合有两个:第一个情况就是,需要一个父节点来管理一批子节点,这时候可以设置一个“无形”的子节点来管理子节点;另一种情况就是有时需要自己定义一个在屏幕上显示的对象,这时候让新定义的这个类继承自CCNode。一个类继承自CCNode类,说明它有如下特点:
重写初始化的方法和周期性回调方法。
在时间线上控制回调。
重写渲染的绘制方法。
CCNode类不含有贴图,它可以进行位置的平移、大小的伸缩变化、旋转变化。在网格特效(会在后面的章节介绍)使用的时候,网格特效可以获得屏幕中绘制的内容,并且对获得的屏幕内容进行渲染。这点在游戏中需要一些全屏特效的时候可以使用。
下面分别介绍CCNode类的成员数据和函数。
3.1.1 CCNode类的成员数据
CCNode类的主要公共成员数据,如表3-1所示。
image

CCNode类的主要保护成员数据(子类可见,Protected关键字)如表3-2所示。
image

3.1.2 CCNode类的函数
CCNode类的主要函数如表3-3所示。
image
image
image
image
image
image

以上就是CCNode类的部分函数,其中不包括本章后面介绍的调度相关的函数。
在2.0版本之前,CCNode类的构造函数是CCNode::node();在2.0版本以后可以使用create函数进行创建。
注意 非C++程序员可能会在API文档中遇到陌生的 virtual修饰符。其修饰的结果是使此函数为虚函数。虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public,实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数。
  在定义了虚函数后,可以在基类的派生类中对虚函数重新定义。在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型,以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。简而言之,虚函数允许在程序运行过程中根据指针的类型动态地选择它调用指针类型的函数。
3.1.3 坐标系简介
通过前面的学习,大家会对CCNode类的属性和方法有所了解,但是可能有些名词会令你困惑,如OpenGL坐标系、世界坐标系、节点相对坐标系、仿射变换等。本节就来解决这些问题。
1 . OpenGL坐标系
Cocos2D-x以OpenGL和OpenGL ES为基础,所以自然支持OpenGL坐标系。该坐标系原点在屏幕左下角,x轴向右,y轴向上。
屏幕坐标系使用的是不同的坐标系统,原点在屏幕左上角,x轴向右,y轴向下。iOS的屏幕触摸事件CCTouch传入的位置信息使用的是该坐标系。因此在Cocos2D-x中对触摸事件做出响应前,需要首先把触摸点转化到OpenGL坐标系。这一点在后面的触屏信息中会详细介绍,可以使用CCDirector的convertToGL方法来完成这一转化。
2 . 世界坐标系
世界坐标系也叫作绝对坐标系,是游戏开发中建立的概念,因此,“世界”即是游戏世界。它建立了描述其他坐标系所需要的参考标准。我们能够用世界坐标系来描述其他坐标系的位置。它是Cocos2D-x中一个比较大的概念。
Cocos2D-x中的元素是有父子关系的层级结构。通过CCNode设置位置使用的是相对其父节点的本地坐标系,而非世界坐标系。最后在绘制屏幕的时候,Cocos2D-x会把这些元素的本地节点坐标映射成世界坐标系坐标。世界坐标系和OpenGL坐标系方向一致,原点在屏幕左下角,x轴向右,y轴向上。
下面让我们暂时从纷乱的坐标系中抽出来,看一个重要概念:锚点。
3 . 锚点
锚点指定了贴图上和所在节点原点(也就是设置位置的点)重合的点的位置,因此只有在CCNode类节点使用贴图的情况下,锚点才有意义。
锚点的默认值是(0.5,0.5),表示的并不是一个像素点,而是一个乘数因子。(0.5,0.5) 表示锚点位于贴图长度乘0.5和宽度乘0.5的地方,即贴图的中心。
改变锚点的值虽然可能看起来节点的图像位置发生了变化,但其实并不会改变节点的位置,其实变化的只是贴图相对于你设置的位置的相对位置,相当于你在移动节点里面的贴图,而非节点本身。如果把锚点设置成(0,0),贴图的左下角就会和节点的位置重合,这可能使得元素定位更为方便,但会影响到元素的缩放和旋转等一系列变换。因此并没有一种锚点设置是放之四海而皆准的,要根据你这个对象的使用情况来定义。在Cocos2D-x中锚点为默认值(0.5,0.5),这样的锚点设置要把一个节点放置到贴图的中央。
4 . 节点坐标系
节点坐标系是和特定节点相关联的坐标系。每个节点都有独立的坐标系。当节点移动或改变方向时,和该节点关联的坐标系(它的子节点)将随之移动或改变方向。这一切都是相对的,相对于基准的,只有在节点坐标系中才有意义。
CCNode类的设置位置使用的就是父节点的节点坐标系。它和OpenGL坐标系的方向也是一致的,x轴向右,y轴向上,原点在父节点的左下角。如果父节点是场景树中的顶层节点,那么它使用的节点坐标系就和世界坐标系重合了。
CCNode类对象中有两个方便的函数可以做坐标转换:
convertToWorldSpace:把基于当前节点的本地坐标系下的坐标转换到世界坐标系中。
convertToNodeSpace:把世界坐标转换到当前节点的本地坐标系中。
这两种转换都是不考虑锚点的,都以当前节点父类的左下角的坐标为标准。另外,CCNode还提供了convertToWorldSpaceAR和convertToNodeSpaceAR。这两个方法完成同样的功能,但是它们的基准坐标是基于坐标锚点的。几乎所有的游戏引擎都会使用类似的本地坐标系而非世界坐标系来指定元素的位置。
这样做的好处是,当计算物体运动的时候,使用同一本地坐标系的元素可以作为一个子系统独立计算,最后再加上坐标系的运动即可,这是物理研究中常用的思路。例如,一个在行驶的车厢内上下跳动的人,只需要在每帧绘制的时候计算他在车厢坐标系中的位置,然后加上车的位置就可以计算出人在世界坐标系中的位置。如果使用单一的世界坐标系,人的运动轨迹就变复杂了,就涉及中学所学到的运动轨迹的合成与分解。
5 . 仿射变换
最后介绍仿射变换。游戏大量使用的旋转、缩放、平移等都是仿射变换。所谓仿射变换是指在线性变换的基础上加上平移。平移不是线性变换。
二维计算机图形学中的仿射变换通常是通过和3×3齐次矩阵相乘来实现的。Cocos2D-x的CCAffineTransform结构体的定义如代码清单3-1所示。
代码清单3-1 CCAffineTransform结构体定义

struct CCAffineTransform {
  CCFloat a, b, c, d;
  CCFloat tx, ty;
}

其中定义了a、b、c、d、tx、ty,它们在矩阵中的位置如图3-3所示。

image


3.1.4 实例:通过节点控制屏幕中的全体渲染对象
本节,已经可以利用我们目前所学的知识做出一些有趣的东西。之前已经说过,CCNode类没有贴图,也就是说在屏幕上单独建立一个节点是没有任何效果的,但是可以通过这个“无形”的节点来控制屏幕上的节点。现在就开始吧!
1 . 加入节点
新建一个项目,并在HelloWorldScene.cpp文件中的init函数中做如代码清单3-2的代码所示的修改。
代码清单3-2 加入节点
bool HelloWorld::init()
{

    if ( !CCLayer::init() )
    {
        return false;
    }

    //创建一个节点
    CCNode *anode = CCNode::create();
    //将节点作为子节点加入场景类中
    this->addChild(anode,0);
    
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
    menu_selector(HelloWorld::menuCloseCallback) );
   pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );
    
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->setPosition( CCPointZero );
    //将菜单作为子节点加入之前定义的节点中
    anode->addChild(pMenu, 1);
    
    CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Thonburi", 34);
    
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    
    pLabel->setPosition( ccp(size.width / 2, size.height - 20) );

    //将标签作为子节点加入之前定义的节点中    
    anode->addChild(pLabel, 1);
    
    CCSprite* pSprite = CCSprite::create("HelloWorld.png");
    
    pSprite->setPosition( ccp(size.width/2, size.height/2) );
    
    //将背景图片作为子节点加入之前定义的节点中    
    anode->addChild(pSprite, 0);
    return true;
}

首先通过create函数创建一个节点anode,把anode作为子节点使用addChild函数加入HelloWorld场景类对象中;然后把本来作为子节点加入HelloWorld场景类对象中的对象,使用addChild函数作为子节点加入anode中。这些对象包括菜单类对象、标签类对象、人物精灵类对象。这些对象的类都是CCNode类的子类。如果目前你对这些对象的使用不了解的话,请跳过这些对象的使用,因为对于这些本书会在后面做相应的讲解。
运行项目,发现和修改前的项目并无区别,如图3-4所示。
2 . 改变位置
修改HelloWorldScene.cpp文件中的init方法,如代码清单3-3所示。
代码清单3-3 设置节点位置

//设置节点位置
    anode->setPosition(ccp(50,50));

运行效果如图3-5所示。

image

可以看到,整体都跟着节点移动了。
3 . 设置缩放
下面修改这段代码如代码清单3-4所示,看一下缩放的效果。
代码清单3-4 设置缩放代码

//设置缩放
anode->setScale(0.5);

运行效果如图3-6所示。

image

4 . 整体旋转
最后再来试验整体旋转,如代码清单3-5所示。因为默认锚点在左下角,因此需要首先移动一下整体的位置,否则整体一转,屏幕中将只显示黑屏。注意角度设置为角度制。
代码清单3-5 设置旋转

//设置旋转
anode->setPosition(ccp(200,200));    
anode->setRotation(90.0);

运行效果如图3-7所示。

image


本节介绍了屏幕中渲染对象的基础类CCNode,下一节将介绍控制游戏显示的导演类CCDirector。
相关文章
|
5月前
CocosCreator 面试题(十六)Cocos Creator 节点池的基本原理是什么?如何使用?
CocosCreator 面试题(十六)Cocos Creator 节点池的基本原理是什么?如何使用?
161 0
|
JavaScript 前端开发
《Cocos2D权威指南》——3.2 CCNode节点类
本节书摘来自华章计算机《Cocos2D权威指南》一书中的第3章,第3.2节,作者:王寒,屈光辉,周雪彬著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1042 0
《Cocos2D权威指南》——3.1 Cocos2D节点基础知识
本节书摘来自华章计算机《Cocos2D权威指南》一书中的第3章,第3.1节,作者:王寒,屈光辉,周雪彬著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1145 0
|
JavaScript
《Cocos2D权威指南》——3.3 CCScene场景类
本节书摘来自华章计算机《Cocos2D权威指南》一书中的第3章,第3.3节,作者:王寒,屈光辉,周雪彬著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1091 0
|
缓存 前端开发 JavaScript
《Cocos2D-x权威指南》——3.3 场景类
本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第3章,第3.3节,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1225 0
|
iOS开发 C++
《Cocos2D-x权威指南》——第3章 Cocos2D-x中的核心类
本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第3章,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
888 0
《Cocos2D权威指南》——第3章 3.0 Cocos2D核心类
本节书摘来自华章计算机《Cocos2D权威指南》一书中的第3章,第3.0节,作者:王寒,屈光辉,周雪彬著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1019 0