CocosCreator只谈实战系列1——成语游戏编辑器篇

前言

作者从18年4月开始试水微信小游戏,后面又用休闲小游戏项目尝试过国内安卓,头条小游戏,facebook等平台。

也是从18年4月第一次使用 cocos creator, 感觉creator的开发体验不错,特别是从Unity3D 转到creator很平滑,

无需看太多说明文档基本就能上手即用,同时,creator也能满足休闲游戏快速产出原型和核心玩法的这一要求。

接下来的一段时间,作者打算将手上的一些项目做成creator系列文章,这些项目每一个核心玩法都有所不同,也使用到了creator引擎的许多方面,希望对creator学习路上的朋友有所帮助。

本篇是系列第一篇,所选项目是今年大火的“成语"类,这个项目打算分两篇介绍,本篇先说关卡编辑器是如何实现的,下一篇再说游戏本体实现。 有看官可能得问了,为什么要先说编辑器?俗话说得好啊 ”工欲善其事必先利其编辑器“, 各位,对于成语这种动则几千关卡的项目,如果没有一个可以用起来很方便的编辑器,开发效率就变得很低下了。。 而就实际数据来说:

  1. 这个关卡编辑器使用了一周进行开发
  2. 一个策划人员一周可轻松制作 300 关卡

好了,废话不多说,下面进入正题。

一,需求分析与设计

”谋定而后动, 知止而有得“

写代码最好的状态是,当开始敲下第一行代码的时候,模块怎么划分,模块间怎么牵线搭桥,全盘皆成竹于胸

我们先来看看成语关卡编辑器的需求点吧:

  1. 我们应该制作一个编辑区,编辑器是9 X 9的格子布局,共81个格子
  2. 编辑成语的方式,应该是随心所欲的在格子上刷出成语,想怎么刷就怎么刷,这样生成关卡才快,你

把编辑器交付给你的策划同事,他要面临的是生成几千个关卡。。

  1. 换成语和删成语。 除了自由刷成语这个基本操作,应该支持对某个成语进行选中,把它换成其它更合适的

成语,或者直接删掉重新编辑。

  1. 去字功能。 这也是编辑器比较重要的一个功能,因为在游戏中玩家看到的成语都不是完整的需要填空,而去字

功能就是用来编辑那些字显示为空格需要让玩家填空。

​ 一个关卡少说有7,8个成语,如果一个一个的去点就太累了,这里我们实现了一个‘自动一键去字’功能,一键去字,如果效果不好,再手动微调即可。

  1. 其它:关卡保存/关卡加载/成语词库配置读取

需求整理出来了,下一步就是简单设计和规划代码结构:

  1. *词条基本数据*

我们希望用一个类来描述成语词条的基本数据,请记住,它对应的仅仅

是成语词库里的一条数据,而不是成语对象。但是很明显,最终它会被一个成语对象所引用。

词条基本数据所需要的数据结构很简单:

//file idiomData.js
export default class IdiomData
{constructor(id, chars, pinyin, note){this.id=id;                //数据idthis.chars=chars;       //保存成语的chars,例如"一马当先"this.pinyin=pinyin;     //成语的注音this.note=note;         //成语的出处和释义}//...
}

​ 2. *成语对象*

​ 我们希望用一个类来描述关卡中编辑出的每一条成语对象

​ 成语对象的成员也很简单:

  • 记录自己占用了哪些格子(因为后续的操作例如换词/删词都会使用这个数据)
  • 引用成语词条数据
  • 记录编辑时,自身的方向(就两个方向:横 or 竖)
  //file Idiom.jsexport const IdiomGridDir={Unknow:0,Horizontal:1,  // 横Vertical:2,     //竖};export default class Idiom{constructor(grids){//占用的格子this.grids=[];//引用的词条数据this.data=null;//方向 横or竖this.girdDir=IdiomGridDir.Unknow;for(let i=0;i<grids.length;i  ){this.pushGrid(grids[i]);}}//...}
  1. *格子对象*
      我们希望用一个类来描述编辑区每个格子的状态与行为:
  • 该格子是否被使用了
  • 该格子上面的成语字符(如果没被使用,就是” ”)
  • 该格子对应的成语对象(格子上需要记录成语对象,并且要以数组形式记录,因为存在两个成语

交叉字格子)

