Sprite(精靈)全解
精靈是遊戲中十分重要的組成部分,隨處可見,如:遊戲背景、NPC、人物、道具等。在cocos2d-x引擎中,只要是用圖片展示的,基本上需要使用精靈類。
1. 首先來了解一下跟精靈相關的幾個類:
(1) Texture2D
可以把它看成一個紋理,它是cocos2d-x渲染圖形的重要參數,用來貼圖,因爲cocos2d-x使用openglES繪製2d圖形的,它的尺寸是2的n次方。一般通過以下方式獲得:
//cocos2d-x3.0beta的用法
Texture2D * texture
= Director::getInstance()->getTextureCache()->addImage("hero.png");
(2) Sprite
這個就是精靈類,是Node的子類,它的內部封裝了Texture2D(紋理),可以通過下面幾種方式初始化精靈對象。
static Sprite* create();
static Sprite* create(const std::string& filename);
//Rect表示圖片的指定範圍,即從圖片的指定矩形區域裁剪
static Sprite* create(const std::string& filename, const Rect& rect);
//Texture2D表示精靈包含的圖片,範圍是整張圖片
static Sprite* createWithTexture(Texture2D *texture);
//SpriteFrame表示精靈的某一幀,大多數情況下精靈本身的圖片有多幀。它內部封裝了Texture2D和Rect,可以從一個大圖片取出一部分作爲一幀。
static Sprite* createWithSpriteFrame(SpriteFrame *pSpriteFrame);
//SpriteFrameName表示幀的名字,根據幀名從內存中取出SpriteFrame
static Sprite* createWithSpriteFrameName(const std::string& spriteFrameName);
(3) TextureCache
它相當於Texture2D的容器,是內存池,用來緩存Texture2D對象的。當調用它的addImage函數添加圖片時,會先根據圖片名稱去內存中查找是否已存在,是則直接取出返回。
如果需要一次加載多張圖片的時候,可以先把圖片加載到TextureCache中,這樣使用圖片的時候速度就會很快了。
(4) SpriteFrameCache
它是管理SpriteFrame的內存池,跟TextureCache功能一樣,不過跟TextureCache不同的是,如果內存池中不存在要查找的幀,它會提示找不到,而不會去本地加載圖片。SpriteFrameCache一般用來處理plist文件(這個文件指定了每個獨立的精靈在這張“大圖”裏面的位置和大小),該文件對應一張包含多個精靈的大圖,plist文件可以使用TexturePacker製作。如下圖所示:
創建精靈方法:利用幀緩存中的一幀的名稱聲稱一個對象,適合於plist打包好的文件:
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("animations/grossini.plist", "animations/grossini.png");
sprite* hero = sprite::createWithSpriteFrameName("grossini_dance_01.png");
只要plist文件跟對應的png圖片在同一目錄下,且名字相同,則addSpriteFramesWithFile(“animations/ grossini.plist”, “animations / grossini.png”);
可以改成addSpriteFramesWithFile(“animations/grossini.plist”);
創建精靈方法:利用另外一幀生成一個精靈對象,適合於做幀動畫使用。
SpriteFrame* frame = SpriteFrame::create("icon.png", Rect(0, 0, 40, 30));
Sprite* sprite = Sprite::createWithSpriteFrame(frame);
(5) SpriteBatchNode
它是批處理繪製精靈,主要是用來提高精靈的繪製效率的,需要繪製的精靈數量越多,效果越明顯。因爲cocos2d-x採用opengl es繪製圖片的,opengl es繪製每個精靈都會執行:open-draw-close流程。而SpriteBatchNode是把多個精靈放到一個紋理上,繪製的時候直接統一繪製該texture,不需要單獨繪製子節點,這樣opengles繪製的時候變成了:open-draw()-draw()…-draw()-close(),節省了多次open-close的時間。注意:因爲繪製的時候只open-close一次,所以SpriteBatchNode對象的所有子節點都必須和它是用同一個texture(同一張圖片),類似下面這樣的圖片,4個貝殼都在同一紋理上:
1. 直接使用Layer進行添加精靈,Layer上有幾個精靈,那麼底層就會繪製幾次精靈;
簡單可以理解成底層繪製方式如下:
for(int i= 0;i<100;i++){open-draw-close;}
但是使用集合的話,Layer只需要對精靈集合進行一次渲染,
簡單可以理解成底層繪製方式如下:
open-draw(100次繪製)-close
從以上兩種方式可以看出兩者的區別了,第二種使用精靈集合省去了99次open和close的過程,從而達到優化作用;
2.使用SpriteBathNode雖然能達到優化,但是要注意一點:
初始化精靈集合SpriteBatchNode的時候會加載一張圖片資源(或者pvr文件等),那麼限制其精靈集合的子精靈都必須使用集合加載的這張圖纔行,否則會給出警告;
3.使用SpriteBatchNode還要注意一點,因爲精靈都存放在集合中,那麼這個集合SpriteBatchNode中的節點(精靈)都將在同一個z軸上,同一深度上;
一般使用TexturePacker工具都會將很多精靈圖片或者動作幀放在一起打包成“.pvr.z”、”.plist”、“-hd.pvr.z”和”-hd.plist”的四個文件,其中兩個-hd的是使用工具生成的打包資源的高清版本(940*480)使用的,這個不再強調了;
那麼肯定會有童鞋說,那麼如果把這資源文件與SpriteBathNode結合使用豈不是更嗨皮,沒錯,可以的,加載的時候只需要將如下創建集合即可:
創建精靈方法:SpriteBathNode與SpriteFrameCache結合使用。
//加載圖片資源
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("xx.plist");
SpriteBatchNode aParenet = SpriteBatchNode::create("xx.pvr.z");
this->addChild(aParenet);
Sprite *pFather = Sprite::spriteWithSpriteFrameName("father.gif");
pFather->setPosition(p(s.width / 2, s.height / 2));
aParenet->addChild(pFather);