首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

2013-04-07 
礼物:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵) [Cocos2d-x相关教程来源于红孩儿的游

礼物:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

 

[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier

红孩儿Cocos2d-X学习园地QQ3群:205100149,47870848

礼物:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)
         另:好吧,我彻底被Cocos2d-x版本的更新速度打败了!我决定停止再对2.0.2版本再做深入分析讲解。本博文实为新书的节选,做为礼物送给大家,望各位仔细阅读后提出批评!      另:本周末工具箱会更新到0.1.1版本,欢迎下载并到官方论坛提出BUG反馈和使用建议。  
   

本节的学习目标:

(1)    了解结点系统,学会自行构建结点系统。

(2)    了结场景,层,精灵的组织关系与各自功能



2.1 结点系统原理入门

2.1.1 结点启蒙:

在介绍Cocos2d-x的结点系统之前,我们需要首先做一些启蒙,什么是树?

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

定义:

 

一棵树(tree)是由n(n>0)个元素组成的有限集合,其中:

(1)每个元素称为结点(node);

(2)有一个特定的结点,称为根结点或根(root);

(3)除根结点外,其余结点被分成m(m>=0)个互不相交的有限集合,而每个子集又都是一棵树(称为原树的子树)

 

如图A:

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)


对于树结构有几个概念要记一下:

:树的度——也即是宽度,简单地说,就是结点的分支数。以组成该树各结点中最大的度作为该树的度,如上图的树,其度为3;树中度为零的结点称为叶结点或终端结点。树中度不为零的结点称为分枝结点或非终端结点。除根结点外的分枝结点统称为内部结点。

深度:树的深度——组成该树各结点的最大层次,如上图,其深度为3;

层次:根结点的层次为1,其他结点的层次等于它的父结点的层次数加1.

         请仔细观察上图这棵树,这里A是根结点,其余结点均是属于A的不同层级的子结点。我们由此图进一步进行想像,人的身体其实也是一棵树。

如图B:

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)


 

         上图详细表现了人体树结构的组织结构,左边是人形的结构,右边是层级关系展开。它作为骨骼动画的基础理论被广泛的应用于各类游戏动画中。

         我们看一下这张图,首先有一个根骨(脊椎),这个根骨即是树结构中的根结点。根骨下有三根子骨骼(左胯,右胯,颈背),这三根子骨骼也各自有属于自已的子骨骼树结构,同时它们由父骨骼牵引并牵引着子骨骼,与父骨骼和第一层子骨骼保持着固定的距离。

         试想一下:

 

         当我们想把这个人移动到一个位置点时,只需要把根骨移动到相应位置,即这个人的所有骨骼都会被这种牵引关系移动到这个世界位置的相对骨骼位置。但如果我们把左胯这根骨骼去掉的话,则在移动根骨后,左胯仍停留在原地,它已经不再属于当前骨骼树了,而成了一棵独立的骨骼树。

        

         看完这张图,已经比较接近我们所要讲述的内容了,对于骨骼结构的理解将有助于我们掌握远大于骨骼动画本身的结构模式,因为由此理论基础我们将学会一切基于结点树结构的系统。

 

         下面我们来用C++的代码构建这样一套系统。

首先,我们创建一个基类,称之为结点。


保存的XML文件打开后:

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

        学到这里,您已经掌握了一个结点系统的基本设计思想,它将在日后成为一个强大的武器来帮助您在游戏开发过程中解决一些相关的设计问题。

2.1.1结点的位置:

上面的结点系统代码中,只有结点的父子关系,并不能实现父结点移动同时带动子结点移动。这又是怎么做到的呢?

这里有一个关键的核心算法:即一个结点的位置,由本结点相对于父结点位置加上父结点的世界位置来取得,而父结点又会通过父结点与其父结点(即爷爷结点)的相对位置加上其父结点(即爷爷结点)的世界位置来取得。这里有一个层层回溯的思想在里面。

我们在代码中加入一个表示空间位置的结构。


 

         这个开始界面做为一个场景是简单了点,但很清晰。游戏开始时首先要运行的场景就是它。我们以三级树形结点来表示这个场景。


礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)


         在这个三级树形结点图示中,“开始界面”即为场景,“界面层”即为层,再下面的四个结点可以算为界面层下的精灵,当然,菜单其实也可以分为几个精灵构成。

         第二类场景就是关卡了。如图:

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

         这是熟悉的第一关,我们仍以三级树形结点来表示这个场景。

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

         在这里,“第一关”即为场景,为了区分具有不同排序分类的精灵集合。我将游戏中的层由远及近观看,由先及后绘制,划分为“远景层”,“近景层”,“人物层”,“效果层”,“界面层”等五个层,再将各种精灵分布到这些层中。

         继续这样子分析,我们可以得出所有的关卡树:

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

         在这里“Root”代表了游戏程序。它共种有十棵树。分别为“开始界面”,“第一关”…“通关界面”,每完成一个关卡,就将进行场景的切换,也就是显示一棵新树。

        

         到这里,精灵,层与场景的结点关系原理已经讲解完成。我们现在来看一下Cocos2d-x中是如何具体实现和应用的。

        

         以开始界面为例,咱们接着上一节中所讲的节点类来进行扩展,为了更好的讲述理论,这部分内容完全不涉及任何渲染引擎的使用,我们只使用VS创建一个简单的WIN32窗口程序,并使用GDI来进行绘制。

        

         我们将创建的工程命名为ShowNodeTree,编译运行只有一个空白窗口,它工作的很好。OK,现在我们创建一个工程筛选目录NodoTree,并将之前创建的Node放入其中,并依次创建好Scene,Layer,Spriet及Director等类。

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

 

