《TypeScript图形渲染实战:2D架构设计与实现》
TypeScript图形渲染实战
2D架构设计与实现
步磊峰 编著
前言
TypeScript是由微软公司开发的一种开源编程语言,主要为大型应用而设计。它是JavaScript的一个超集,扩展了JavaScript的语法,任何现有的JavaScript程序都可以不加改变地在TypeScript下工作。
本书使用最新的TypeScript语言,以面向接口及泛型的编程方式,采用HTML 5中的Canvas2D绘图API,实现了一个2D动画精灵系统,并在该精灵系统上演示了精心设计的与图形数学变换相关的Demo。该精灵系统是一个具备最小运行环境(更新、重绘、裁剪,以及事件分发和响应),并支持精确点选(点与点、线段、矩形、圆形、椭圆、三角形及凸多边形),采取了享元设计模式,基于场景图管理且兼容非场景图类型,而且易于扩展的系统。
本书有何特色
1.全程使用TypeScript面向接口的编程语言
本书通过TypeScript语言提供的面向接口编程功能实现了:
* Doom3引擎中文本格式的词法解析器接口;
* 接口一致,且使用了树结构管理(场景图)和线性结构管理(非场景图)的精灵系统,并且能够让场景图类型的精灵系统兼容运行非场景图类型的精灵系统。
2.剖析Canvas2D的底层原理
本书中的Canvas2D相关章节实现了如下几个重要例子:
* 模拟了Canvas2D中的渲染状态堆栈和矩阵变换堆栈,并且在实例中使用自己的矩阵变换堆栈来运行相关例子;
* 实现了类似于Canvas2D文本绘制的各种对齐算法;
* 实现了加强版的drawImage方法,使其支持repeat/repeat-x/repeat-y填充模式的算法(类似于Canvsas2D中的图案填充),并且使用加强版的drawImage实现了九宫格缩放算法(Scale9Grid)。
3.详解图形数学及点与基本几何形体的碰撞检测算法
图形编程的最大“拦路虎”是涉及图形数学变换。书中以图形数学变换为核心实现了以下例子:
* 将平移、缩放和旋转的不同顺序组合绘制出来;
* 通过绘制各种轨迹来观察和理解物体原点变换的奥秘所在;
* 贝塞尔曲线原理动画;
* 坦克方向正确地朝着鼠标指针位置移动(三角函数版);
* 坦克方向正确地朝着鼠标指针位置移动(使用向量缩放来避免使用sin / cos三角函数);
* 坦克方向正确地朝着鼠标指针位置移动(使用从两个方向以向量构建的旋转矩阵来避免使用三角函数atan2,并且用自己实现的矩阵堆栈来替换Canvas2D中的矩阵堆栈);
* 坦克沿着多条贝塞尔曲线围成的封闭路径朝向正确地运动;
* 点投影到向量上的动画效果(涉及向量的所有操作);
* 使用鼠标精确点选旋转中的精灵(测试点与线段、矩形、圆形、椭圆、三角形,以及凸多边形碰撞检测算法及凸多边形判断算法);
* 太阳系模拟动画;
* 骨骼层次精灵动画。
4.提供了几何原理图的生成源代码
本书图形数学相关章节中的几何原理图都是使用Canvas2D直接绘制出来的,并提供了绘制源代码。主要有如下图示:
* 向量方向与大小概念图示;
* 向量的加减法图示;
* 负向量图示;
* 向量与标量乘法图示;
* 向量点乘图示;
* 点与三角形关系图示;
* 凹多边形、凸多边形及三角形扇形化图示;
* 旋转矩阵推导图示。
5.精准地使用设计模式
本书中用到的设计模式如下:
* 使用工厂模式生产各种接口(精灵系统的精灵ISprite和所有基本形体IShape都是由SpriteFactory制造生产的);
* 使用迭代器模式抽象所有具有迭代功能的类或接口(IDoom3Tokenizer、贝塞尔曲线迭代器、树结构深度优先和广度优先的8个线性遍历迭代器);
* 使用模板方法设计模式(Application类通过模板方法模式规定了整个入口类的运行流程);
* 使用适配器模式(在树结构中为了统一线性遍历算法,将队列和栈数据结构适配成一致的操作接口);
* 使用享元设计模式(实现的精灵系统使用享元模式,多个精灵可以共享同一个形体,但是可以有不同的渲染状态、大小、位置和方向等)。
6.详尽地描述了树的数据结构要点
本书专门用一章来介绍树的数据结构,并且详尽地描述了树结构的各种重要算法。
* 基于队列的广度优先方式的4种非递归遍历算法(先根、后根、从左到右、从右到左);
* 基于栈的深度优先方式的4种非递归遍历算法;
* 基于“父亲+儿子”数组方式的深度优先的4种递归遍历算法;
* 基于“父亲+儿子兄弟”方式的深度优先的4种递归遍历算法;
* 基于“父亲+儿子兄弟”方式的深度优先的非递归遍历算法;
* 基于JSON的序列化和反序列化算法。
7.提供完善的技术支持和售后服务
本书提供了专门的售后服务邮箱hzbook2017@163.com。读者在阅读本书的过程中若有疑问,可以通过该邮箱获得帮助。
本书内容及知识体系
第1篇 TypeScript篇(第1、2章)
第1章构建TypeScript开发、编译和调试环境,主要介绍了TypeScript语言的开发、编译和调试环境的搭建,最终形成一个支持源码自动编译、模块自动载入、服务器端热部署及具有强大断点调试功能的TypeScript快捷开发环境。
第2章使用TypeScript实现词法解析器,用TypeScript语言,以面向接口的方式实现了一个Doom3(原id Software公司毁灭战士3游戏引擎)词法解析器;并在此基础上实现了工厂和迭代器两种设计模式,使其支持接口的生成及使用迭代方式进行Token解析输出;同时封装了XMLHttpRequest类,用来支持从服务器端下载要解析的文件。本章还系统地介绍了后续章节中要用到的一些TypeScript常用的语法知识。
第2篇 Canvas2D篇(第3、4章)
第3章动画与Application类,详细介绍了requestAnimationFrame方法与屏幕刷新频率之间的关系;并在此基础上封装了一个支持基于时间的刷新、重绘,以及事件的分发和处理的Application类;还实现了能正确处理CSS盒模型的坐标变换功能;最后添加了支持不同帧率运行的计时器,模拟了setTimeout和setInterval方法的实现。
第4章使用Canvas2D绘图,主要介绍了Canvas2D中矢量图形、文本、图像及阴影绘制的相关内容,实现了一个本章及后续章节都要使用的基于Canvas2D的演示和测试环境。本章需要读者重点关注渲染状态堆栈的实现原理,以及各种文本对齐方式的算法和支持Repeat模式的drawImage实现等内容。
第3篇 图形数学篇(第5~7章)
第5章Canvas2D坐标系变换是本书的精华,通过多个例子演示了Canvas2D中局部坐标系变换的相关知识点,让读者知道变换顺序的重要性,理解变换及掌握原点变换的几种方式;并且通过太阳自转和月亮自公转的例子,介绍了Canvas2D中矩阵堆栈层次变换的用法;最后通过一个坦克跟随鼠标指针朝向正确地运动Demo,深入讲解了一些常用三角函数的应用。
第6章向量数学及基本形体的点选,首先讲述了向量的一些基本操作,然后通过向量的加法和缩放操作替换第5章坦克Demo中使用的sin/cos函数。为了演示向量的一些基本操作,特意实现了点投影到向量的动画效果Demo;给出了点与线段、圆、矩形、椭圆、三角形及凸多边形等基本形体之间的碰撞检测算法;最后给出了本章所有几何图示的生成源代码,便于读者更加深入地理解向量各个操作背后的几何含义。
第7章矩阵数学及贝塞尔曲线,首先讲述了矩阵的相关知识,重点推导了旋转矩阵;然后将第5章中的坦克Demo用矩阵方式重写,演示如何通过两个单位向量构建旋转矩阵,从而消除对atan2函数的使用;接着模拟了Canvas2D中的矩阵堆栈,并用自己实现的矩阵堆栈重写坦克Demo;最后介绍了贝塞尔曲线多项式的推导过程,并实现了一个曲线动画的Demo。
第4篇 架构与实现篇(第8~10章)
第8章精灵系统,以面向接口编程的方式实现了一个精灵系统,并在该系统上实现了一个Demo,用来测试系统的点与各个基本形体之间的精确碰撞检测。该系统具有必要的功能(更新、绘制、鼠标和键盘事件的分发与响应),使用了非场景图类型,支持精确点选,基于保留模式,并采用了享元设计模式。
第9章优美典雅的树结构,主要介绍了树结构的增、删、改、查,以及各种遍历算法,最后实现了树结构的JSON序列化和反序列化算法。本章重在灵活应用TypeScript泛型编程,涉及不少泛型编程的细节。
第10章场景图系统,融合前面章节所讲知识,以面向接口的编程方式实现了一个精灵系统。该系统具有必要的功能(更新、重绘、裁剪及事件分发和响应),使用了场景图类型(建立在第9章的树结构上),支持精确点选,基于非立即渲染模式(保留模式),采用了享元设计模式,兼容运行第8章的非场景图类型。在此基础上,通过骨骼层次精灵动画,演示了场景图的层次变换功能及享元模式的优点;最后实现了坦克沿着贝塞尔路径朝向正确运行的Demo,以演示该精灵系统的综合特点。
本书配套资源获取方式
本书涉及的源代码文件和Demo需要读者自行下载。请登录华章公司网站www.hzbook.com,在该网站上搜索到本书,然后单击“资料下载”按钮即可在页面上找到“配书资源”下载链接。
运行书中的源代码需要进行以下操作:
(1)按照本书第1章中的介绍下载并安装Node.js和VS Code。
(2)在VS Code的终端对话框中输入npm install命令,自动下载运行依赖包。
(3)下载好依赖包后继续输入npm run dev即可自动运行Demo。
本书读者对象
* 对图形、游戏和UI开发感兴趣的技术人员;
* 想转行到图形开发领域的技术人员;
* 需要全面学习图形开发技术的人员;
* 想从C/C++、Java、C#、Objective-C等语言转HTML 5开发的技术人员;
* JavaScript程序员;
* 想学习TypeScript的程序员;
* 想提高编程水平的人员;
* 在校大学生及喜欢计算机编程的自学者;
* 专业培训机构的学员。
本书阅读建议
* 没有图形框架开发基础的读者,建议从第1章顺次阅读并演练每一个实例。
* 有一定图形开发基础的读者,可以根据实际情况有重点地选择阅读各个模块和项目案例。对于每一个模块和项目案例,先思考一下实现思路,然后阅读,效果更佳。
* 可以先阅读书中的模块和Demo,再结合配套源代码理解并调试,这样更加容易理解,而且也会理解得更加深刻。
本书作者
本书由步磊峰编写。感谢在本书编写和出版过程中给予了笔者大量帮助的各位编辑!
由于笔者水平所限,加之写作时间较为仓促,书中可能还存在一些疏漏和不足之处,敬请各位读者批评指正。
步磊峰
目录
前言
1.3.2 解决生成tsconfig.json文件后带来的常见问题 13
1.4.1 tsconfig.json文件中的target和module命令选项 16
1.4.2 编写Canvas2D类导出给main.ts调用 16
1.5 使用SystemJS自动编译加载TypeScript 18
1.5.1 NPM本地安装TypeScript库和SystemJS库 18
1.5.2 SystemJS直接编译TypeScript源码 19
1.6 使用VS Code调试TypeScript源码 20
1.6.1 安装及配置Debugger for Chrome扩展 20
1.6.2 VS Code中单步调试TypeScript 20
第2章 使用TypeScript实现 Doom 3词法解析器 24
2.1.2 使用IDoom3Token与IDoom3Tokenizer接口 26
2.1.4 IDoom3Token与IDoom3Tokenizer接口的定义 29
2.2 IDoom3Token与IDoom3Tokenizer接口的实现 30
2.2.5 Doom3Tokenzier处理数字和空白符 34
2.2.6 IDoom3Tokenizer接口方法实现 34
2.2.7 Doom3Tokenizer字符处理私有方法 35
2.2.10 实现_getNumber方法解析数字类型 38
2.2.11 实现_getSubstring方法解析子字符串 40
2.2.13 IDoom3Tokenizer词法解析器状态总结 42
2.3.4 模拟微软.NetFramework中的泛型迭代器 44
2.3.5 IDoom3Tokenizer扩展 IEnumerator接口 45
3.1 requestAnimationFrame方法与动画 60
3.1.2 requestAnimationFrame与监视器刷新频率 62
3.2.7 使用getBoundingRect方法变换坐标系 75
3.2.8 将DOM Event事件转换为CanvasInputEvent事件 77
3.2.9 EventListenerObject与事件分发 77
3.2.11 Canvas2DApplication子类和WebGLApplication子类 79
3.3.1 继承并覆写Application基类的虚方法 80
3.3.5 CSS盒模型对_viewportToCanvasCoordinate的影响 84
3.3.6 正确的_viewportToCanvasCoordinate方法实现 86
3.4.1 Timer类与TimeCallback回调函数 90
第4章 使用Canvas2D绘图 98
4.1 绘制基本几何体 98
4.1.1 Canvas2DApplication的绘制流程 98
4.1.2 绘制矩形Demo 99
4.1.3 模拟Canvas2D中渲染状态堆栈 100
4.1.4 线段属性与描边操作(stroke) 103
4.1.5 虚线绘制(交替绘制线段) 105
4.1.6 使用颜色描边和填充 108
4.1.7 使用渐变对象描边和填充 110
4.1.8 使用图案对象描边和填充 113
4.1.9 后续要用到的一些常用绘制方法 115
4.2 绘制文本 117
4.2.1 封装fillText方法 117
4.2.2 文本的对齐方式 119
4.2.3 自行实现文本对齐效果 121
4.2.4 计算文本高度算法 122
4.2.5 嵌套矩形定位算法 122
4.2.6 fillRectWithTitle方法的实现 125
4.2.7 自行文本对齐实现Demo 126
4.2.8 font属性 128
4.2.9 实现makeFontString辅助方法 129
4.3 绘制图像 130
4.3.1 drawImage方法 131
4.3.2 Repeat图像填充模式 133
4.3.3 加强版drawImage方法的实现 134
4.3.4 加强版drawImage方法效果演示 136
4.3.5 离屏Canvas的使用 137
4.3.6 操作Canvas中的图像数据 138
4.4 绘制阴影 141
4.5 本章总结 142
第3篇 图形数学篇
第5章 Canvas2D坐标系变换 146
5.1 局部坐标系变换 146
5.1.1 准备工作 146
5.1.2 平移操作演示 149
5.1.3 平移和旋转组合操作演示 150
5.1.4 绘制旋转的轨迹 152
5.1.5 变换局部坐标系的原点 154
5.1.6 测试fillLocalRectWithTitle方法 156
5.1.7 彻底掌控局部坐标系变换 158
5.1.8 通用的原点变换方法 166
5.1.9 公转(Revolution)与自转(Rotation) 169
5.1.10 原点变换的另一种方法 171
5.2 坦克Demo 173
5.2.1 象限(Quadrant)文字绘制 174
5.2.2 坦克形体的绘制 175
5.2.3 坦克及炮塔的旋转 178
5.2.4 计算坦克的朝向 179
5.2.5 坦克朝着目标移动 182
5.2.6 使用键盘控制炮塔的旋转 183
5.2.7 初始朝向的重要性 184
5.2.8 朝向正确的运行 187
5.2.9 坦克朝着目标移动效果的生成代码 189
5.3 本章总结 190
第6章 向量数学及基本形体的点选 192
6.1 向量数学 192
6.1.1 向量的概念 192
6.1.2 向量的大小与方向 194
6.1.3 向量的加减法及几何含义 196
6.1.4 负向量及几何含义 198
6.1.5 向量与标量乘法及几何含义 198
6.1.6 向量标量相乘取代三角函数sin和cos的应用 200
6.1.7 向量的点乘及几何含义 201
6.1.8 向量的夹角及朝向计算 203
6.2 向量投影Demo 203
6.2.1 Demo的需求描述 205
6.2.2 绘制向量 205
6.2.3 向量投影算法 207
6.2.4 投影效果演示代码 208
6.2.5 向量getAngle和getOrientation方法的区别 210
6.3 点与基本几何形体的碰撞检测算法 211
6.3.1 点与线段及圆的碰撞检测 211
6.3.2 点与矩形及椭圆的碰撞检测 213
6.3.3 点与三角形的碰撞检测 213
6.3.4 点与任意凸多边形的碰撞检测 215
6.4 附录:图示代码 217
6.4.1 图6.1向量概念图示源码 217
6.4.2 图6.2和图6.3向量加减法图示源码 218
6.4.3 图6.4负向量图示源码 218
6.4.4 图6.5向量与标量相乘图示源码 219
6.4.5 图6.6向量的点乘图示源码 219
6.4.6 图6.11点与三角形的关系图示源码 220
6.4.7 图6.12和图6.13 凹凸多边形图示源码 221
6.5 本章总结 222
第7章 矩阵数学及贝塞尔曲线 223
7.1 矩阵数学 223
7.1.1 矩阵乘法 223
7.1.2 单位矩阵 225
7.1.3 矩阵求逆 225
7.1.4 用矩阵变换向量 226
7.1.5 平移矩阵及其逆矩阵 227
7.1.6 缩放矩阵及其逆矩阵 228
7.1.7 旋转矩阵及其逆矩阵 230
7.1.8 从两个单位向量构建旋转矩阵 233
7.1.9 使用makeRotationFromVectors方法取代atan2的应用 234
7.1.10 仿射变换 237
7.1.11 矩阵堆栈 237
7.1.12 在坦克Demo中应用矩阵堆栈 239
7.1.13 图7.1旋转矩阵推导图示绘制源码 243
7.2 贝塞尔曲线 245
7.2.1 Demo效果 245
7.2.2 使用Canvas2D内置曲线绘制方法 246
7.2.3 伯恩斯坦多项式推导贝塞尔多项式 249
7.2.4 贝塞尔曲线自绘版 251
7.2.5 鼠标碰撞检测和交互功能 253
7.2.6 实现贝塞尔曲线枚举器 255
7.3 本章总结 257
第4篇 架构与实现篇
第8章 精灵系统 260
8.1 精灵系统的架构与接口 260
8.1.1 应用程序的入口与命令分发 262
8.1.2 IRenderState、ITransformable和ISprite接口 265
8.1.3 IDrawable、IHittable和IShape接口 267
8.2 实现非场景图类型精灵系统 268
8.2.1 Transform2D辅助类 269
8.2.2 ISprite接口的实现 269
8.2.3 Sprite2DManager管理类 272
8.3 IShape形体系统 275
8.3.1 线段Line类 276
8.3.2 BaseShape2D抽象基类 278
8.3.3 Rect类和Grid类 280
8.3.4 Circle类和Ellipse类 281
8.3.5 ConvexPolygon类 282
8.3.6 Scale9Grid类 283
8.3.7 SpriteFactory生产IShape产品 289
8.4 精灵系统测试Demo 290
8.4.1 Demo的运行流程 291
8.4.2 创建各种IShape对象 292
8.4.3 创建网格精灵和事件处理函数 293
8.4.4 非网格精灵的事件处理函数 295
8.4.5 Demo的入口代码 296
8.5 本章总结 296
第9章 优美典雅的树结构 298
9.1 树的数据结构 298
9.1.1 树结构简介 298
9.1.2 树节点添加时的要点 300
9.1.3 树节点isDescendantOf和remove方法的实现 300
9.1.4 实现添加树节点方法 303
9.1.5 树结构的层次关系查询操作 304
9.2 树数据结构的遍历 308
9.2.1 树结构遍历顺序 308
9.2.2 树结构线性遍历算法 309
9.2.3 树结构遍历枚举器 310
9.2.4 树结构枚举器的实现 311
9.2.5 测试树结构枚举器 316
9.2.6 深度优先的递归遍历 320
9.2.7 使用儿子兄弟方式递归遍历算法 321
9.2.8 儿子兄弟方式非递归遍历算法 323
9.3 树数据结构的序列化与反序列化 327
9.3.1 树节点自引用特性导致序列化错误 328
9.3.2 树节点的序列化和反序列化操作 328
9.4 队列与栈的实现 331
9.5 本章总结 332
第10章 场景图系统 334
10.1 实现场景图精灵系统 334
10.1.1 非场景图精灵系统的不足之处 334
10.1.2 树结构场景图系统 336
10.1.3 矩阵堆栈和场景图 338
10.1.4 实现场景图精灵系统概述 338
10.1.5 核心的SpriteNode类 338
10.1.6 实现SpriteNode类的接口方法 340
10.1.7 SpriteNode的findSprite方法实现 342
10.1.8 递归的更新与绘制操作 343
10.1.9 SpriteNodeManager类 344
10.1.10 修改Sprite2D类的getWorldMatrix方法 346
10.1.11 让Sprite2DApplication类支持场景图精灵系统 347
10.2 骨骼层次精灵Demo 348
10.2.1 实现骨骼形体 348
10.2.2 SkeletonPersonTest类 349
10.2.3 事件处理程序 351
10.2.4 使用renderEvent事件 354
10.2.5 本节总结 356
10.3 坦克沿贝塞尔路径运动Demo 357
10.3.1 实现BezierPath形体类 358
10.3.2 需求描述 359
10.3.3 Demo的场景图 361
10.3.4 TankFollowBezierPathDemo类初始化 361
10.3.5 创建锚点、控制点及连线精灵 363
10.3.6 创建二次贝塞尔路径及坦克精灵 364
10.3.7 键盘事件处理方法 365
10.3.8 鼠标事件处理方法 366
10.3.9 坦克沿路径运动的核心算法 367
10.3.10 让坦克动起来 368
10.4 让精灵系统支持裁剪操作 370
10.5 本章总结 372
- 点赞
- 收藏
- 关注作者
评论(0)