1.纹理像素格式
纹理优化工作的另一重要的指标是纹理像素格式能够最大程度满足用户对保真度要求的情况下选择合适的像素格式可以大幅提高纹理的处理速度。而且纹理像素格式有与硬件有这密切的关系。
下面我们先了解一下纹理像素的格式主要的格式有
RGBA8888。32位色它是默认的像素格式每个通道8位比特每个像素4个字节。
BGRA8888。32位色每个通道8位比特每个像素4个字节。
RGBA4444。16位色每个通道4位比特每个像素2个字节。
RGB888。24位色没有Alpha通道所以没有透明度。每个通道8位比特每个像素3个字节。
RGB565。16位色没有Alpha通道所以没有透明度。R和B通道是各5位G通道是6。
RGB5A1或RGBA5551。16位色每个通道各4位Alpha通道只用1位表示。
PVRTC4。4位PVR压缩纹理格式PVR格式是专门为iOS设备上面的PowerVR图形芯片而设计的。它们在iOS设备上非常好用因为可以直接加载到显卡上面而不需要经过中间的计算转化。
PVRTC4A。具有Alpha通道的4位PVR压缩纹理格式。
PVRTC2。2位PVR压缩纹理格式。
PVRTC2A。具有Alpha通道的2位PVR压缩纹理格式。
此外PVR格式在保存的时候还可以采用Gzip和zlib压缩格式进行压缩对应的保存文件为pvr.gz和pvr.ccz。经过压缩文件会更小加载的时候使用更少的内存虽然是转化为纹理的时候需要解压但对于CPU影响很小。
2.纹理缓存异步加载
我们在启动游戏和进入场景时候由于需要加载的资源过多就会比较“卡”用户体验不好。我们可以采用纹理缓存TextureCache异步加载纹理图片TextureCache类异步加载函数如下
virtual void addImageAsync(const std::string & filepath,
std::function< void(Texture2D *)> callback
)
其中第一个参数文件路径第二参数是回调函数。下面我们通过一个实例介绍一下纹理缓存异步加载使用有200张小图片加载到纹理缓存加载过程会有一个进度显式在界面上如图20-25所示。
纹理缓存异步加载实例
HelloWorldScene.cpp中主要代码如下
bool HelloWorld::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , origin.y + closeItem->getContentSize().height/2)); auto menu = Menu::create(closeItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); _labelLoading = Label::createWithTTF ("loading...", "fonts/Marker Felt.ttf", 35); _labelPercent = Label::createWithTTF ("0%%", "fonts/Marker Felt.ttf", 35); _labelLoading->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2 - 20)); _labelPercent->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2 + 20)); this->addChild(_labelLoading); this->addChild(_labelPercent); _numberOfLoadedSprites = 0; _imageOffset = 0; auto sharedFileUtils = FileUtils::getInstance(); std::string fullPathForFilename = sharedFileUtils->fullPathForFilename("ImageMetaData.plist"); ① ValueVector vec = FileUtils::getInstance()->getValueVectorFromFile(fullPathForFilename); ② _numberOfSprites = vec.size(); ③ //加载纹理 for( auto& e : vec) ④ { auto row = e.asValueMap(); auto filename = "icons/" + row.at("filename").asString(); Director::getInstance()->getTextureCache()->addImageAsync(filename, CC_CALLBACK_1(HelloWorld::loadingCallBack, this)); ⑤ } return true; } void HelloWorld::loadingCallBack(Texture2D *texture) ⑥ { ++_numberOfLoadedSprites; __String* str = __String::createWithFormat("%d%%", (int)(((float)_numberOfLoadedSprites / _numberOfSprites) * 100)); ⑦ _labelPercent->setString(str->getCString()); ⑧ Size visibleSize = Director::getInstance()->getVisibleSize(); int i = ++_imageOffset * 60; auto sprite = Sprite::createWithTexture(texture); ⑨ sprite->setAnchorPoint(Vec2(0,0)); addChild(sprite, -1); sprite->setPosition(Vec2( i % (int)visibleSize.width, (i / (int)visibleSize.width) * 60)); if (_numberOfLoadedSprites == _numberOfSprites) ⑩ { _numberOfLoadedSprites = 0; } }
上述代码第①行代码是获得资源目录下ImageMetaData.plist 文件全路径ImageMetaData.plist 文件是我们定义用来描述要加载图标文件名文件内容如下
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <dict> <key>filename</key> <string>01-refresh.png</string> </dict> <dict> <key>filename</key> <string>02-redo.png</string> </dict> <dict> <key>filename</key> <string>03-loopback.png</string> </dict> <dict> <key>filename</key> <string>04-squiggle.png</string> </dict> … … </array> </plist>
ImageMetaData.plist 文件是属性列表文件内部结构是数组类型我们可以通过第②行代码FileUtils 的getValueVectorFromFile函数读入到ValueVector类型变量vec中。第③行代码_numberOfSprites = vec.size()是获得数组的长度然后赋值给成员变量_numberOfSprites为了能够计算加载进度。
第④行代码是循环遍历数组数组结构中的每一个元素是键值对结构取的键值对结构语句是auto row = e.asValueMap()。然后通过语句row.at("filename").asString()从键值对对象row中取出键为filename对应的值。
第⑤行代码是调用TextureCache的addImageAsync函数实现异步加载图片缓存HelloWorld::loadingCallBack是回调函数this参数表示回调函数的目标对象。
第⑥行是我们定义的回调函数实现。第⑦行代码在的表达式(int)(((float)_numberOfLoadedSprites / _numberOfSprites) * 100)可以计数出加装进度"%d%%"可以显示百分号其中的%d是格式化输出数字。%%是输出%前面%起到转义作用。第⑧行代码_labelPercent->setString(str->getCString())是设置进度标签_labelPercent的内容。
第⑨行代码auto sprite = Sprite::createWithTexture(texture)是通过纹理对象texture创建精灵对象。第⑩行代码if (_numberOfLoadedSprites == _numberOfSprites)是判断是否完成任务_numberOfLoadedSprites是已经加装的图片数_numberOfSprites是要加装的全部图片数。
更多内容请关注最新Cocos图书《Cocos2d-x实战 C++卷》
本书交流讨论网站http://www.cocoagame.net
更多精彩视频课程请关注智捷课堂Cocos课程http://v.51work6.com
欢迎加入Cocos2d-x技术讨论群257760386
《Cocos2d-x实战 C++卷》现已上线各大商店均已开售
京东http://item.jd.com/11584534.html
当当http://product.dangdang.com/23606265.html
互动出版网http://product.china-pub.com/3770734
《Cocos2d-x实战 C++卷》源码及样章下载地址
源码下载地址http://51work6.com/forum.php?mod=viewthread&tid=1155&extra=page%3D1
样章下载地址http://51work6.com/forum.php?mod=viewthread&tid=1157&extra=page%3D1
欢迎关注智捷iOS课堂微信公共平台