解说cocos2d-x几种画图方法的用法与思考

CCRenderTexture

自己的理解

CCRenderTexture类似一张空白的“画布“,用户通过自定义笔刷(CCSprite*),在touch事件中把笔刷的移动痕迹“记录”起来,从而“画”出各种艺术效果。记录方法很简单,首先CCRenderTexture调用自己的begin()函数,开启“记录”功能,然后调用笔刷->visit()把自己”画“在这张画布上,最后CCRenderTexture调用end()结束记录,那就OK了。

这里我想CCRenderTexture是通过把笔刷的纹理叠加到自己的纹理(Texture)里,而不是不断创建新纹理,所以消耗比较低,即使画得很频繁,帧数也能保持稳定,是个很赞的类。

CCRenderTexture由于只要begin()开启“记录”功能后,任何之后的CCNode*对象只要调用了visit(),就能将自己“画”在其身上。所以,一般游戏的截屏功能,完全可以使用CCRenderTexture的来实现,具体可以看tests里例子,cocos2d-x已经提供了相关例子,看看源代码就能搞明白的。

优点

用CCRenderTexture可以很简单的实现出理想的画图效果(只要搞一张很小的笔刷图,然后用CCSprite载入来,再适当调用一个CCSprite的visit()就行了),帧数消耗低,还很方便实现出游戏的截屏功能,做《你画我猜》这种项目,第一想到的应该就是它了。

缺点

由于每个Android手机的硬件或者OpenGL版本不一样,导致有些手机用CCRenderTexture会出现花屏,比如HTC。就算是官方提供的tests例子也难逃一花屏,这个致命的缺点导致用它来实现的《你画我猜》不能跨手机,比较坑爹…

这个Bug我想不是cocos2d-x引擎的问题,有牛人说是因为Texture在重复画导致的(只画一次没问题,所以截屏功能应该不受影响),也许是每台Android手机的OpenGL不一样吧,所以问题一直没得到解决,只能等cocos2d-x或者有其他牛人以后可以把它Fixed掉。

因为花屏问题,现阶段不推荐使用(如果有牛人解决了花屏问题,请教教我,谢谢)

[ 花屏参考图 ]

例子

CCRenderTexture大概是大家比较熟悉的,tests里也有相关例子,要知道用法直接看tests的源代码就可以了,效果如图:

用OpenGL-ES实现画图

自己的理解

OpenGL-ES是OpenGL的精简版,由于太精简,很多OpenGL常用的函数都被“简”掉了,导致有很多网上一搜一大把的画图算法用不上。所以用OpenGL-ES画图,这个感觉难度非常高。

在cocos2d-x中,OpenGL-ES一般在draw()这个函数里面调用其相关函数。当然cocos2d-x也封装了几个常用的画图函数:ccDrawLine,ccDrawCircle等,当然cocos2d-x也提供了例子,在tests里可以轻松找到。

优点

暂时没想到,因为我本身对OpenGL-ES不熟…

缺点

实现难度大可以拦截一大批人了,感觉。因为不能像CCRenderTexture那样在touch事件中进行绘图,所以一般会把要画的CCPoint在touch事件的记录下来,然后在draw()这个函数里遍历之,以实现绘图效果。

移动过的点一般都要保存下来,注意的是要全部保存,如果只保存当前点的话,draw()就只会画一个点,画出来的效果就像一个“光点”跟随的鼠标移动,而不是绘图。一般画一幅画,鼠标都会拖动出N个点,如果只是简单的vector保存的话,vector会超大,draw中遍历它也很耗时,导致没一会帧数就掉光了。具体怎么保存看数据结构吧,同事以线段作为数据结构来记录点,这样消耗不大,帧数也能保持稳定。

另外一个缺点就是如果算法实现不好,画出来的效果很坑爹,同事的线段法虽然能很流畅的画线,但是锯齿问题很严重,开了OpenGL的抗锯齿也没效果。如果对OpenGL-ES很熟而且算法也很牛的话,也许draw()是最快最好的一种画图法了。

最后还一个超坑爹的缺点:draw()在Google那台三星手机上,始终画在最顶层显示,然后线条就会把游戏UI遮盖住了,无论怎么设置z-Order都没用,估计是Google的三星手机的OpenGL-ES做过什么特殊处理吧,导致“坑爹啊…”

