加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Cocos2dx-- 3.0前后对比

发布时间:2020-12-14 16:57:06 所属栏目:百科 来源:网络整理
导读:前言:cocos2dx-3.0算是cocos引擎版本的一个分水岭,这之后它从多个方面对引擎功能进行了增强,大幅度提高了引擎性能,还对引擎的渲染架构进行了重写,使其更灵活,更易用。截止到目前cocos引擎已经更新到3.10版本了,下面我们就来大体讲讲3.0这个分水岭前后

前言:cocos2dx-3.0算是cocos引擎版本的一个分水岭,这之后它从多个方面对引擎功能进行了增强,大幅度提高了引擎性能,还对引擎的渲染架构进行了重写,使其更灵活,更易用。截止到目前cocos引擎已经更新到3.10版本了,下面我们就来大体讲讲3.0这个分水岭前后引擎的对比变化:

回归C++风格

Cocos2d-x是基于Cocos2d-iphone移植的,在3.0之前一直保持着与Cocos2d-iphone一致的Objective-C接口风格,如:类名称加前缀”CC”,单例命名”sharedXXX()”,还有属性的使用等。
但在3.0之后,Cocos开始抛弃Objective-C风格,还原C++,并在引擎接口设计中加入了一些C++11的特性。大体修改有下面这些:

  • 使用命名空间代替”CC”前缀:例如,CCSprite被更名为Sprite,CCNode更名为Node等。
  • 使用clone()代替copy()方法:这个克隆将直接返回一个加入自动回收池的对象,调用者不需要手动再将其加入回收池了。
  • 用getInstance()和destroyInstance()方法代替sharedXXX()和endXXX()方法来使用单例。
  • TextureCache,Dispatcher等对象不再是全局的单例,它们属于Director,需要通过Director来获取其实例,这使得Cocos可以支持多个窗口,即多个Director来实现。
  • 使用了部分C++11的特性,如std::function,强类型枚举(enum class name ={XXX}),std::thread,auto,override和final关键字,移动语义,lambda表达式(匿名函数:[capture] (parameters)->return-type{body})等。

跨平台的Label

首先要搞清OpenGL ES并不直接提供对文字的支持,我们游戏中看到的文字其本质都是通过绘制纹理来显示的。
Cocos 3.0对字体进行了重构,使用了开源的FreeType字体库来解析文字和生成纹理,并能返回字形的信息。这样,不仅能通过着色器程序给每个文字添加不同的特性,还能让多个文字共享一张纹理,使绘制效率大大提升。
Cocos 3.0还用Label对象统一了LabelTTF,LabelBMFont,LabelAtlas字体,使它们拥有相同的属性及使用方法,更加不依赖各种平台。唯一区别只是底层生成或加载纹理方式不同:
TTF字体:是通过实时解析TTF字体库,来对应生成字体纹理来显示,这种字体占用内存小,但相对耗效率,一般适用于显示大量静态的文字。
BMFont字体:把字体预先保存到一张大的纹理上,通过查找匹配显示文字,这种字体耗内存但效率高,适用于要显示大量实时更新的动态文字。
Atlas字体:和BMFont类似,预先保存字体到纹理上,但这种一般是保存阿拉伯数据或字母表,直接根据他们的ASCII 顺序查找,用于实时更新的数值类文字,如时钟等。

新的渲染系统

在一般得3D应用程序中,OpenGL渲染管线可以根据片段的深度来正确处理场景中元素的层级,我们只需要处理透明与非透明物体的绘制顺序即可。而对于2D程序,每个元素通常具有相同的深度,那我们怎么保证每个元素的绘制顺序呢?

