CCSpriteBatchNode
它是批處理繪製精靈,主要是用來提高精靈的繪製效率的,需要繪製的精靈數量越多,效果越明顯。因爲cocos2d-x採用opengl es繪製圖片的,opengl es繪製每個精靈都會執行:open-draw-close流程。而CCSpriteBatchNode是把多個精靈放到一個紋理上,繪製的時候直接統一繪製該texture,不需要單獨繪製子節點,這樣opengl
es繪製的時候變成了:open-draw()-draw()…-draw()-close(),節省了多次open-close的時間。CCSpriteBatchNode內部封裝了一個CCTextureAtlas(紋理圖集,它內部封裝了一個CCTexture2D)和一個CCArray(用來存儲CCSpriteBatchNode的子節點:單個精靈)。注意:因爲繪製的時候只open-close一次,所以CCSpriteBatchNode對象的所有子節點都必須和它是用同一個texture(同一張圖片),類似下面這樣的圖片,4個貝殼都在同一紋理上:
在addChild的時候會檢查子節點是不是Sprite類型,紋理的名稱跟CCSpriteBatchNode的是不是一樣,如果不一樣就會出錯,源碼:
void SpriteBatchNode::addChild(Node *child, int zOrder, int tag)
{
CCASSERT(child != nullptr, "child should not be null");
CCASSERT(dynamic_cast<Sprite*>(child) != nullptr, "CCSpriteBatchNode only supports Sprites as children");
Sprite *sprite = static_cast<Sprite*>(child);
// check Sprite is using the same texture id
CCASSERT(sprite->getTexture()->getName() == _textureAtlas->getTexture()->getName(), "CCSprite is not using the same texture id");
Node::addChild(child, zOrder, tag);
appendChild(sprite);
}
再看看3.0版本里的draw部分
void SpriteBatchNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
// Optimization: Fast Dispatch
if( _textureAtlas->getTotalQuads() == 0 )
{
return;
}
for(const auto &child: _children)
child->updateTransform();
_batchCommand.init(
_globalZOrder,
getGLProgram(),
_blendFunc,
_textureAtlas,
transform);
renderer->addCommand(&_batchCommand);
}
向渲染器裏添加里一個BatchCommand,跟到BatchCommand裏
void BatchCommand::execute()
{
// Set material
_shader->use();
_shader->setUniformsForBuiltins(_mv);
GL::bindTexture2D(_textureID);
GL::blendFunc(_blendType.src, _blendType.dst);
// Draw
_textureAtlas->drawQuads();
}
當程序準備渲染SpriteBatchNode裏的精靈時,這個函數就會被調用。裏面調用了TextureAtlas的drawQuads對精靈進行批量繪製下面是使用CCSpriteBatchNode的使用代碼示例:
1
2
3
4
5
6
7
8
9
10
11
12
|
CCSpriteBatchNode*
BatchNode1 = CCSpriteBatchNode::batchNodeWithFile( "Images/grossini_dance_atlas.png" ,
50); addChild(BatchNode1,
0, kTagSpriteBatchNode); CCSpriteBatchNode*
BatchNode = (CCSpriteBatchNode*) getChildByTag( kTagSpriteBatchNode ); int idx
= CCRANDOM_0_1() * 1400 / 100; int x
= (idx%5) * 85; int y
= (idx/5) * 121; CCSprite*
sprite = CCSprite::spriteWithTexture(BatchNode->getTexture(), CCRectMake(x,y,85,121)); BatchNode->addChild(sprite); sprite->setPosition(
ccp( p.x, p.y) ); |