從零開始的小游戲開發(fā)之第三篇 Dragonbones龍骨使用多個圖集的辦法

游戲正式名為 ?〖露易絲傭兵團(tuán)〗 ?已經(jīng)發(fā)布了,微信小程序里可以搜到了

這篇文章分享一點(diǎn)我制作游戲時的一點(diǎn)小技巧吧:

Dragonbones龍骨如何在cocos creator 里同時使用多個DragonBonesAtlasAsset圖集的辦法

這是我現(xiàn)在正在做的游戲視頻:

https://www.bilibili.com/video/BV1j5411h7ZY/

我的qq群:1142732961 歡迎一起討論交流啦


1.Dragonbones 龍骨在cocos creator 里使用多個圖集

在學(xué)習(xí)做龍骨動畫時,我發(fā)現(xiàn)很多組件是重復(fù)的,在小游戲里出現(xiàn)大量重復(fù)的素材還是很占包體的,所以我嘗試著把重復(fù)的東東單獨(dú)放到一個獨(dú)立的圖集里,龍骨動畫則會同時加載兩個圖集的素材

完整沒拆圖集的角色


拆出的通用圖集,我把角色通用的部位和所有可替換的衣服和武器抽了出來


角色拆出自己的圖集,我這里只抽出了發(fā)型和頭飾,表情服裝這些都用通用圖集的


合并后在游戲里不同角色的樣子(這里我偷懶沒換衣服,衣服其實(shí)是可以換成圖集里其他的)



1.實(shí)現(xiàn)方法

我沒有改cocos creator原生的代碼邏輯,而是純用ts腳本來實(shí)現(xiàn)出來的

當(dāng)然我寫代碼比較業(yè)余,里面好多東東寫的很臨時,沒有做封裝,我就貼出一下重要的代碼和步驟吧,當(dāng)然如果遇到問題可以隨時問我的.

首先,我們拿到要公用的圖集,如果這個圖集沒有被用到最好手動init一次,否則是拿不到龍骨圖集里的textures的.

我的邏輯是這樣寫的:

// 初始化公共貼圖

initHeroAtlas(dragonAtlasAsset: dragonBones.DragonBonesAtlasAsset) {

if (this.heroCommonAtlas != undefined) return

let heroCommonAtlas = {}

this.heroCommonAtlas = heroCommonAtlas

let textureAtlasData = dragonAtlasAsset['_textureAtlasData']

if (!textureAtlasData) {

dragonAtlasAsset['init'](dragonBones.CCFactory.getInstance())

textureAtlasData = dragonAtlasAsset['_textureAtlasData']

}

if (!textureAtlasData) return

let textures = textureAtlasData.textures

let whiteListTexture = this.whiteListTexture

for (let i = 0; i < whiteListTexture.length; i++) {

let name = whiteListTexture[i]

heroCommonAtlas[name] = textures[name]

}

let name = 'empty'

heroCommonAtlas[name] = textures[name]

}

這樣我們獲得了一個 heroCommonAtlas 的對象結(jié)構(gòu),存放圖集里的texture ,這個可以用來替換.當(dāng)然,如果你需要兩個以上的圖集也沒關(guān)系,把其他的圖集里的texture保存起來就可以了

我們生成的角色貼圖只有頭發(fā)和頭飾,其他的東東要從 heroCommonAtlas 里找到,當(dāng)然你可以寫邏輯選擇合并時具體使用圖集里的哪個武器或者哪件衣服

這是我合并兩個圖集的邏輯:

// 合并傭兵圖集

combineHero(ad: dragonBones.ArmatureDisplay) {

if (ad == undefined) return

let dragonAsset = ad.dragonAsset

let dragonAtlasAsset = ad.dragonAtlasAsset

if (dragonAsset == undefined || dragonAtlasAsset == undefined) return

let armature = ad.armature()

if (armature == undefined) return

let slots = armature['_slots']

let whiteListSlot = this.whiteListSlot

for (let i = 0; i < slots.length; i++) {

let slot = slots[i]

if (slot == undefined) continue

if (this.contain(whiteListSlot, slot.name)) {

let displayDatas = slot['_displayDatas']

for (let j = 0; j < displayDatas.length; j++) this._replaceDisplay(displayDatas[j])

if (this._replaceDisplay(slot['_displayData'])) slot['_updateDisplayData']()

}

}

}

這里比較重要的是 更新 displayData 以及最后slot的貼圖被更換成功后要手動_updateDisplayData的,否則不會立刻生效的.之所以用更新displayData數(shù)據(jù)的辦法是避免龍骨播放其他動畫時把插槽里的貼圖給還原掉,索性我們就先讓它用從公共圖集里借來的texture吧

這里還有個地方要小心就是龍骨的回收,如果你做了回收一定要記得把借來的texture還回去哈,不然龍骨的factory會按照當(dāng)前的atlas全部回收的,當(dāng)然公共圖集的我們肯定不希望被刪掉啦.回收的邏輯我后面會貼出代碼,這里貼一下 replaceDisplay 的實(shí)現(xiàn)吧:

// 使用傭兵公共貼圖

_replaceDisplay(display: dragonBones.DisplayData) {

let whiteListTexture = this.whiteListTexture

let texture = display['texture']

if (texture == undefined) return false

if (this.contain(whiteListTexture, texture.name)) {

display['texture'] = this.heroCommonAtlas[texture.name]

return true

}

return false

}

這里就用到前面生成的 heroCommonAtlas 了,其實(shí)原理還是很簡單的,只是換掉了texture,當(dāng)然摸索的過程可不這么簡單,我嘗試了好多種辦法,最后覺得這個辦法是最安全的了

主要的邏輯就是這些接下來說一下回收龍骨時要注意的東東:

我在替換貼圖前把老的texture保存下來,存到一個叫revert的字段里,因?yàn)榛厥盏臅r候要把texture換回去,

我的回收邏輯大致是這個樣子.龍骨一些邏輯沒有做容錯,所以這類偷梁換柱的操作一定要保證徹底還原回去,否則問題會非常難查:

let atlasSearch = this.atlasSearch

let res = atlasSearch[k]

let revert = res['revert'] // 是否有回收需要恢復(fù)的

if (revert) {

let textureAtlasData = res['_textureAtlasData']

if (textureAtlasData) {

let textures = textureAtlasData.textures

let empty = [] // 空的key要刪掉,不然龍骨會報錯

for (let i in revert) {

let o = revert[i]

textures[i] = o // 用回原來的

if (o == undefined) empty.push(i)

else {

let p = o['parent']

if (p && p['imagePath'] == 'part_tex.png') {

console.log('[ERROR]:', o['name'], i, ' in ', k, ' error!')

empty.push(i) // 不回收就不回收,總比報錯好

}

}

}

for (let i = 0; i < empty.length; i++)delete textures[empty[i]];

}

res['revert'] = undefined

}

atlasSearch[k] = undefined

cc.loader.releaseRes(k, dragonBones.DragonBonesAtlasAsset)

原理雖然挺簡單,代碼也不多,但是摸索出這些花掉我好多時間,我之前試過很多種辦法,換slot,換display,都會在播動畫重置時出現(xiàn)各種問題,最后還是覺得從textureAtlasData里抽出texture換掉最穩(wěn)最簡單,這是我自己摸索出來的,或許有更好更專業(yè)的辦法吧...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容