天天看點

菜鳥也能學cocos2dx 3.0 骨骼動畫spine

首先我們來看到底什麼是骨骼動畫:

在早期的機器上,渲染本身已經占用了很多CPU資源,是以,對于渲染,往往采取的是一種空間換時間的政策,以避免在模型的渲染中繼續加重CPU的負擔。

幀動畫模型在這種條件下應運而生。比較著名的幀動畫格式是Quake2所采用的MD2。

到今天為止,幀動畫依然存在,隻不過幀動畫更多地是來描述小且動作相對少些的物體。

GPU出現後,CPU的問題早已不像以前那麼突出,一些新的手段和技術也可以被應用進來了。

骨骼動畫相對于幀動畫而言,更加靈活多變,但同時,骨骼動畫需要更多的計算量,是以骨骼動畫往往應用在需要着重展現動作細節的模型中。

骨骼動畫技術後于幀動畫技術出現。

最開始,骨骼動畫僅用于非實時渲染的模組化領域,如3DMax這類模組化軟體之中,以友善美工的模組化。

後來,CPU從渲染中解放後,骨骼動畫才用于實時渲染的遊戲中。

骨骼動畫原理

骨骼動畫的想法來源于人體骨骼。

例如說,人的上肢所有肌肉和皮膚都受上肢骨胳的影響,而人的踝關節則分别承受小腿骨胳和腳骨的影響。

根據這個我們可以将骨骼動畫了解為兩個概念: 骨骼:用以控制蒙皮的一種抽象的概念,如人體骨骼控制皮膚。 蒙皮:被骨骼控制、并顯示在外的因素,如人體的皮膚被骨骼所影響。

骨骼動畫原理:蒙皮(SKINMESH)

在最終的渲染結果中,蒙皮将完全顯示出來,蒙皮實際上就是頂點、法線和紋理坐标等将被渲染的元素。

而其中,最關鍵的當然是頂點,頂點将直接被骨頭牽扯運動,因而使得整個模型呈現骨骼所決定的樣子。

骨骼動畫原理:骨骼(SKELETON)

骨骼是一種抽象的概念,在最終的渲染結果中,它不可見。

類如人體骨骼、骨骼是若幹骨頭(Bone)成樹狀的集合體,而每塊骨頭又分别與若幹數量的蒙皮頂點關聯。

當骨頭運動的時候,與之關聯的所有蒙皮頂點也會受骨骼的影響而運動。

骨頭與蒙皮頂點的關聯需要考慮到每塊骨頭對蒙皮頂點的影響。 盡管大部分情況下,一個頂點将僅僅被一個骨頭的影響,但是關節處的頂點往往被多根骨頭影響,例如踝關節,可能會分别受小腿骨50%和腳骨50%的影響,這種影響叫作權重(Weight)。

在這種情況下,我們稱踝關節的這些頂點,受小腿骨影響的權重是50%,受腳骨影響的權重也是50%。

而在cocos2dx中常用的骨骼動畫編輯器就是cocosStudio和spine了。

但是就我的感受,2款編輯器中spine可以說是完爆ccs的骨骼動畫部分,不僅因為spine容易上手,并且它提供了mesh,通常來說一張紋理隻有4個頂點,左下右下左上右上,但是有了mesh,我們可以抓取這個圖檔,并設定大量的頂點給它,之後就能通過對頂點的設定完成圖檔的拉伸形變,比如乳搖功能。

spine中30幀為1s,最新版中也提供了IK,可以将骨骼固定,做動作。

具體的編輯我就不說了,主要說一下運作庫。

首先提供spine的最新運作庫,當然這不是官方的,裡面封裝了ffd,是我自己修改過并添加了ffd代碼,采用newSkeletonAnimation差別原先的skeletonAnimation具體點選:spine FFD runtime  

其中要注意的幾個地方:

1.  1.8版本以上的atlas做了修改 在第二行添加了size 是以隻要删除size這一行即可,

菜鳥也能學cocos2dx 3.0 骨骼動畫spine

2. 動作制作的時候如果層級有發生改變或者切換了skin,slot,請K幀一下,修改的部分:draworder和bone,一般首尾都K一下就行了。

3.至于.skel的binary檔案,是spine本身就提供的二進制檔案,性能必然高于json,本人目前正在修改完善spine runtime的binary(因為官方也不提供,完成起來慢了點,以後或許會放出)。

4.newskeletonanimation在create時候最後一個參數scale别忘了。

說一下runtime中常用的一些方法:

skeletonNode = NEWSkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas", 0.6f);//建立動作,最後的參數為scale.

skeletonNode->startListener = [this] (int trackIndex) {//設定動作開始檢測的監聽器
	spTrackEntry* entry = spAnimationState_getCurrent(skeletonNode->state, trackIndex);//獲得目前動作的狀态資訊
	const char* animationName = (entry && entry->animation) ? entry->animation->name : 0;
		log("%d start: %s", trackIndex, animationName);
	};
	skeletonNode->endListener = [] (int trackIndex) {//同理,結束動作監聽
		log("%d end", trackIndex);
	};
	skeletonNode->completeListener = [] (int trackIndex, int loopCount) {//同理,完成動作監聽
		log("%d complete: %d", trackIndex, loopCount);
	};
	skeletonNode->eventListener = [] (int trackIndex, spEvent* event) {//同理,事件監聽,在spine中編輯好event導出
		log("%d event: %s, %d, %f, %s", trackIndex, event->data->name, event->intValue, event->floatValue, event->stringValue);
	};

	skeletonNode->setMix("walk", "jump", 0.2f);//協調動作
	skeletonNode->setMix("jump", "run", 0.2f);
	skeletonNode->setAnimation(0, "walk", true);//設定動作,可用多個set進行動作混合
	spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 3);//添加動作,在上個動作直接玩之後,之後為循環參數和delay
	skeletonNode->addAnimation(0, "run", true);

	skeletonNode->setStartListener(jumpEntry, [] (int trackIndex) {
		log("jumped!");
	});</span>
           
skeletonNode->timeScale = 0.3f;//動作間隔
 skeletonNode->debugBones = true;//debug模式
 skeletonNode->update(0);//更新動作
 spBone* root=skeletonNode->findBone("root");//找到name為root的骨骼,同理  通過 findslot 可以找到名字為name的slot
           

順便吐糟一下cocos2dx 官方,雖說cocosstduio是親兒子吧,但是也不能不管spine啊,spine的ffd一直愣是沒加上去,逼得我自己改過來- =!

spine執行個體 附上執行個體

繼續閱讀