露易丝佣兵团 安卓 版发布啦
露易丝佣兵团在微信上得到了一些玩家的反馈,于是自己尝试能不能把它做成安卓版
不过模拟器和浏览器在龙骨上差别非常巨大,所以不得不复制粘贴一份改了好多好多代码,然后加新功能两边同步...(好麻烦鸭)
虽然很折腾,但是游戏里加了很多新内容:
比如,炼金术(顺便恶搞了下英雄无敌的鹰眼术):
加了宠物(虽然目前只有猫咪)
还有试炼关卡
还增加了魔石和炼金素材,修改了商店的规则,还有佣兵的收藏品:
还增加了很多新的随机事件.
还有很多的想法还不知道要怎么做,不过我会坚持更新这个游戏的!
露易丝佣兵团 游戏发布咯
从零开始的小游戏开发之第三篇 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换掉最稳最简单,这是我自己摸索出来的,或许有更好更专业的办法吧...
从零开始的小游戏开发之第二篇
前一篇日志讲了开始准备开发一个小的游戏我所做的准备,这篇总结一下开始使用cocos遇到的一些对新手不太友好的问题和解决办法吧
稍微录了一下自己游戏的视频,里面好多东东可能还需要改.开头的漫画是因为有人反馈进去就打怪太突然了我花两天画的用来过渡的
https://www.bilibili.com/video/BV1j5411h7ZY
我的qq群:1142732961 欢迎一起讨论交流啦
1.cocos 文本立刻 改变大小尺寸,获取cc.Label新size
根据文字的多少改变按钮宽度是个蛮常见的功能,为了实现这个功能我搜了很多诸如 “强制刷新获取高度” “Label下一帧才刷新大小” “改变string更新宽度高度” 这类关键词,给的答案一般是:
label._forceUpdateRenderData(true)
然而我在typescript里真正使用它时却是这个样子的:
显示的错误是 类型“Label”上不存在属性“_forceUpdateRenderData”。ts(2339)
没错, _forceUpdateRenderData 在 2.3中 标红 报错 不能直接用哦,莫非没有_forceUpdateRenderData这个函数?
之所以这样,原因是cocos creator2.3这个接口并没有导出定义,所以才会变成红色.但这并不影响使用,这样写,就能解决问题了:
console.log(this.label.node.getContentSize()) this.label.string = '我是啤啤鸭不卖萌' this.label['_forceUpdateRenderData'](true) console.log(this.label.node.getContentSize())
当然_forceUpdateRenderData并不是无敌的,我在使用 RESIZE_HEIGHT 的模式时遇到过它计算的结果是错误的,我实在想不出解决的办法,只好 scheduleOnce 在下一帧计算高度.当然绝大多数情况下这个还是能解决问题的
2.updateAlignment重新排版把所有的父节点也重新排版了
当界面或窗口大小发生变化时,一般需要重新适配所有的ccWidgets,比如我的游戏里就有面板的展开和收缩的功能.但是调用 updateAlignment 时它的所有父节点也会被全部重新排版,有的时候这不是我们希望的,尤其是一些游戏里不断改变组件大小位置的情况
如果只想改变自己的布局而不想影响它的父节点,可以试试这个办法:
this.widget.enabled = true
上面这句会刷新cc.Widgets的排版,但不是立即刷新,而是下一帧刷新,而 updateAlignment 是当前帧立即刷新,使用哪种办法可以自己来根据情况权衡
3.屏幕适配,根据屏幕比例或父节点适配改变ui大小尺寸,按固定比例百分比改变尺寸
开始我用的办法很蠢,是用cc.winSize获得屏幕的宽度和高度再乘以百分比来计算,如果在一些 Layout 里这样计算会非常麻烦,直到一次偶然我去次饭鼠标无意中对准了一个位置,肥来后我竟然看到了芥个:
天鸭,居然是可以输入百分比
居然藏得这么深?我百度搜了好多文章也没找到的东东居然会出现在这里!谁知道这里还会藏着这种操作.
用百分比可以解决很多烦人的问题,至少不需要写那么多 scheduleOnce 了.
好啦.就写到这里吧,有cocos的问题可以问我,虽然我也还是初学者....
从零开始的小游戏开发之第一篇
哈喽哈喽,大家好,我是啤啤鸭,一个还不太会写代码的cocos初学者.不过呢,几个月前我决定开始尝试完全靠自己做出我人生的第一个小游戏,先给大家看看我这几个月肝出来的一点点成果吧.
我的qq群:1142732961 欢迎一起讨论交流啦
其他角色
画了一些怪物
虽然是初学者,但是我之前还是有一点点基础的,因为喜欢玩游戏自学过做一些游戏的mod,为了做出好玩的mod也自学了一点代码和绘画.当然尝试自己做游戏靠这些还差远呢!所以,我想把我开始做游戏的过程,遇到的对新手非常不友好的问题以及进度记录下来,希望能对和我一样想尝试做游戏的人有一丢丢帮助.当然,如果哪里描述的不对或者误导了其他人还请多多指正,我会改掉的,毕竟我不是很专业.但是我会在写东西之前多多查阅一些资料,让我记录下的东东尽可能的准确的!
游戏引擎我选择的是cocos,目标是打算发布微信小游戏.之所以这样选择是因为加过的一个群里有位dalao做过微信小游戏,我想至少用cocos遇到我解决不了的问题还是可以找到人问一问,总比自己一个人从头开始摸索会安心一点.
游戏我打算做挂机类游戏,因为我个人猜测这个大概是最好做的游戏类型了,毕竟我还不是很有信心去尝试复杂的游戏类型.虽然是挂机游戏,我会用心思把它做的很好玩的!
好了,说了这么多东东,还是说一些开发的过程和这几个月的心得吧.
首先,第一天,我下载了Cocos Creator,这是它的官网
https://www.cocos.com/creator
我下载的是几个月前的最新版本,现在打开发现出了很多新版本,更新的好快啊.我现在用的是V2.3.3,也就是四月份的版本,当然用新版本也是没关系的.
Cocos Creator安装还是很简单的,我想应该不会难到谁.不过有个注意事项就是安装路径不要带中文,不然安装后会有问题的.
安装完成之后是上面这个样子,点开新建空的工程里面一片空白,什么都没有.当时我就不知道接下来我要点什么,要怎么开始做游戏.毕竟这和做mod不太一样,代码和画的画是从无到有的.于是我把这个听起来有点蠢的问题问了一位正在开发steam游戏的个人开发,他给我的建议是:
写一篇文档描述清楚你想做的游戏有哪些内容,然后再把这些内容细化成非常详细的步骤.即使你还不知道这些步骤在cocos里要怎么做,你也可以按照自己的理解大胆的写.写完之后再划掉你认为不是最重要或者可以几个月后慢慢做的内容,将剩下的内容和步骤做成一份清单,按照这份清单一点点做,就没问题了
虽然我很想快快用Cocos做东东,但我还是听了他的建议,写了一份非常不专业的功能清单,这个花掉了我两天的时间,写的时候我习惯性的反复修改写好的内容让它描述得更具体.现在想想,这样做对我还是很有帮助的,因为有了这份清单,我可以很明确的知道要做什么,做这些东西要学什么,毕竟Cocos的功能很多,学完所有功能再开始做游戏是很难坚持下来的.明确自己要做什么,有目的的花时间边学边做既可以让自己更好的掌握学到的,又能让游戏每天都有进展,因为每个步骤分的很细致,学习一个步骤用到的知识可能只用不到一个小时的时间,这样边学边做一点点推进游戏进度,会让自己更有信心.
当然,除了上面建议的内容,我还自己尝试瞎画了几个游戏想做出的界面,虽然和现在已经有点不一样了,但是这对当时度过对游戏开发完全陌生的时期是非常有帮助的:
最早写的功能清单在我这几个月的开发摸索中被我不断的修改,补充,删掉完成的功能,现在已经面目全非了,我也就不截图给大家看了.但我还记得我当时写出文档的前几步大致这个亚子:
功能1:做出个大致的游戏界面:
步骤1:做出个游戏背景图,随便找个图就行,只要游戏运行时能看到这张图就ok
步骤2:做出个按钮,只要这个按钮能点就行,具体点了怎么关联到代码后面再研究
步骤3:把这些背景和按钮拼成一个和你画出来的差不多的界面
......
功能x:
步骤x:开始试着画主角,画的差不多能在游戏里看到就行
虽然这些描述给专业的人看可能会觉得非常可笑,但我一步步按照这个清单去做,做出来的就会删除掉,实在不会的就剪切到后面的功能里以后再做.每做完一个步骤删掉其中一项会特别有成就感.我想,如果你打开Cocos一时不知道要做什么,又没耐心看Cocos教程,或者觉得做游戏几天毫无进展,不妨试试我这个办法.
先写到这里,后面我会不断总结Cocos小游戏制作中遇到的各种问题,我认为一个人开始制作游戏的过程不仅是对自己的写代码能力和学习能力的考验,也是对自己的精神力的考验,因为做的过程中经常会忍不住去想:不好玩没人玩怎么办,有些东东我做不到怎么办.有人经过考验做出自己的游戏了,我相信我遇到的问题也一定曾困扰过这些人,虽然他们可能已经记不太清当时是怎么坚持下去的了。
我会坚持更新我的文章的,我的qq群:1142732961 欢迎大家加入一起探讨游戏的开发过程和遇到的困难和心得。我希望我记下的东东或许在以后能帮助到和我一样经历过类似困扰的人,当然也欢迎大家多多指教啦!