顾名思义,上面这些文件分别为:

 

         Director.h/cpp:win32绘制管理类CDirector,绘图用。

         Node.h/cpp:结点基类CNode,用于构建结点树。

         Layer.h/cpp: 层类CLayer。

         Scene.h/cpp:场景类CScene。

         Sprite.h/cpp:精灵类CSprite。

 

我们来看一下具体实现:

首先是win32绘制管理类CDirector:

Director.h:



 

         这里共有一个层和八个精灵。层嘛,就是一纯黑背景色块,八个精灵嘛,就如上图所示分别用来显示不同的位图:


礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

 我们现在打开程序的主源文件ShowNodeTree.cpp,在文件顶部加入:



        怎么样?不错吧。一个开始界面层展现在我们面前,所有精灵做为层的子结点而随着层保持运动。虽然这种方式还有一些闪屏,但,那并不是重点,关键是你彻彻底底的理解了结点系统对于引擎架构的作用和设计思想。好了,喝口水歇一会儿开始进入到Cocos2d-x中去看看。

2.1.2 Cocos2d-x中的精灵,层,场景与结点:


         在Cocos2d-x中,结点的基类是CCNode,它的实现远远超越了上面结点代码的复杂度,不过没关系,随着后面相关代码接触的加深,你可以很明白它的全部接口函义,但现在,你所需要的只是明白它就不过是个结点,它不过是咱们上面结点类的演变,说的通俗点:不要以为你穿个马甲哥就认不出你了!

 

         在CCNode中,有一个指针容器成员m_pChildren ,它存放了当前结点下的所有子结点,我们通过addChild来增加子结点到其中。我们并没有发现所谓的兄弟结点,为什么呢?那时因为兄弟结点被“扁平化”处理了。为了提升效率,减少递归调用的次数,可以将所有子结点的指针都存放在当前结点的容器中,所以子结点的兄弟结点就不必出现了。

 

         有了结点CCNode,我们来看一下精灵CCSprite,它在libcocos2d的sprite_nodes分类下。

打开CCSprite.h:

 

         CCSprite :publicCCNode,public CCTextureProtocol,public CCRGBAProtocol

        

         很明显,精灵是由结点CCNode派生出来的子类。它的主要功能就是显示图形。在其函数中,涉及纹理加载和OpenGL相关的顶点和颜色,纹理寻址的操作。

        

         层CCLayer和场景CCScene是被存放在libcocos2d的layers_scenes_transitions_nodes分类下。

         打开CCLayer.h:

 

CC_DLLCCLayer : public CCNode,public CCTouchDelegate,publicCCAccelerometerDelegate,publicCCKeypadDelegate

 

         可以看到,CCLayer除了由结点CCNode派生外,还增加了用户输入事件的响应接口。如CCTouchDelegate是触屏事件响应接口类,CCAccelerometerDelegate是加速键消息事件响应接口类,CCKeypadDelegate是软键盘消息事件响应接口类。

 

    打开CCScene.h:

class CC_DLL CCScene :publicCCNode

         好吧,真是简单明了,场景就是专门管理子结点的,或者说就是专门管理层结点的。

 

         现在我们来看一些它们的具体应用。

         打开HelloCpp工程。在Classes下我们看到有两个类:

 

1 . AppDelegate:由CCApplication派生,即Cocos2d-x的程序类。可以把它当作上面图示中的”Root”。它的作用就是启动一个程序,创建主窗口并初始化游戏引擎并进入消息循环。

 

2 . HelloWorld:由CCLayer派生,即Cocos2d-x的层。对应上面图示中“开始界面”场景中的“界面层”。它的作用是显示背景图和菜单及退出按钮等精灵。在这个类里有一个静态函数HelloWorld::scene()创建了所用到的场景并创建HelloWorld这个层放入到场景中。

 

         在程序的main函数中创建了AppDelegate类的实例对象并调用run运行。          之后会在AppDelegate的函数applicationDidFinishLaunching(代表程序启动时的处理)中结尾处调用HelloWorld::scene()创建了场景。

 

         游戏运行起来是个什么样子呢?没错,我看跟魂斗罗的“开始界面”也差不到哪去嘛。当然,只是指组织关系。

礼品:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)

         嗯,到此,本节的知识算是讲述完毕!做为一个有上进心的程序员,咱们来做些课后题吧?

2.3 课后题目

1.在2.1.1结中为结点增加缩放,旋转(当然,如果没有好的数学知识就算了,也可以用一些第三方数学库)的处理,使取得一个子结点在世界坐标系中的大小时会受到其父结点的影响。

 

2.  将《魂斗罗》之外你玩过的游戏选几个做一个树型分析。

     最后,本节所涉及实例工程代码下载:http://download.csdn.net/detail/honghaier/5221534
2楼b6456066248昨天 00:18
顶了再看
1楼kltwjt昨天 23:27
为了说明cocos2d-x内部关系,重新实现了个简单的“框架”~ 酷!nn看到“CNode* CNode::QueryBorther(const char* szName)”此方法的实现时,有些疑惑,看名子应该是同一深度遍历匹配的,看到后面才知道,这也许只是“QueryChild”方法的辅助,但“QueryBorther”是横向查询,感觉“宽度优先”更合适,即先判断207行“m_pFirstBorther->QueryBorther(szName);”是否有返回值,没有的话再回头查子项。nn纯属个人浅见,稍作讨论~ : P

热点排行