首先咱們講點話外的東西,異步載入:衆所周知。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支持還需要發展。