第一章 渲染框架(深入理解一下吧)

http://blog.csdn.net/hahahakonghee/article/details/9200521
最近研究了一阵cocos2dx游戏引擎,在此把研究的成果分享给大家,以供大家共同学习和进步。

本文不会介绍cocos2dx的历史以及环境搭建(网上例子很多),我喜欢直奔主题,接下来讲一下cocos2dx的渲染框架。


做游戏很重要的一个东西,就是渲染,所以渲染框架至关重要,本章主要涉及到节点,场景,导演,精灵,动作等内容。这些类是最常用的一些,可以说是必须掌握的,我们先从节点类开始。


第一节  CCNode类(节点类)


【章外话】

      几乎任何面向对象语言都会有一个超集父类,通常它叫对象类Object,cocos2dx也不免俗,cocos2dx的超集父类叫CCObject,它是该系统一切类的本源。所有的类都继承了CCObject

          继承CCObject你就意味着可以采用引用计数来管理内存,而不是通常的newdelete

      引用计数机制牵扯到三个函数retain(),release(),autorelease()。

      每个对象都会有一个retainCount来记录该对象被引用了多少次,有多少地方在用这个对象。这样会让我们内存管理容易很多,因为只要有一个地方引用着该变量,我们就没有理由释放。当某个地方不想用这个变量只需要将引用的次数减1即可。当没有任何地方引用着该变量的时候,我们就把它释放。引用计数机制就是这个原理。当某个对象被构造(调用构造函数),retainCount为自动变为1,当调用retain()函数时候,retainCount会加1。调用release()和autorelease()的时候,retainCount会减1。然后判断retainCount是否为0,如果为0,将自动释放对象所占用的空间。

release()和autorelease()貌似执行的操作是一样的,它们有何区别?主要区别就是,release()会立刻执行(retainCount减去1等动作),而autorelease在其作用域内是不会执行的,当对象逃出作用域后才会执行,也就是说新建立的autorelease()对象,在作用域内还可以使用,甚至可以作为返回值返回,而release()的对象就不可用了。

我们只要能保证我们构造和retain的次数,刚好等于releaseautorelease,我们的程序就不会产生内存泄露,否则程序会有内存泄露。[谁构造 谁release 谁retain  谁release]


【CCNode的基本特性】

 CCNode是cocos2dx渲染框架的一切类的本源,渲染框架所有的类都继承CCNode,所以它有非常高的重要性,但是实际开发中,它对于程序员来讲通常是透明的,我们通常会使用它的子类,而不是它。但是我们要对它的大部分特性和属性非常清楚。

渲染框架的特性(CCNode的特性):

(1)可以加任何子节点

(2)可以计数回调函数

(3)可以添加动作

因此,我们对于该类的使用的流程也大概了如指掌了。

(1)构建节点对象,初始化其属性

(2)添加回调函数

(3)实现回调函数(执行某些动作?)

(4)适当的时机移除它,释放它


既然我们知道了其使用的流程,那么我们就把该流程遇到的知识点做详细讲解。

(1)构建节点对象,初始化其属性

通常使用的时候,我们用的是其子类,而新版的cocos2dx,都加入了create方法,由create方法构造的对象是autorelease对象,即它会在逃出作用域时,释放对象,所以我们无需释放该对象。


对于CCNode的属性,我们来看一下其常用的属性

Position:位置,默认值为0,0,只该节点在屏幕中被绘制的位置,其坐标是以左下角为原点的,右侧和上侧分别为x正向和y正向。

scale(x,y):缩放比例,默认是1,1。

rotation(in degrees,clockwise):旋转角度,默认是0。

CCCamera:摄像机朝向,后面会详细介绍改类。

anchorPoint:锚点,即参考点,默认为(0.5,0.5)。是指当节点平移,旋转,缩放时是以那个点为参考,1,1代表右上角,0,0代表左下角,依次类推。通常它的取值范围是(0,0)-(1,1)。

visible:是否显示。默认是true。

z-order:z轴,默认是0,由于节点可以增加子节点,所以z轴指的是层次概念,如果z越小表示越靠手机里面,离我们越远,越容易被其他的子节点挡住,数字越大代表离我们越近。

openGLzPosition:openGLz轴,默认是0,表示三维的z轴坐标。

这些属性都有对应的set和get方法来进行管理。


(2)添加回调函数(定时器回调)

如何给节点加一个计时的回调函数呢?,cocos2dx有以下api以之相关。


//检查当前的回调函数是否在继续执行

bool isScheduled(SEL_SCHEDULE 回调函数指针);

//启动定时器更新函数

void scheduleUpdate();

//修改回调函数的优先级

void scheduleUpdateWithPriorty(int 优先级);

//取消回调函数的刷新

void unscheduleUpdate();

//启动回调函数

void schedule(SEL_SCHEDULE 回调函数句柄);

voidschedule(SEL_SCHEDULE 回调函数句柄,float 回调时间周期);

