首先咱们讲点话外的东西,异步载入:众所周知。loading里面通常都是载入数据的,那么是怎么载入的呢?css
Director::getInstance()->getTextureCache()->addImageAsync(const std::string &path, const std::function<void(Texture2D*)>& callback)//參数1。文件路径,參数2,回调函数(通常都是进度条)
那么假设咱们要载入帧动画呢?html
auto frameache=SpriteFrameCache::getInstance(); frameache->addSpriteFramesWithFile(" xxxxxx ");//參数。plist文件路径
可是这样并不是异步载入。那么应该怎么办?事实上仍是用上面这两个:ios
Director::getInstance()->getTextureCache()->addImageAsync(const std::string &path, const std::function<void(Texture2D*)>& callback);//咱们首先异步载入了纹理 auto My_Texture2D=Director::getInstance()->getTextureCache()->addImage(" ");
//假设咱们成功异步载入图片以后,咱们可以从纹理缓存里面,即std::unordered_map<std::string,Texture2D*> _textures 返回相应key的纹理。而key在引擎源码中则是文件的完整路径,因为在texture2d里面会作一步std::string fullpath =FileUtils::getInstance()->fullPathForFilename(path);而咱们外部用的话,仅仅需要平时resources的路径就能够。json
或者直接auto cache=SpriteFrameCache::getInstance(); cache->addSpriteFramesWithFile("plist路径","png路径");缓存
auto frameache=SpriteFrameCache::getInstance(); frameache->addSpriteFramesWithFile(" xxxxxx ",My_Texture2D);//參数1。plist文件路径,參数2,纹理 这样咱们就能完毕异步载入帧动画了~
进入正题 刀塔传奇:安全
首先咱们解压dota的包。会发现有异步
一张背景为黑色的jpg图和一张灰度图,对不是带alpha的png图,而是无alpha的jpg。那么刀塔传奇为何要这么作呢?编辑器
下面为我我的的理解:ide
jpg图是将图像像素进行了压缩。而另一张灰度图实际上则是附带了透明通道的8位的png,那么咱们仅仅要将灰度图的alpha复制过去,就能实现jpg的背景镂空。函数
这种话就能缩小图片的资源大小。毕竟你jpg是通过压缩的。同等镂空的png果断是要大很是多的,这里可以肯定jpg+8位灰度<png。
那么这样作的优点在哪里呢,没错,就是在图片资源很是多的状况下。咱们可以清楚得感觉到使用这种图片格式的优势:1、可以使你的应用程序更小,因为图片是压缩过了的。2、你的游戏可以启动地更快。
原理上和pvr.ccz有点类似。可是pvr.ccz有着它独特的优点,就是pvr格式可以直接被ios的显卡所承认。比png更加安全,避免大量图片载入的内存问题。
而后呢。咱们应该怎么用jpg+灰度图实现纹理镂空的效果呢?
看引擎代码!
Texture2D * TextureCache::addImage(const std::string &path) { Texture2D * texture = nullptr; Image* image = nullptr; // Split up directory and filename // MUTEX: // Needed since addImageAsync calls this method from a different thread std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);//获取完整路径 if (fullpath.size() == 0) { return nullptr; } auto it = _textures.find(fullpath);//在缓存中查找是不是已经载入过的纹理图片 if( it != _textures.end() ) texture = it->second; if (! texture)//假设是未被加过的纹理 { // all images are handled by UIImage except PVR extension that is handled by our own handler do { image = new Image();//建立一个image对象,imgae对象中封装了libjpeg,即jpg的解压/压缩库,另外利用了FileUtils::getInstance()->getDataFromFile(_filePath) FileUtils默认会以rb模式读取二进制的数据信息 CC_BREAK_IF(nullptr == image); bool bRet = image->initWithImageFile(fullpath);//将FileUtiles读取的数据用jpeg进行解压,期间有个图片格式的推断 CC_BREAK_IF(!bRet); texture = new Texture2D(); if( texture && texture->initWithImage(image) )//载入纹理将rgb888的jpg转为rgba8888 { #if CC_ENABLE_CACHE_TEXTURE_DATA // cache the texture file name VolatileTextureMgr::addImageTexture(texture, fullpath); #endif // texture already retained, no need to re-retain it _textures.insert( std::make_pair(fullpath, texture) ); } else { CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache", path.c_str()); } } while (0); } CC_SAFE_RELEASE(image); return texture; } /*.. 省略 */ *outDataLen = dataLen/3*4;//将rgb的length增加到rgba的长度 *outData = new unsigned char[*outDataLen];//申请一块长度为rgba长度的内存 auto TempData=outData; /*.. 省略 */ for (ssize_t i = 0, j=0,l = dataLen - 2; i < l; i += 3,++j) { * outData ++ = data[i]; //R * outData ++ = data[i + 1]; //G * outData ++ = data[i + 2]; //B * outData ++ =png_data[j]; //A 依据灰度图的像素信息0和255设置alpha } auto new_Texture2d=new Texture2D(); new_Texture2d->initWithData(TempData,datalen。pixelFormat, imageWidth, imageHeight, imageSize);
//这样咱们就能实现刀塔传奇的主界面效果。
至于主界面中的比方泉水发光的效果,则是经过shader实现的
至于dota的骨骼部分听说是他们本身的flash引擎作的,而我则用spine作了骨骼,因为cocostuio的骨骼功能不无缺,spine则是专门针对骨骼的编辑器。并且全平台支持,u3d,libgdx。as3等等。
最赞的应该就是spine的ffd,蒙皮了。
眼下正在研究binary,即spine的二进制文件导出。直接读取binary建立骨骼的话,将会比json读取的更快。内存占用更小。
ps:cocos2dx 3.1rc0出了,支持prite3d和video。眼下感受video应该是比較有用的,3d的话,我的感受仍是u3d吧。。。
cocos的3d支持还需要发展。