从小游戏聊起游戏开发干货

公众号 捞干的唠

首先说下,本系列文章均为原创,并且相关代码最后会开源。本系列文章主要讲的是本人从业十来年积累的一些简单易用且提升效率的“干货”,所以文章的代码多数只是示意,不会从零开始带着大家写下来,我尽量把内容写简单,但是免不了还是会有一丢丢门槛。

下面小程序码可以扫一扫看看该系列文章都是从这个游戏展开来讲的

这是我花了两个星期的时间用cocos creator开发的一款答题类游戏,游戏功能很简单,之后我会用这款游戏给大家介绍下我是如何从零开始开发一款微信小游戏的。顺便聊一聊游戏开发中的干货。接下来我们主要聊一聊以下几个方面:

  1. 我是怎么架构整改游戏的
  2. 各种管理器
  3. 消息中心
  4. 声音管理
  5. 有关2D游戏的优化种种
  6. 常用功能的封装以及框架迭代
  7. 工具开发

今天我们就先聊一聊第一点,我是怎么架构整个游戏的。

首先先说下我为什么选择cocos creator

  1. 要做小游戏那就免不了要使用引擎,现在主流的H5引擎有
  2. layabox
  3. cocos creator
  4. 白鹭
  5. playcanvas
  6. 等等

先说说我对上述几个引擎的看法首先layabox本身是不错的,但这里没有选择主要是因为这个游戏是2D游戏,layabox在UI编辑器部分个人感觉没有cocos creator好用,且layabox本身是依附于unity的编辑器,所见即所得还是查了一些。

白鹭关注过的都知道这里就不细说了

playcanvas引擎在图形方面做得很好很出色,同样对于我们这样轻量级的2D游戏来说是有点太重了

虽然这里选择了cocos creator,但是用下来我不得不吐槽下,cocos creator进步的空间还是很大的。。。

关于整体游戏的架构

好了书归正传,聊一聊今天要说的主题,我是怎么架构整个游戏的。

大致分了两部分第一:底层的一些功能类

第二:就是各个系统的业务UI

生命周期

这里我没有让所有的Component都走cocos creator自己的生命周期,我选择了由一个Main的GameObject来管理全部的Component对象,Component的生命周期(onLoad start update onDestroy …)将不会再Main之外被调用,又有时间紧任务重我没有进一步去看引擎只是猜测可能会和unity一样生命周期函数是通过反射一类的方式触发调用的,那么当Component量很大的时候生命周期函数的调用就会比较耗时所以我采用了Main这一个东西来管理所有的Component,具体做法如下:封装接口 IBehaviour

export interface IBehaviour {
    preInit():boolean; // 初始化之前的调用可类比onLoad
    init():boolean; // 初始化等价于start
    fini(); // 反初始化
    tick(dTime:number); // 更新
}

然后在Main的生命周期函数中增加各类管理器,每个类型的管理器都是管理上述接口

class Simple implements IBehaviour {
  preInit():boolean{
    return true;
  }
  
  init():boolean{
    return true;
  }
  
  fini(){}
  
  tick(dTime:number){}
}

class Main extends Component{
  simple:Simple = new Simple();
  onLoad(){
    if(!this.simple.preInit()){
      cc.error("simple preinit error!");
      return;
    }
  }
  
  start(){
    if(!this.simple.init()){
      cc.error("simple init error!");
      return;
    }
  }
  
  update(dTime:number){
    this.simple.tick(dTime);
  }
  
  onDestroy(){
    this.simple.fini();
  }
}

管理器

免不了游戏中会有很多全局的管理器,所以我抽出了一层Global,用来放一些常用的全局的管理器

class Gloabl{
  static simple:Simple = new Simple();
  static aMgr:aManager = new aManager();
  static bMgr:bManager = new bManager();
  
  onLoad(){
    if(!this.simple.preInit()){
      cc.error("simple preinit error!");
      return;
    }
    if(!this.aMgr.preInit()){
      cc.error("aMgr preinit error!");
      return;
    }
    if(!this.bMgr.preInit()){
      cc.error("bMgr preinit error!");
      return;
    }
  }
  
  start(){
    if(!this.simple.init()){
      cc.error("simple init error!");
      return;
    }
    if(!this.aMgr.init()){
      cc.error("aMgr init error!");
      return;
    }
    if(!this.bMgr.init()){
      cc.error("bMgr init error!");
      return;
    }
  }
  
  update(dTime:number){
    this.simple.tick(dTime);
    this.aMgr.tick(dTime);
    this.bMgr.tick(dTime);
  }
  
  onDestroy(){
    this.simple.fini();
    this.aMgr.fini();
    this.bMgr.fini();
  }
}


// 上述Main则修改为
class Main extends Component{
  onLoad(){
    Global.preInit();
  }
  
  start(){
    Global.init();
  }
  
  update(dTime:number){
    Global.tick(dTime);
  }
  
  onDestroy(){
    Global.fini();
  }
}

各位同学如果感兴趣的话可以参看最终的脚本组织结构

好了,今天先到这里,剧透下下一篇文章我打算展开讲一讲流程相关的内容,可能会着重说一下角色的脚本组织,当然也可能不是说这些

原文 从小游戏聊起游戏开发干货

2赞