voidschedule(SEL_SCHEDULE 回调函数句柄,float 回调时间周期,unsigned int 重复次数,float 延迟时间);

void scheduleOnce(SEL_SCHEDULE  回调函数句柄,float 延迟时间);//单次调用

//取消回调用函数

void unschedule(SEL_SCHEDULE 回调函数句柄);

voidunscheduleAllSelectors();

//恢复定时器调用以及动作

voidresumeSchedulerAndActions();

//暂停所有定时器和动作

void pauseSchedulerAndActions();


每个CCNode的实例都有一个默认的定时器,我喜欢叫它刷帧器,其优先级为0,0代表无敌的意思。优先级数字越大优先级越低,所以再同时触发的时候,会根据优先级来一次调用定时器的回调函数。

如果更新的时间周期为0,则表示定时器的回调函数,将会在每次引擎循环周期中都被调用。


注意:一个CCNode的实例当中,仅可以有一个回调函数。因为引擎的运算会占用时间,所以函数的回调时间周期,不可能真正为0。


除了默认的定时器,程序员可以使用函数自定义定时器。它的执行级别要低于默认的。

CCNode的定时器可以是永不停息的。

如果想取消一个定时器,要么等定时器重复次数完毕或对象销毁,要么就调用unschedule。

注意上述的最后两个函数,不仅与定时器相关,更与动作有关,本帖暂不讲动作。


(3)给节点添加一些动作

CCNode还有一个特性可以添加动作,停止动作


//执行动作

CCAction *  runAction(CCAction* 动作);

//停止所有动作

void stopAllActions();

//停止参数指定动作

void stopAction(CCAction* 动作);

//根据标志停止动作

voidstopActionByTag(int 标志);

//根据标志得到动作

CCAction*getActionByTag(int 标志);

//获取当前执行的动作的数目

unsigned int numberOfRunningActions();


我们的节点可以动,但是我们需要创建动作,动作本帖暂不讲。

这里的动作跟动画概念差不多,它可以代表运动,颜色改变,透明度等等。


注意:销毁一个CCNode对象的时候,会先停止所有的动作和定时器。


从最后一个方法,我们可以看出,一个节点可以执行多个动作。


CCNode的树结构】

CCNode其实还有一个特性,就是任意的CCNode可以添加任意个CCNode孩子对象,所以它的结构相当于树,一个节点有很多孩子,一个孩子还有很多孩子。

我们来看先关的API


//添加孩子节点

virtual void addChild(CCNode * 孩子); //默认的孩子z坐标为0

virtual void addChild(CCNode * 孩子,int  z轴坐标);

virtualvoid addChild(CCNode* 孩子,int  z轴坐标,int  标志);//标志也可以在外面设置   孩子->setTag(标志);

【注意:当添加完一个孩子节点的时候,会立即调用onEnteronEnterTransitionDidFinish,后面会补充介绍】


//从父节点移除

virtual voidremoveFromParentAndCleanup(bool 是否顺便清除孩子的动作以及回调);


//移除孩子节点

virtualvoid removeChild(CCNode* 孩子,bool是否顺便清除孩子的动作以及回调);

virtualvoid removeChild(int 孩子的标志,bool 是否顺便清除孩子的动作以及回调);

virtualvoid removeAllChildrenWithCleanup(bool是否顺便清除孩子的动作以及回调);


//得到孩子节点

CCNode*getChildByTag(int 孩子的标志);

【注意:如果存在多个相同标志的孩子,将会返回第一个添加的孩子】


//重置孩子的z坐标

virtualvoid reoderChild(CCNode* 孩子,int  z坐标);


//重新排布所有子节点

virtualvoid sortAllChildren();  【注意:该方法不要随意调用,除非需要在当前帧移除新加的子节点】


//获得孩子们

virtual  CCArray *getChildren();


//获得孩子的个数

unsigned int getChildrenCount();



【场景切换的影响】

//进入场景时会调用

virtualvoid onEnter();

//场景切换完成时会调用

virtualvoid onEnterTransitionDidFinish();

//推出场景时调用

virtualvoid onExit();

//场景开始切换时会调用

virtual voidonExitTransitionDidStart();


【注意:第二个函数和第四个函数是否被调用取决于,切换时是否使用特效来切换,比如翻页,百叶窗等,本帖暂不讲场景和特效,剩下两个是必调的,记住如果程序员派生节点的子类,复写这四个方法,必须先调用父类方法,否则会出现内存泄露】



CCNode的家族成员和结构】

CCNode

CCScene(场景)     CCLayer(图层)   CCMenu(菜单)CCSprite(精灵)      CCPaticleSystem(粒子系统)

这五个派生类是渲染框架的核心,当然CCNode还有万万千千的子类,但是最主要的就是这五个。之前说了CCNode是渲染框架的起点,所以渲染框架的所有类,都有CCNode的特性。


好了,本小结到此结束,谢谢观看。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值