从零开始的小游戏开发之第三篇 Dragonbones龙骨使用多个图集的办法

游戏正式名为  〖露易丝佣兵团〗  已经发布了,微信小程序里可以搜到了

这篇文章分享一点我制作游戏时的一点小技巧吧:

Dragonbones龙骨如何在cocos creator 里同时使用多个DragonBonesAtlasAsset图集的办法

这是我现在正在做的游戏视频:

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

我的qq群:1142732961 欢迎一起讨论交流啦


1.Dragonbones 龙骨在cocos creator 里使用多个图集

在学习做龙骨动画时,我发现很多组件是重复的,在小游戏里出现大量重复的素材还是很占包体的,所以我尝试着把重复的东东单独放到一个独立的图集里,龙骨动画则会同时加载两个图集的素材

完整没拆图集的角色


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


角色拆出自己的图集,我这里只抽出了发型和头饰,表情服装这些都用通用图集的


合并后在游戏里不同角色的样子(这里我偷懒没换衣服,衣服其实是可以换成图集里其他的)



1.实现方法

我没有改cocos creator原生的代码逻辑,而是纯用ts脚本来实现出来的

当然我写代码比较业余,里面好多东东写的很临时,没有做封装,我就贴出一下重要的代码和步骤吧,当然如果遇到问题可以随时问我的.

首先,我们拿到要公用的图集,如果这个图集没有被用到最好手动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 的对象结构,存放图集里的texture ,这个可以用来替换.当然,如果你需要两个以上的图集也没关系,把其他的图集里的texture保存起来就可以了

我们生成的角色贴图只有头发和头饰,其他的东东要从 heroCommonAtlas 里找到,当然你可以写逻辑选择合并时具体使用图集里的哪个武器或者哪件衣服

这是我合并两个图集的逻辑:

// 合并佣兵图集

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数据的办法是避免龙骨播放其他动画时把插槽里的贴图给还原掉,索性我们就先让它用从公共图集里借来的texture吧

这里还有个地方要小心就是龙骨的回收,如果你做了回收一定要记得把借来的texture还回去哈,不然龙骨的factory会按照当前的atlas全部回收的,当然公共图集的我们肯定不希望被删掉啦.回收的逻辑我后面会贴出代码,这里贴一下 replaceDisplay 的实现吧:

// 使用佣兵公共贴图

_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 了,其实原理还是很简单的,只是换掉了texture,当然摸索的过程可不这么简单,我尝试了好多种办法,最后觉得这个办法是最安全的了

主要的逻辑就是这些接下来说一下回收龙骨时要注意的东东:

我在替换贴图前把老的texture保存下来,存到一个叫revert的字段里,因为回收的时候要把texture换回去,

我的回收逻辑大致是这个样子.龙骨一些逻辑没有做容错,所以这类偷梁换柱的操作一定要保证彻底还原回去,否则问题会非常难查:

let atlasSearch = this.atlasSearch

let res = atlasSearch[k]

let revert = res['revert'] // 是否有回收需要恢复的

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,都会在播动画重置时出现各种问题,最后还是觉得从textureAtlasData里抽出texture换掉最稳最简单,这是我自己摸索出来的,或许有更好更专业的办法吧...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352