  • 该格子是否是被共享的格子
  • 该格子是否是被‘去字’的状态

重点就是以上属性,当然肯定有一些显示相关属性就不一一列出了

  //file Grid.jscc.Class({extends: cc.Component,properties: {//格子IDgridId:{default:0,visible:false},//是否是被使用的格子isUsed:{default:false,visible:false},},// LIFE-CYCLE CALLBACKS:onLoad () {//其它属性 ...        //引用的词条数据this.data=null;//使用的成语字符this.char="";//格子反向保存idiom引用this.idioms=[];//是否是共享格this.isShareGrid=false;//是否是被’去字‘状态this.isSpaceGrid=false;},
  1. *关卡对象*
    我们希望用一个类来描述游戏关卡对象:

关卡对象组织了格子和成语对象,并且负责对刷成语和换成语/删成语/去字/保存加载等

因此关卡类会包含更多的数据与行为,事实上大部分代码也集中在关卡类中

关卡对象主要的数据成员为:

  • 一个9X9长度的数组,保存格子信息
  • 一个用于存放已经完成编辑的成语对象数组
  • 一个存放编辑过程中选中格子的数组(便于做一些计算,比如确定刷格子的方向,再比如

刷格子的数量是否已经越界了等)

onLoad () {this.totalGridsNum=this.gridLineNum * this.gridLineNum;//格子数组 最大长度9x9=81this.grids=[];//保存已经编辑的成语对象的数组this.idioms=[];//缓存编辑过程中鼠标已选中的格子this.selectedGrids=[];

关卡对象start() 函数

  • 创建9X9的编辑区背景格子
  • 注册鼠标事件,处理格子刷取逻辑
  • 注册键盘事件(主要处理CTRL 左键,做精确去字选取处理)
start () {//创建9X9 编辑区背景格子this.createBgGrids();//注册鼠标事件this.registTouchEvent();//注册键盘事件this.registKeyEvent();},

关卡对象主要函数如下,原则上我们将每个编辑功能封装成一个函数,让他们各司其职:

registTouchEvent:function ()    //处理touch事件
registKeyEvent:function()       //处理键盘事件
selectIdiom:function(idiom)        //选中一个成语对象
selectGrid:function(grid)        //选中一个格子
changeSelectedIdiom:function()  //将选中的成语换成其它成语
deleteSelectedIdiom:function()    //删除选中的成语
autoRemoveChar:function()        //自动给成语去字
saveLevel:function()            //保存关卡
loadLevel:function()            //加载关卡

小结一下,其实成语关卡编辑器核心的类就是上述4个,通过简单的需求分析,我们作了一个比较清晰的划分,让它们各自负责各自的工作。这里想多提一下,有经验的老鸟看到这里肯定会发现一个问题,严格说类似 registTouchEvent,registKeyEvent, saveLevel,loadLevel 这样的行为,不属于Level对象需要负责的工作,更合理的做法,应该是抽象出一个Editor类,来负责处理事件,保存加载关卡,串联编辑流程。确实在大一些的项目,笔者更推荐这样的设计,本次介绍的项目由于结合开发工期原因,将一些编辑器负责的行为添加到了关卡对象中。

二,编辑流程实现

接下来再简单介绍下编辑流程实现,由于项目本身偏简单,就只抓重点讲啦。

*1. 刷词*

刷词主要是在 TouchEvent事件中处理,其实如果只考虑在空白格子刷词,是非常容易处理的,

这种情况下,程序上只需要判断格子选取情况,再从成语库中取词填充格子就行了,而格子选取符合要求

的条件无非是:必须是连续选中的4格,格子不能有拐弯,选取范围不要超过编辑有效范围。

刷词稍微复杂一些的情况是某些选定的格子已经被使用了,就出现了多词共享格的情况,这时候必须把这些字和它

的位置作为附加条件,带到成语词库中进行搜索。

先看一下刷词逻辑,在touch_end中判断是否符合刷词条件:

this.node.on(cc.Node.EventType.TOUCH_END,(event)=>{let point=event.touch.getLocation();// 转到编辑格子区域的 local positionlet localPoint=this.node.convertToNodeSpace(point);localPoint.y=this.node.height - localPoint.y;                        // 做一些是否超出编辑范围等判断 。。。//选取的格子长度为4if(this.selectedGrids.length===4){//先按格子ID排个序,因为格子可能是从右到左或者从下到上刷的this.selectedGrids.sort((a,b)=>{return a.gridId - b.gridId;});//排序OK后,4个格子ID取出来let idx0=this.selectedGrids[0].gridId;let idx1=this.selectedGrids[1].gridId;let idx2=this.selectedGrids[2].gridId;let idx3=this.selectedGrids[3].gridId;//满足这个条件,说明是横向连续4格if(idx1===idx0 1 && idx2===idx1 1 && idx3===idx2 1){//在选取范围中获取被共用的charlet shareChars=this.getShareCharsInSelection();//成语库中查找let idiomData=WordsLib.instance.findIdiomData(shareChars);if(idiomData!==null){//找到了,生成新idiom对象let idiom=new Idiom(this.selectedGrids);//新成语保存关卡中this.idioms.push(idiom);this.updateIdiomNumLabel();//更新成语对象数据idiom.setIdiomData(idiomData);//更新格子状态idiom.updateGrids();}else{//没有合适的成语可填,做一些编辑状态的清理工作                        }}//满足这个条件,说明是纵向连续4格else if(idx1===idx0 this.gridLineNum && idx2==idx1 this.gridLineNum && idx3===idx2 this.gridLineNum){//内部逻辑和上面横向是一样的。。。}}

*2. 自动去字*

实现自动去字主要是为编辑时提供一个快捷功能,一个成语最多自动去掉两个字

写了一个removeChar函数来处理

    removeChar(){let ret=this.getSpaceGrids();//已经有两个空格字的话就不继续处理了if(ret.length===2)return;let removeIdx=[0,1,2,3];if(ret.length===1){//在剩余的3格里面再去掉一个字removeIdx.splice(ret[0],1);let randIdx=Util.randRangeNumber(0,removeIdx.length-1);let gid=removeIdx[randIdx];this.grids[gid].forceSetSpace();}else if(ret.length===0){//这是需要去掉两个字的情况let randIdx=Util.randRangeNumber(0,removeIdx.length-1);this.grids[randIdx].forceSetSpace();removeIdx.splice(randIdx, 1);randIdx=Util.randRangeNumber(0,removeIdx.length-1);let gid=removeIdx[randIdx];this.grids[gid].forceSetSpace();}}

以上是关于刷词和去字的实现,至于说其它如选词/换词/删词/保存加载,其实实现都很简单,成语项目整体来说

很容易实现,这些功能就不啰嗦了。

顺便作一下下个项目的预告吧,下个项目准备介绍一个竖版跑酷类游戏——《峭壁逃亡》

该游戏参与了头条小游戏平台的内测,相关新闻连接 http://dy.163.com/v2/article/detail/DT5A07F10546236I.html

这个 项目将重点给大家介绍 跑酷类游戏无限关卡的生成方法,以及基于dragonBone的角色控制, 敬请期待。

笔者简介:

肖尧,从事游戏 前端/后端/3D引擎开发多年

前盛大锦天项目主程,前成都网龙研发负责人,高级架构师

现任休闲游戏公司H5技术总监,未来将持续专注于基于H5的泛娱乐/教育/传媒/工具等产品的研究与开发。

微信/QQ : 1611471

CocosCreator只谈实战系列1——成语游戏编辑器篇相关推荐

  1. Cocos Creator 只谈实战系列—成语游戏篇

    相关文章导读: H5线体验链接: H5关卡编辑:http://game.ixuexie.com/idiomEditor H5成语游戏:http://game.ixuexie.com/idiomGame ...

  2. Cocos Creator游戏引擎可以支持鼠标吗_Cocos Creator入门实战:桌球小游戏

    本文作者:BigBear 多年游戏行业研发经验 精通Unreal.CocosCreator游戏引擎 参与过多款手游.端游项目的研发 Cocos Creator入门实战:桌球小游戏 本篇主要是希望能够通 ...

  3. ​Cocos Creator入门实战:桌球小游戏

    本文作者:BigBear 多年游戏行业研发经验 精通Unreal.CocosCreator游戏引擎 参与过多款手游.端游项目的研发 Cocos Creator入门实战:桌球小游戏 本篇主要是希望能够通 ...

  4. Java秒杀系统实战系列~RabbitMQ死信队列处理超时未支付的订单(转)

    转自: https://juejin.cn/post/6844903903130042376 文末有源代码,非常棒 摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十篇,本篇 ...

  5. GPS项目实战系列1:GPS数据解析1

    前面写了一系列关于Linux的文章,从这一篇开始换个题目,叫做GPS项目实战系列,后面的很多篇内容都会围绕着这个项目展开.这个项目要完成的任务,可以参考之前的文章:https://topsemic.c ...

  6. Java秒杀系统实战系列~定时任务补充处理超时未支付的订单

    摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十一篇,本篇博文我们将借助定时任务调度组件来辅助"失效超时未支付的订单记录"的处理,用以解决上篇博文中采用 ...

  7. asp按时间自动递增编号_Java秒杀系统实战系列-分布式唯一ID生成订单编号

    本文是"Java秒杀系统实战系列文章"的第七篇,在本文中我们将重点介绍 "在高并发,如秒杀的业务场景下如何生成全局唯一.趋势递增的订单编号",我们将介绍两种方法 ...

  8. sql取系统时间减一小时_Java秒杀系统实战系列-整体业务流程介绍与数据库设计...

    本篇文章是"Java秒杀系统实战系列文章"的第三篇,本文将主要介绍秒杀系统的整体业务流程,并根据相应的业务流程进行数据库设计,最终采用Mybatis逆向工程生成相应的实体类Enti ...

  9. sql判断时间大于0点_Java秒杀系统实战系列-数据库级别Sql的优化与代码的调整

    本文是"Java秒杀系统实战系列文章"的第十三篇,从本篇文章开始我们将进入"秒杀代码优化"环节,本文将首先从数据库级别Sql的优化入手,结合调整秒杀相关的部分核 ...

最新文章

  1. 微软开源的自动机器学习工具上新了:NNI概览及新功能详解
  2. Ubuntu 16.04下Caffe-SSD的应用(三)——训练VOC2007数据生成模型
  3. java基础提升篇:Java 序列化的高级认识
  4. 新纳米结构能加快电子设备运行
  5. 玛氏携手阿里 天猫网罗全球快消三巨头
  6. 外设驱动库开发笔记26:nRF24L01无线通讯驱动
  7. RpcException:No provider available for remote service异常
  8. 无法从Windows上的资产index.android.bundle加载脚本
  9. java 序列化 学习
  10. lintcode-20-骰子求和
  11. python中颜色表_python 颜色表
  12. android备份apk,无需手机助手,ABI帮你安装/备份安卓APK
  13. 女神告诉你什么是互联网思维
  14. QOS中 PQ,CQ.RR,WFQ,CBWFQ,LLQ区分(上)
  15. 梳理 | 机器人学习(Robot Learning)的发展
  16. 从China Webmaster上收集房地产网站排名、网址和简介
  17. 安卓虚拟机_安卓虚拟机雷电模拟器
  18. 热搜第一!刘强东回国了!
  19. *p++是什么意思?
  20. 嵌入式开发之中断服务程序

热门文章

  1. Top-K Off-Policy Correction for a REINFORCE Recommender System
  2. QQ群关系库数据库查询解决方案,sql引索语句。
  3. 全球与中国铟金属市场深度研究分析报告
  4. linux离线软件包下载,Linux离线安装Docker
  5. 有没有Linux下好用的电脑遥控器阿?
  6. 电脑遥控接收器电路_遥控电路图讲解
  7. python电影推荐系统 github_GitHub - JaniceWuo/MovieRecommend: 一个电影推荐系统
  8. 赵小楼《天道》《遥远的救世主》深度解析(63)什么是强势文化?什么是弱势文化?怎么无所用,无所不用?
  9. html图片锚点怎么设定,html怎么设置锚点
  10. web3D 车型展示