[ 万恶的锯齿…]

例子

Cocos2d-x提供的相关例子(DrawPrimitivesTest),常见的画直线、画圆、画Bezier线等,都有函数提供,具体还是自己打开tests看看源代码吧,这里就不详述了。

[ DrawPrimitivesTest ]

CCSpriteBatchNode

自己的理解

用CCSpriteBatchNode生成的CCSprite共用一个纹理,这样的好处是生成很多相同的CCSprite很高效,帧数可以很高很稳定。由于这个特点,用来实现粒子效果是一个很好的选择,不过我还没有看过cocos2d-x粒子系统的实现,这里不做推测,以免误导大家。关于CCSpriteBatchNode的用法当然还是tests里面有,有兴趣的朋友可以自己看看。

优点

由于draw()实现难度太高,而CCRenderTexture又有花屏的问题,所以尝试用CCSpriteBatchNode来实现画图,绘图效果很不错,因为是使用CCSprite做自定义笔刷嘛。帧数保持58-60,很稳定(如果只是单纯的创建CCSprite*,然后addChild到Layer里,掉帧会很严重的)

缺点

虽然CCSpriteBatchNode效果很不错,不过也有一个致命的缺点,就是CCSpriteBatchNode*对象不能addChild太多的CCSprite*对象,同事做了一下实验,大概addChild到16000+个CCSprite后,CCSpriteBatchNode就不能addChild了,也就是说,画图画到16000+个点后,画笔就“没墨水”,导致鼠标再怎么拖都没效果。

查看了一下源代码,大概是CCSpriteBatchNode在addChild时会重新分配内存,当需要分配的内存很大时,回导致内存分配失败,从而CCSpriteBatchNode会将这次addChild无效掉。

解决思路有一个,就是来个计数,当CCSpriteBatchNode它addChild到10000个后,用CCRenderTexture截个图保存当前的画图记录,然后清空CCSpriteBatchNode和把计数置零,再来画图。这个操作会有延迟,所以没有实现。

CCRibbon

自己的理解

CCRibbon应该说是一个线段集吧,与上述方法不同的是,它只能是单一颜色。就是说,你将它setColor为红,那么你画过的线条就全部为红,为蓝的话,则线条全部为蓝。

生成一个CCRibbon*对象需要指定:笔刷的宽度,笔刷的图片,线段的长度,笔刷的颜色等参数(Fade最后这个参数暂时还没搞懂意思…)。

CCRibbon提供addPointAt(CCPoint location, float width),将点以多宽加入到CCRibbon中,这里cocos2d-x对这个点的大小进行计算,从而使线条达到“头尾窄,身体宽”的效果。这个可以说是优点也可以说是缺点吧,“头尾窄,身体宽”看起来比较像笔刷,不过想做出均匀的画笔就不行了。

优点

帧数稳定,笔刷效果不错。因为CCRibbon也是用draw()进行画图,所以不用担心CCRenderTexture那样的花屏问题,CCRibbon目前感觉是比较理想的画图方法了。

缺点

如果在(100,100)点上一个点,然后跑去(400,400)再点一个点,CCRibbon会自动将两个点连起来,如果用户想做出平常画图那种“刷刷刷“的排线法,CCRibbon就不行了。解决方法就是每次TouchBegan都生成一个CCRibbon,这样就不会出现这个问题了,不过生成太多的CCRibbon不知道会不会出现其他问题,比如CCSpriteBatchNode那个…

由于CCRibbon是单一颜色的,所以想画彩色图是不行的。解决方法当然还是像上面那样,生个多个CCRibbon*对象,每个CCRibbon*对象的颜色不同就行了。

最后感觉不太人性化的就是画笔只能“头尾窄,身体宽“,如果想画出”头身尾均匀“的线条,用CCRibbon也许做不了。

例子

Cocos2d-x没有直接给出CCRibbon的例子,所以这个不能够在tests上看到使用方法,不过自己稍稍尝试一下就行了,用法挺简单。

posted @ 2013-06-24 21:27  爱生活,爱编程  阅读(384)  评论(0编辑  收藏  举报