Cocos3.0以前,是通过给每个元素指定一个逻辑深度(UI树结构),并按照这个深度对UI元素进行排序,游戏每一帧需要对UI树做一个深度优先遍历,然后就可以按照正确的顺序绘制整个场景了。这套机制,在每一帧上除了渲染几乎没有额外的计算工作,因此能够较高效率的执行渲染工作。但是,这套架构缺不易扩展,例如,开发者无法修改一个元素在全局的层级,每个元素都按照UI树的结构绘制,不能在父级或子级之间变更层级。由于每个元素(Sprite)都单独负责自己的绘制,所以不易针对绘制做更好的优化。例如:相邻的两个元素使用了相同的纹理和相同的OpenGL ES绘制参数,但是它们仍然需要单独绘制两次。

Cocos3.0以后,重新设计了渲染机制,将渲染从UI树遍历中分离出来,主线程在每一帧遍历UI树的每一个元素时,并不直接调用OpenGL ES进行绘制,而是将每个元素的绘制命令包装成一个RenderCommand对象发送至绘制栈,绘制栈在遍历场景中的每一个元素之后开始绘制。绘制栈包括:QuadCommand,GroupComand,BatchCommand及自定义绘制命令的CustomCommand,这样可以带来以下几个方面的好处:

  • 绘制命令可以被重用。不同的元素可以使用相同的绘制命令进行组合,如:Label,Particle,TileMap都使用BatchCommand进行绘制。
  • 所有绘制命令被集中处理,渲染系统就可以做一些优化工作。如:对相邻的绘制命令,如果它们使用了相同的RenderCommand类型,并且使用相同的纹理及OpenGL ES绘制参数,渲染系统就可以把它们合并成一次绘制。这我们一般称为自动批绘制技术。如果场景中有100个相同的Sprite,它们来自同一张纹理,那么OpenGL ES就只会调用一次绘制命令。(以前还需要手动加入批处理缓存中才能实现)
  • UI树与渲染分离,使其可以用不同于UI树结构的绘制顺序绘制了,通过globalZOrder来设定全局绘制顺序,绘制栈则优先根据globalZOrder中设定进行排序,然后再对glocalZOrder的RenderCommand进行排序,以决定绘制顺序。
  • 新渲染系统还引入了自动裁剪技术,所有窗口之外的Sprite根本不会发送绘制命令到绘制栈,减少不必要的OpenGL ES绘制调用。

统一的消息分发

消息机制一直是软件开发中减少模块之间耦合的标准方式(观察者模式)。Cocos3.0之后将以前的CCTouchDispatcher,CCkeypadDispatcher,CCkeyboardDispatcher及CCAccelerometerDispatcher封装成一个统一的事件分发器—-EventDispatcher。除了能分发上面系统提供的事件外,而且还可以向EventDIspatcher注册自定义的事件类型。
以前事件分发顺序是通过设定一个int值来比较大小分发事件的,越小越优先分发(0:系统保留,Node分发默认0)。而现在保留了以前数字优先级机制,同时新增了通过关联UI元素来指定事件分发优先级,及离屏幕越近先处理,这样事件分发顺序更加清晰。接口如下:

void addEventListenerWithSceneGraphPriority(EventListener *listener,Node *node); //关联节点事件分发

void addEventListenerWithFixedPriority(EventListener *listener,int fixedPriority); //关联整数事件分发

将事件与一个Node元素关联,还一个好处是:当这个元素被移除时,与其关联的事件也同时被移除,不需要手动再去移除了。

其它

  • 大大简化了物理引擎的使用方式,对大部分的物理属性及对象进行了封装,深度集成了物理引擎,开发者甚至不用了解底层物理引擎的接口就可以使用物理引擎。
  • 新的数据结构,C++标准库提供的std::vector,std::map等比较优秀的数据结构,然后它不支持Cocos的内存管理方式,以前我们使用的是CCArray和CCDictionary,然而它们缺不能很好的支持C++标准库中的迭代器的操作也和我们全面使用C++风格不合。Cocos3.0后用Vector< T >和Map< K,V >代替CCArray和CCDictionary,它其实就是对C++标准库中std::vector< T >和std::unordered_map< K,T >的封装,只是使其支持Cocos的内存管理方式。
  • 。。。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读