標籤:ccaction ccsprite ccanimate ccanimation cocos2d-x
原創文章,轉載請註明出處:http://blog.csdn.net/sfh366958228/article/details/38850499
前言
在Cocos2d-x中對圖片得封裝是通過CCImage來完成,該類實現了對於不同類型圖片得讀取、解析、像素資訊儲存。由於在引擎內部封裝,一般情況下不需要修改此類,由於Cocos2d-x使用了Open GL的圖形庫,因此在圖片顯示在螢幕的過程中是通過在3D空間的某個平面通過紋理貼圖的方式完成的圖片顯示,在Cocos2d-x中通過CCTexture2D來實現。
在紋理處理中有如下一些常用類:
CCImage // 調用libpng libjpg來讀取圖片的像素資訊
CCTexture2D // 封裝紋理對象
CCTextureCache // 一組紋理對象,通過CCDictionary管理,通過字元key擷取
CCRenderTexture // 建立動態紋理
CCSprite // 實現紋理顯示
CCSpriteFrame // 用來定義動畫層的每一幀,定義好厚以CCAction的形式作用到一個CCSprite上來呈現動畫效果
CCSpriteBatchNode //
CCSpriteFrameCache // 一組紋理對象,通過CCDictionary管理,通過字元key擷取
CCAnimation // 實現一組Sprite播放的Action
根據圖片檔案建立CCSprite
CCSprite * sprite = CCSprite::create("HelloWorld.png");利用create方法完成了對圖片紋理的載入,我們來看看建立過程的源碼
CCSprite* CCSprite::create(const char *pszFileName, const CCRect& rect){ CCSprite *pobSprite = new CCSprite(); //建立一個CCSprite對象 if (pobSprite && pobSprite->initWithFile(pszFileName, rect)) // 如果成功建立,且初始化成功 { pobSprite->autorelease(); // 添加到自動釋放管理CCPoolManager中 return pobSprite; } CC_SAFE_DELETE(pobSprite); // 建立失敗,安全刪除 return NULL;}bool CCSprite::initWithFile(const char *pszFilename, const CCRect& rect){ CCAssert(pszFilename != NULL, ""); // 檔案名稱不可為空 CCTexture2D *pTexture = CCTextureCache::sharedTextureCache()->addImage(pszFilename); // 將圖片添加至紋理緩衝中,並擷取對應的CCTexture對象 if (pTexture) // 如果對象不為空白,返回initWithTexture { return initWithTexture(pTexture, rect); } return false;}bool CCSpriteFrame::initWithTexture(CCTexture2D* pobTexture, const CCRect& rect){ CCRect rectInPixels = CC_RECT_POINTS_TO_PIXELS(rect); // 點矩形轉像素矩形 return initWithTexture(pobTexture, rectInPixels, false, CCPointZero, rectInPixels.size);}bool CCSpriteFrame::initWithTexture(CCTexture2D* pobTexture, const CCRect& rect, bool rotated, const CCPoint& offset, const CCSize& originalSize){ m_pobTexture = pobTexture; if (pobTexture) { pobTexture->retain(); } m_obRectInPixels = rect; m_obRect = CC_RECT_PIXELS_TO_POINTS(rect); m_obOffsetInPixels = offset; m_obOffset = CC_POINT_PIXELS_TO_POINTS( m_obOffsetInPixels ); m_obOriginalSizeInPixels = originalSize; m_obOriginalSize = CC_SIZE_PIXELS_TO_POINTS( m_obOriginalSizeInPixels ); m_bRotated = rotated; return true;}
根據CCTexture2D紋理對象建立CCSprite有時候,為了讓圖片資源更小,會根據一張圖片來建立不同的CCSprite,這樣需要首先通過CCTextureCache載入圖片到圖片紋理的緩衝,然後從緩衝擷取這張圖片的CCTexture2D對象,根據這個對象來建立CCSprite,代碼如下:
CCTexture2D *texture = CCTextureCache()::sharedTextureCache()->addImage("Player.png");CCSprite *sprite = CCSprite::createWithTexture(texture, CCRectMake(0, 0, 85, 121));CCRectMake是指定一個裁剪地區,該方法實現了將紋理對象texture的一部分地區建立一個CCSprite圖層。
CCSprite* CCSprite::createWithTexture(CCTexture2D *pTexture, const CCRect& rect){ CCSprite *pobSprite = new CCSprite(); if (pobSprite && pobSprite->initWithTexture(pTexture, rect)) { pobSprite->autorelease(); return pobSprite; } CC_SAFE_DELETE(pobSprite); return NULL;}createWithTexture和create方法幾乎類似。
使用CCSpriteFrame建立CCSpriteCCSpriteFrame是用來定義動畫層的每一幀,定義好以後以CCAction的形式作用到一個CCSprite上來呈現動畫效果,一般情況下會用這個動畫的第一幀來建立CCSprite:
CCTexture2D *texture = CCTextureCache()::sharedTextureCache()->addImage("Player.png");CCSpriteFrame spriteFrame01 = CCSpriteFrame::createWithTexture(texture, CCRectMake(132 * 0, 132 * 0, 132, 132));CCSprite *sprite = CCSprite::createWithSpriteFrame(spriteFrame01);而CCSpriteFrame的建立除了直接通過CCTexture2D對象之外,還可以通過讀取紋理工具(Cocos Studio)匯出的plist檔案來建立。
CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache();cache->addSpriteFramesWithFile("grossini.plist");CCArray *aniFrames = CCArray::createWithCapacity(14);char str[100] = {0};for (int k = 0; k < 14; ;++){sprintf(str, "grossini_dance_%02d.png", (k+1));CCSpriteFrame *frame = cache->spriteFrameByName(str);animFrames->addObject(frame);}通過grossini.plist將圖片剪裁程多幀,在使用的時候通過spriteFrameByName方法從CCSpriteFrameCache擷取每一幀,通過工具軟體產生plist,通過上述方法解析plist,能大大加快程式開發的效率。
使用CCAnimate和CCAnimation建立動畫
// 序列幀載入方法1 - 逐圖載入CCAnimation *animation = CCAnimation::create();char str[100] = {0};for(int i = 1; i <= 14; i++){ sprintf(str, "grossini_dance_%02d.png", i); animation->addSpriteFrameWithFileName(str);}animation->setDelayPerUnit(0.2);animation->setRestoreOriginalFrame(false);sprite->runAction(CCAnimate::create(animate));// 序列幀載入方法2 - 切圖法CCArray* animFrames = CCArray::createWithCapacity(14);CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("grossini_dance_atlas_nomipmap.png");for (int i = 0; i < 14; i++) { CCSpriteFrame* spriteFrame = CCSpriteFrame::createWithTexture(texture, CCRectMake(40 * i % 5, 57 * i / 5, 40, 57)); animFrames->addObject(spriteFrame);}CCAnimation *animation = CCAnimation::createWithSpriteFrames(animFrames, 0.2f);sprite->runAction(CCAnimate::create(animation));
用CCSpriteBatchNode進行文理貼圖的最佳化
在情境中隨機產生100個相同的精靈,看看使用CCSpriteBatchNode最佳化前和最佳化後兩種不同的效果。
// 最佳化前for (int i = 0; i < 100; i++){ CCSprite *sp = CCSprite::create("Icon.png"); int x = arc4random()%480; int y = arc4random()%320; sp->setPosition(CCPointMake(x, y)); this->addChild(sp);}// 最佳化後CCSpriteBatchNode* batchNode = CCSpriteBatchNode::create("Icon.png", 10);batchNode->setPosition(CCPointZero);this->addChild(batchNode);for (int i=0; i<100; i++){ CCSprite *sp = CCSprite::create("Icon.png"); int x = arc4random()%480; int y = arc4random()%320; sp->setPosition(CCPointMake(x, y)); batchNode->addChild(sp);}
效果(最佳化前):
效果(最佳化後):
最佳化了之後,明顯的看的出第一幅圖第一個參數是100,也就是說精靈渲染了100次,這是比較消耗資源的。第二幅圖,第一個參數只渲染一次。還有就是由於模擬器調用的是PC的記憶體所以記憶體比較大,對第三個參數是不會有多大的影響的,但如果是真機調試的話效果會很明顯,第一種情況會明顯的比較卡。
Cocos2d-x學習筆記(九)紋理CCTexture2D和精靈CCSprite