手把手教你打造一款轻量级canvas渲染引擎

本文介绍如何构建一个轻量级的canvas渲染引擎,它借鉴了Web开发流程,允许通过XML和CSS配置界面,同时兼顾高效和代码可读性。引擎支持基本的HTML标签,如view、text和image,并实现事件绑定、滚动列表等功能。文中详细阐述了引擎从解析XML到渲染的整个过程,包括布局计算、重排和重绘的实现。此外,还提供了在线调试器和应用场景,适用于游戏周边插件、代码包优化和屏幕截图等场景。
摘要由CSDN通过智能技术生成

背景

当我们开发一个canvas应用的时候,出于效率的考量,免不了要选择一个渲染引擎(比如PixiJS)或者更强大一点的游戏引擎(比如Cocos Creator、Layabox)。

渲染引擎通常会有Sprite的概念,一个完整的界面会由很多的Sprite组成,如果编写复杂一点的界面,代码里面会充斥创建精灵设置精灵位置和样式的“重复代码”,最终我们得到了极致的渲染性能却牺牲了代码的可读性。

游戏引擎通常会有配套的IDE,界面通过拖拽即可生成,最终导出场景配置文件,这大大方便了UI开发,但是游戏引擎一般都很庞大,有时候我们仅仅想开发个好友排行榜。

基于以上分析,如果有一款渲染引擎,既能用配置文件的方式来表达界面,又可以做到轻量级,将会大大满足我们开发轻量级canvas应用的场景。

本文会详细介绍开发一款可配置化轻量级渲染引擎需要哪些事情,代码开源至Github:https://github.com/wechat-miniprogram/minigame-canvas-engine

配置化分析

我们首先期望页面可配置化,来参考下Cocos Creator的实现:对于一个场景,在IDE里面一顿操作,最后场景配置文件大致长下面的样子:

  // 此处省略n个节点
  {
    "__type__": "cc.Scene",
    "_opacity": 255,
    "_color": {
      "__type__": "cc.Color",
      "r": 255,
      "g": 255,
      "b": 255,
      "a": 255
    },
    "_parent": null,
    "_children": [
      {
        "__id__": 2
      }
    ],
  },

在一个JSON配置文件里面,同时包含了节点的层级结构样式,引擎拿到配置文件后递归生成节点树然后渲染即可。PixiJS虽然只是个渲染引擎,但同样可以和cocos2d一样做一个IDE去拖拽生成UI,然后写一个解析器,声称自己是PixiJS Creator😬。

这个方案很好,但缺点是每个引擎有一套自己的配置规则,没法做到通用化,而且在没有IDE的情况下,手写配置文件也会显得反人类,我们还需要更加通用一点的配置。

寻找更优方案

游戏引擎的配置方案如果要用起来主要有两个问题:

  1. 手写可读性差,特别是对于层级深的节点树;
  2. 样式和节点树没有分离,配置文件冗余;
  3. 配置不通用;

对于高可读性样式分离,我们惊讶的发现,这不就是Web开发的套路么,编写HTML、CSS丢给浏览器,界面就出来了,省时省力。
在这里插入图片描述

如此优秀的使用姿势,我们要寻求方案在canvas里面实现一次!

实现分析

结果预览

在逐步分析实现方案之前,我们先抛个最终实现,编写XML和样式,就可以得到结果:

let template = `
<view id="container">
  <text id="testText" class="redText" value="hello canvas"> </text>
</view>
`;

let style = {
    container: {
         width: 200,
         height: 100,
         backgroundColor: '#ffffff',
         justContent: 'center',
         alignItems: 'center',
     },
     testText: {
         color: '#ff0000',
         width: 200,
         height: 100,
         lineHeight: 100,
         fontSize: 30,
         textAlign: 'center',
     }
}
// 初始化渲染引擎
Layout.init(template, style);
// 执行真正的渲染
Layout.layout(canvasContext);

方案总览

既然要参考浏览器的实现,我们不妨先看看浏览器是怎么做的:
在这里插入图片描述
如上图所示,浏览器从构建到渲染界面大致要经过下面几步:

  • HTML 标记转换成文档对象模型 (DOM);CSS 标记转换成 CSS 对象模型 (CSSOM)
  • DOM 树与 CSSOM 树合并后形成渲染树。
  • 渲染树只包含渲染网页所需的节点。
  • 布局计算每个对象的精确位置和大小。
  • 最后一步是绘制,使用最终渲染树将像素渲染到屏幕上。

在canvas里面要实现将HTML+CSS绘制到canvas上面,上面的步骤缺一不可。

构建布局树和渲染树

上面的方案总览又分两大块,第一是渲染之前的各种解析计算,第二是渲染本身以及渲染之后的后续工作,先看看渲染之前需要做的事情。

解析XML和构建CSSOM

首先是将HTML(这里我们采用XML)字符串解析成节点树,等价于浏览器里面的“HTML 标记转换成文档对象模型 (DOM)”,在npm搜索xml parser,可以得到很多优秀的实现,这里我们只追求两点:

  1. 轻量:大部分库为了功能强大动辄几百k,而我们只需要最核心的xml解析成JSON对象;
  2. 高性能:在游戏里面不可避免有长列表滚动的场景,这时候XML会很大,要尽量控制XML解析时间;

综合以上考量,选择了fast-xml-parser,但是仍然做了一些阉割和改造,最终模板经过解析会得到下面的JSON对象

{
    "name":"view",
    "attr":{
        "id":"container"
    },
    "children":[
        {
            "name":"text",
            &#
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
随着html5 相关技术的兴起,因其跨平台的特性,和标准的日益完善。html5相关技术越来越多的被应用到前沿app的开发中,尤其是html5 小游戏的开发。 Laro 是一个基于html5 canvas的用于平面2d或者2.5d游戏制作的轻量级游戏引擎。 因为当前canvas作为画布形态的dom元素,并提供了大量关于矢量图以及texture绘制的api,但是由于其本身提供的api太过于底层,在类似游戏这一类交互性,逻辑性较为复杂的app时。需要开发者编写大量底层的api来实现本身的业务逻辑。 Laro出现的目的是为了简化使用canvas制作游戏时的api调用。同时提供了一套“有限状态机”的开发模式,这种模式在对于游戏这一类的典型的“事件驱动”的模型的开发上。能够很好的做到模块间的低耦合,利于开发者梳理整个开发逻辑。 Laro 游戏引擎目前已经完成了游戏开发中所需要的模块和api的封装,并有一些实际的Demo和TestCase供使用者参考。而且随后会结合这个引擎整理出一套用于html5 小游戏开发的可视化编辑工具。 旨在帮助开发者更快更容易的搭建一款小游戏为目的。 目前已经开源到github (https://github.com/AlloyTeam/Laro) 我们团队希望通过Laro的不断完善,能够帮助更多的html5 小游戏开发者以更快的速度,更优的质量完成 html5小游戏 产业化的开发。 Version Log 0.1 - 基础模块搭建 0.2 - 融入jcanvas,配合鼠标事件处理 0.3 - 加强状态机模块 查看以下demo最好使用chrome  : ) http://hongru.github.com/proj/laro/examples/emberwind/ http://hongru.github.com/proj/laro/examples/typeshot/index.html http://hongru.github.com/proj/laro/examples/jxhome/ http://heroes.github.com/world-of-heroes/development/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值