我的Cocos2d-x學習筆記(八)利用CCSpriteBatchNode進行優化


OpenGL是一個基於C語言的三維圖形API,是一個開放的、跨平台的圖形接口。

OpenGL ES是OpenGL在移動設備上的版本。

Cocos2d-x是一個基於OpenGL的游戲引擎,渲染功能由OpenGL實現。

游戲中會用到許多圖片資源,對圖片資源渲染進行優化能明顯提高效率。

OpenGL中紋理的長和寬像素是2的冪,大小不足的紋理補充到2的冪大小;可以通過把多張小圖片合成一張大圖加載到游戲中,減少紋理加載次數,減少補齊2的冪大小的空白。

之前學習的紋理緩存、精靈幀緩沖可以把紋理等預先加載到內存中,訪問時候節省訪問時間;除此之外還可以通過CCSpriteBatchNode節省渲染次數來達到優化的目的。

CCSpriteBatchNode(精靈批處理類):

原理借鑒一下權威指南內容:

    當你需要顯示兩個或兩個以上相同的精靈時,如果逐個渲染精靈,每一次渲染都會調用OpenGL的函數;

    因為當系統在屏幕上渲染一張貼圖的時候,圖形處理硬件必須首先准備渲染,然后渲染圖形,最后完成渲染以后的清理工作。

    以上是每次渲染固定的開銷,這樣幀率就會下降15%左右或者更多。
    如果將所有需要渲染的同一張貼圖只進行一次准備,一次渲染,一次清理就可以解決這個問題了。

    這時可以使用CCSpriteBatchNode類來批處理這些精靈。

CCSpriteBatchNode:

先來看看它的創建相關代碼:

class CC_DLL CCSpriteBatchNode : public CCNode, public CCTextureProtocol
{
public:
	static CCSpriteBatchNode* create(const char* fileImage, unsigned int capacity);
	static CCSpriteBatchNode* create(const char* fileImage)
	{
		return CCSpriteBatchNode::create(fileImage, kDefaultSpriteBatchCapacity);
	}
	static CCSpriteBatchNode* createWithTexture(CCTexture2D* tex, unsigned int capacity);
	static CCSpriteBatchNode* createWithTexture(CCTexture2D* tex) 
	{
		return CCSpriteBatchNode::createWithTexture(tex, kDefaultSpriteBatchCapacity);
	}
}
    由上述代碼可以看到CCSpriteBatchNode可以通過圖片文件直接創建,也可以通過紋理來創建。

    CCSpriteBatchNode

(一)、通過圖片文件創建CCSpriteBatchNode並且使用它

	static CCSpriteBatchNode* create(const char* fileImage, unsigned int capacity);
	static CCSpriteBatchNode* create(const char* fileImage)
	{
		return CCSpriteBatchNode::create(fileImage, kDefaultSpriteBatchCapacity);
	}
通過紋理圖片直接創建精靈批處理我們可以使用兩個創建函數,不過由上述代碼可以看出其實只有一個創建函數;

只指定紋理圖片路徑名稱時候,其第二個參數capacity(表示紋理圖像容量)為一個系統默認值,並且此函數調用的為兩個參數的create函數。

實例:

	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::create("HelloWorld.png");
	for (int i = 0; i < 50; i++)
	{
		CCSprite* sprite = CCSprite::create("HelloWorld.png");
		batchNode->addChild(sprite);
	}
	addChild(batchNode);
首先,通過紋理圖片創建一個精靈批處理;

之后,通過循環創建50個精靈,把這50個精靈添加到批處理當中;

最后把批處理加入到父節點。

(二)通過CCTexture2D創建CCSpriteBatchNode並且使用它

實例一:通過紋理緩存中取得紋理創建精靈批處理,此后創建精靈時候可以使用紋理圖片名字創建。

	CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("HelloWorld.png");
	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::createWithTexture(texture);
	for (int i = 0; i < 29; i++)
	{
		CCSprite* sprite = CCSprite::create("HelloWorld.png");
		batchNode->addChild(sprite);
	}
	addChild(batchNode);

	CCTexture2D * texture = CCTextureCache::sharedTextureCache()->addImage("HelloWorld.png");
	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::createWithTexture(texture);
	for (int i = 0; i < 50; i++)
	{
		CCSprite* sprite = CCSprite::createWithTexture(texture);
		batchNode->addChild(sprite);
	}
	addChild(batchNode);

上訴兩種方式實際上使用起來同樣效果,解釋如下:

首先,通過紋理緩存獲取一個紋理;

之后,通過循環創建50個精靈,把這50個精靈添加到批處理當中,此時創建精靈的時候可以使用紋理圖片名稱,也可以使用之前從紋理緩沖中獲取的紋理;

最后把批處理加入到父節點。

實例二:通過直接創建一個紋理(CCTexture2D)來創建精靈批處理,此后精靈創建時候必須使用之前創建的紋理來創建精靈。

	CCImage* image = new CCImage();
	image->initWithImageFile("HelloWorld.png");
	image->autorelease();
	CCTexture2D* texture = new CCTexture2D();
	texture->initWithImage(image);
	texture->autorelease();

	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::createWithTexture(texture);
	for (int i = 0; i < 50; i++)
	{
		CCSprite* sprite = CCSprite::createWithTexture(texture);
		batchNode->addChild(sprite);
	}
	addChild(batchNode);

首先,通過new的方式獲取一個紋理;

之后,通過循環創建50個精靈,把這50個精靈添加到批處理當中,此時的精靈需要用到之前創建的紋理來創建;

最后把批處理加入到父節點。

實例三:加載多張圖片使用

	CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("batch.plist");
	CCSpriteBatchNode* batchNode = CCSpriteBatchNode::create("bach.png");
	addChild(batchNode);

上訴代碼在精靈幀緩沖中加入一個plist文件;

利用plist對應的圖片創建CCSpriteBatchNode;

之后

	static bool flag = true;
	CCSprite * sprite;
	for (int i = 0; i < 1000; i++)
	{
		if (flag)
		{
			sprite = CCSprite::createWithSpriteFrameName("one.png");
		}
		else{
			sprite = CCSprite::createWithSpriteFrameName("two.png");
		}
		flag = !flag;
		sprite->setPosition(ccp(CCRANDOM_0_1() * 480, CCRANDOM_0_1() * 320));
		batchNode->addChild(sprite);
	}
之前把紋理圖片添加到精靈幀緩沖中后使用CCSpriteBatchNode創建同一張圖片;

此后通過精靈幀緩沖中的精靈幀創建精靈同樣為優化后的。


總結:

    當我們需要多次使用同一張紋理創建的精靈時候使用它。

     因為所有CCSprite節點都添加到同一個CCSpriteBatchNode中,所以所有CCSprite的zOrder相同。

     添加到同一個CCSpriteBatchNode中的CCSprite必須使用同一個紋理圖片。

     精靈幀緩沖(CCSpriteFrameCache)與精靈批處理(CCSpriteBatchNode)結合使用效果更好!

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM