在quick-cocos2d-x中对非2的幂纹理进行平铺操作
在quick-cocos2d-x中对非2的幂纹理进行平铺操作
tile use NPOT texture in quick-cocos2d-x
本文基于 quick 2.2.1rc 版本
在 quick 的 framework.display 包中,有这样一个方法实现图片的平铺:
1function display.newTilesSprite(filename, rect)
2 if not rect then
3 rect = CCRect(0, 0, display.width, display.height)
4 end
5 local sprite = CCSprite:create(filename, rect)
6 if not sprite then
7 echoError("display.newTilesSprite() - create sprite failure, filename %s", tostring(filename))
8 return
9 end
10
11 local tp = ccTexParams()
12 tp.minFilter = 9729
13 tp.magFilter = 9729
14 tp.wrapS = 10497
15 tp.wrapT = 10497
16 sprite:getTexture():setTexParameters(tp)
17 CCSpriteExtend.extend(sprite)
18
19 display.align(sprite, display.LEFT_BOTTOM, 0, 0)
20
21 return sprite
22end
这里直接通过调整 OpenGL ES 的纹理渲染参数来实现平铺,性能相当好。
但使用这个方法有个限制,就是被平铺的纹理必须是2的幂(POT, Power Of Two)。
于是,我尝试使用 CCSpriteBatchNode 来对纹理进行平铺,达到不用2的幂(NPOT)的纹理即可进行平铺的目的。
但是这个方法也有一个问题。当对这个 CCSpriteBatchNode 进行缩放的时候,平铺的纹理之间会出现非常细的空隙,导致最终看起来的效果像是栅栏一样,无法实现无缝平铺的效果。
这种缩放并不一定需要主动进行。假设你的游戏做了多分辨率处理(在如今的世界,这是不可避免的),在不同的设备分辨率中,cocos2d-x 会根据分辨率进行缩放处理。 这种情况下也会出现这个问题。
一个可行的办法,是制作平铺图的时候,在图像边缘留1个像素的重复像素。在拼接的时候,将两个相邻的纹理互相覆盖1个像素。
我把这个功能封装成了 display.newTiledBatchNode 方法:
1-- 创建一个可平铺的 CCSpriteBatchNode,纹理的大小可以是非2的幂
2-- @param __fileName 与 display.newSprite 的第一个参数相同
3-- @param __texture plist文件,因为使用了BatchNode,必须传递plist文件
4-- @param __size 一个CCSize对象
5-- @param __hPadding 横向覆盖几个像素
6-- @param __vPadding 纵向覆盖几个像素
7-- @return a CCSpriteBatchNode
8
9function display.newTiledBatchNode(__fileName, __texture, __size, __hPadding, __vPadding)
10 __size = __size or cc.size(display.width, display.height)
11 __hPadding = __hPadding or 0
12 __vPadding = __vPadding or 0
13 local __sprite = display.newSprite(__fileName)
14 local __sliceSize = __sprite:getContentSize()
15 __sliceSize.width = __sliceSize.width - __hPadding
16 __sliceSize.height = __sliceSize.height - __vPadding
17 local __xRepeat = math.ceil(__size.width/__sliceSize.width)
18 local __yRepeat = math.ceil(__size.height/__sliceSize.height)
19 -- how maney sprites we need to fill in tiled node?
20 local __capacity = __xRepeat * __yRepeat
21 local __batch = display.newBatchNode(__texture, __capacity)
22 local __newSize = cc.size(0,0)
23 --printf("newTileNode xRepeat:%u, yRepeat:%u", __xRepeat, __yRepeat)
24 for y=0,__yRepeat-1 do
25 for x=0,__xRepeat-1 do
26 __newSize.width = __newSize.width + __sliceSize.width
27 __sprite = display.newSprite(__fileName)
28 :align(display.LEFT_BOTTOM,x*__sliceSize.width, y*__sliceSize.height)
29 :addTo(__batch)
30 --print("newTileNode:", x*__sliceSize.width, y*__sliceSize.height)
31 end
32 __newSize.height = __newSize.height + __sliceSize.height
33 end
34 __batch:setContentSize(__newSize)
35 return __batch, __newSize.width, __newSize.height
36end
这个方法已经加入了 quick 官方仓库的 develop 分支。
但是,这个方法无法处理这样的情景——平铺带有透明度的纹理。
- 文章ID:2054
- 原文作者:zrong
- 原文链接:https://blog.zengrong.net/post/tile_use_npot_texture_in_quick-cocos2d-x/
- 版权声明:本作品采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可,非商业转载请注明出处(原文作者,原文链接),商业转载请联系作者获得授权。