微信小游戏开发:前端篇
上QQ阅读APP看书,第一时间看更新

第1课 创建项目

微信小游戏是小程序的一个特殊分支,其执行环境与运行机制和小程序是一样的。第1课将着手创建一个小游戏项目,通过该项目探讨小游戏的运行机制,快速建立对小游戏开发的概念认知。

了解小游戏的双线程运行机制

微信开发者工具的前身是公众号微页面开发调试工具,而公众号微页面开发有一个配套的SDK(中文版是微信JS-SDK,英文版是Weixin JSSDK),其下载地址如下:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html。

后来几经发展,此SDK就演变成了微信小程序/小游戏底层的WeixinJSBridge。微信小游戏底层双线程示意图如图1-2所示。WeixinJSBridge位于其底层部分。

说明:在谈到环境时,小程序和小游戏是一回事,以下简称小游戏环境。

图1-2 微信小游戏底层双线程示意图

在图1-2中,WeixinJSBridge可以看作小游戏与微信App之间的一个桥梁,小游戏通过它访问手机操作系统的本地存储、网络、罗盘、陀螺仪等硬件设备。

从图1-2也可以看出,在小游戏应用中主要有两个线程:一个线程负责视图层代码执行,另一个线程负责逻辑层代码执行。

□左边是视图层线程,负责视图的渲染。在小程序里,主要使用WXML、WXSS、WXS等进行视图渲染;小游戏里没有WXML组件,主要使用Canvas渲染视图。

□右边是逻辑层线程,负责JS(JavaScript的简称)代码的执行。

在不同系统平台中,小程序在这两个线程的实现上有不同的方式。

□在iOS手机上,视图层渲染是基于iOS的WKWebView实现的,逻辑层代码运行在JavaScriptCore中。

□在Android手机上,视图层渲染是微信基于Mobile Chrome内核自研的XWeb引擎实现的,逻辑层代码运行在谷歌浏览器的V8引擎中。V8是一个由谷歌开发的开源JS引擎,该引擎在笔者提供的预备篇中有提到。

□在微信开发者工具中,视图层渲染是基于Chromium WebView实现的,逻辑层代码运行在NW.js中。Chromium是谷歌浏览器背后的引擎,国内大多数双核浏览器都采用了Chromium内核。NW.js原名Node-Webkit,是一个基于Chromium和Node.js实现的应用运行时,通过它可以用HTML和JS编写桌面应用程序。

这两个线程虽然在不同的平台上有不同的实现方式,但在所有平台上具有相同的协作方式。微信封装了底层差异,开发者才有了跨平台开发的便利。

在逻辑层的JS代码中,像setData这样的方法是通过WeixinJSBridge调用底层的evaluateJavaScript函数发挥作用的;在视图层,当有用户输入时,例如单击了一个按钮,若我们在这个按钮上事先绑定过一个函数,那么这个函数也是通过evaluateJavaScript函数间接被调用的。

有一点需要特别注意,evaluateJavaScript方法的执行效率太低,它是先将数据对象转换为字符串,再将字符串与JS代码拼接成一个脚本文本后才执行的。从逻辑层、视图层到底层,往来调用都是采用这样一种模式,重复且低效。逻辑层与视图层的两个线程是独立的,并不存在直接的调用渠道。具体的调试方式,可以看下面这个示例:

这是一段Java代码,其在Android应用中通过调用mWebview对象的evaluateJavaScript方法来达到执行JS代码的目的。第一行中的变量jsStr是一段准备执行的代码文本。

两个线程单通道通信,不能进行并发操作,往来都要在字符串与对象之间转换,这是小游戏程序产生性能瓶颈的最大原因之一,在开发中尤其要注意。在小程序开发中,JS是主要的编程语言,但是微信又在小程序开发中创造了一个WXS脚本语言,用于在WXML页面中编写直接操作页面元素的代码,并且不能与逻辑层的代码直接进行交互,以在一定程度上缓解这个性能瓶颈。

对于初学者来说,目前阶段了解这些运行机制就足够了,不需要深究。接下来我们开始创建并运行自己的第一个小游戏项目,创建小游戏项目需要一个开发者账号,我们下面先解决这个问题。

注册开发者账号

或许有读者会问,之前注册过小程序账号,这个账号能否直接用于小游戏开发呢?

答案是不可以。虽然小游戏是小程序的一个特殊类目下的分支,但两者账号是独立的。另外,一个邮箱只能注册一个账号,如果已注册过小程序账号,那么此邮箱就不能再用来注册小游戏账号了。

打开微信公众平台(https://mp.weixin.qq.com/),类别选择小程序,开始注册一个小游戏账号,注册过程按提示操作即可。

注意,在注册过程中有一项是选择服务类目,此处一定要选择游戏类目。如果选择了非游戏类目,则该账号只能用于小程序开发,微信是以服务类目区分小程序和小游戏的。

注册完成后,登录账号,打开设置界面进行开发设置,记录下AppID备用。例如,笔者的AppID是wx2e4e259c69153e40,这个AppID在接下来创建项目时会用到。

有读者可能会问,能用别人的AppID吗?

不可以。微信开发者工具需要微信登录,如果登录的微信与小游戏账号绑定的微信不一致,会报出“登录用户不是该小程序的开发者”的错误。

有了小游戏账号,还需要安装一个微信开发者工具,即微信团队开发的专用于小程序/小游戏/公众号项目开发的IDE(集成开发环境)软件,该软件集成了目标项目开发所需的所有常见功能,包括编辑、编译、测试、上传、代码管理等。

安装微信开发者工具

在2017年1月9日小程序上线之前,微信开发者工具就已经存在了,当时它只用于微信内HTML5微页面的开发调试。

在小游戏开发工具的选择上,除了微信官方提供的IDE,还有Egret Wing等第三方提供的集成开发环境,也有人使用Webstorm、Vim、Sublime Text 3或Visual Studio Code作为小游戏项目的开发工具。但对初学者来说,笔者建议使用官方出品的微信开发者工具。官方工具不仅可以开发项目,还附有项目发布、云开发管理、代码管理等内置功能,且与微信提供的小游戏基础库版本最为契合,更新也最为及时。

那么,此工具要如何下载呢?下面是微信开发者工具的下载页面:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html。

注意:这个下载地址以后可能会有变化,如果打不开,可以前往小游戏文档首页(https://developers.weixin.qq.com/minigame/dev/guide/),然后在顶部导航区选择工具,并在侧边栏选择下载即可找到。在笔者的公众号“艺述论”回复关键字10000,也可以找到这个软件的安装包。

微信开发者工具是跨平台的,有3个版本:Windows 64版本、Windows 32版本和Mac版本。开发者可根据自己的操作系统选择,苹果用户选择Mac版本;大多数Windows用户选择Windows 64版本;少数Windows XP系统用户和Windows 7系统用户可以选择Windows 32版本。在选择了与自己的系统匹配的安装包后,下载、解压,并按照提示安装即可。

工欲善其事,必先利其器。在安装了微信开发者工具之后,为了方便开发,提升编码效率,最好对开发环境做一些简单、必要的配置。打开微信开发者工具,在菜单栏依次选择“设置”→“编辑器设置”命令,进行编辑器设置。如图1-3所示,在“文件保存”区域下选中除“修改文件时自动保存”之外的全部选项。这样在开发时,如果对文件进行了修改,就不需要频繁地手动保存了,文件会自动保存;当需要预览项目的运行效果时,直接单击工具栏区域的“编译”按钮就可以了。

图1-3 配置微信开发者工具的编辑器

注意:macOS系统与Windows系统在菜单上略有不同。在Windows系统中,需要先打开一个项目,才可以找到“设置”菜单,这时候可以先随便创建一个小游戏或小程序项目,等创建完了再进行设置。微信开发者工具自发布以来,界面一直在重构,以后操作界面可能会与书中描述的不同,如果按上面提示找不到“设置”菜单或其他子项,可以在其他菜单下尝试寻找。另外,微信开发者工具及基础库版本以后也会有变化,笔者编写书中示例使用的基础库版本是2.19.2,软件版本是Stable 1.05.2108130,读者练习时最好选择与笔者一致的版本。

在微信开发者工具中还有很多其他配置,例如外观、快捷键的设定等,这些都可以根据自己的需求进行设置。

现在我们有了账号和开发者工具,也配置好了环境,准备工作做完了。接下来,我们基于项目模板快速创建一个小游戏项目,并让这个项目运行起来。

创建第一个小游戏项目

打开微信开发者工具,依次选择“小程序项目”→“小游戏”→“新建项目”选项,打开如图1-4所示的项目创建面板。

在图1-4中,项目名称可随意取,笔者填写的是“小游戏从0到1”。目录这里选择一个空目录即可,笔者选择的是“~/work/disc/第1章/1.1/minigame”。AppID填写本课之前注册账号时记录的AppID。后端服务选择“微信云开发”或“不使用云服务”都可以,但如果像笔者一样,该AppID对应的小游戏账号已经开通了云开发环境,则工具默认会选择“微信云开发”。云开发是一种无服务器后端程序开发技术,在《微信小游戏开发:后端篇》一书中会有详细介绍。

若一个空目录作为项目目录被选用,并且AppID是小游戏账号的AppID,那么此时单击“确定”按钮,微信开发者工具将自动基于默认模板创建一个“小飞机”游戏项目。

或许有读者会问,为什么我创建的不是小飞机项目?

这时候就要检查一下是否已输入AppID,因为创建项目时是可以不填写AppID而使用测试号的。另外,你要检查输入的是不是小游戏的AppID。如果确定不是AppID的问题,要检查一下选择的项目目录是不是空目录。

图1-4 小游戏项目创建面板

如果没有注册小游戏账号,也可以单击使用“测试号”,进入免注册快速体验模式。但通过体验模式创建项目,部分功能会受到限制,例如上传、预览等功能就不能使用,一些平台开放接口(诸如登录、拉取用户信息等)也不能调用。如果要系统学习小游戏开发,注册账号是必不可少的。

项目创建之后,如何查看运行效果呢?小游戏怎么样才能在自己的手机上运行呢?这就需要用到预览功能了。

项目测试:本地预览与手机预览

预览有两种形式—本地预览和手机预览,本地预览又包括模拟器预览和PC微信预览。

1.模拟器预览

单击工具栏上的“编译”按钮,即可在左侧的模拟器区域看到小游戏的运行效果,这就是模拟器预览的效果。模拟器预览可以快速查看代码效果,但并不是所有的功能都可以在微信开发者工具的模拟器中测试,部分功能只有在真机上才可以测试。

2.PC微信预览

单击“编译”按钮旁边的“预览”按钮,选择“自动预览”选项,如图1-5所示,这里有两个单选项,“启动手机端自动预览”和“启动PC端自动预览”。以前只有第1个选项,后来PC版微信支持打开小程序或小游戏,就有了第2个选项。选择第2个选项,单击下方的“编译并预览”按钮,即可在PC版微信中预览小游戏效果了。

图1-5 “自动预览”浮窗面板

3.二维码预览

单击“编译”按钮旁边的“预览”按钮,选择“二维码预览”选项,使用开发者微信扫描二维码,即可在手机上预览代码效果。单击工具栏区域的“真机调试”按钮,选择“二维码真机调试”,微信扫描二维码后同样可以在手机上预览代码效果。

在手机上预览效果以后,可以单击右上角胶囊按钮区域内形似三个点的“更多菜单”图标,在屏幕底部弹出的面板中选择“打开调试”选项,即可打开vConsole面板查看调试输出。

选择“预览”选项后,再选择“自动预览”→“启动手机端自动预览”选项,然后单击“编译并预览”按钮,即可在手机上自动预览。

可能有读者会觉得这个自动预览的功能虽然不用扫码,但每次都要单击多次按钮也很枯燥,其实这可以通过设置快捷键来简化。打开“设置”菜单,并选择“快捷键”选项,即可查看和自定义快捷键。

另外一个启动自动真机预览的方法是,选择“真机调试”选项后,再选择“自动真机调试”选项,这样就可以在手机上远程自动预览代码效果。

从上述内容可知,微信开发者工具既有“预览”功能,又有“真机调试”功能,并且两个预览功能里面都各自有二维码预览和自动预览,那么这两个测试功能是雷同的吗?

显然不是,一个IDE一般不会在工具栏上放置完全一样的功能按钮。那么,是左边的“预览”功能限于本地测试,右边的“真机调试”用于远程调试吗?

也不是,在使用后读者就可以发现,预览功能并不要求手机与微信开发者工具必须处于同一种网络下,也就是说手机是4G网络,开发机是Wifi,也不影响测试。预览中的手机其实也可以是远程手机,不一定要在身边。既然如此,那这两个测试按钮有什么区别呢?

它们真正的区别在于测试的重点不同。“预览”主要是预览代码改动后的效果,是将改动后的代码包上传到微信服务器,快速查看整体的运行效果;而“真机调试”侧重于调试,打开后会弹出一个独立于已有调试区的调试窗口,远程手机上的vConsole面板输出会传输到本地微信开发者工具中,便于开发者定位线上问题。

此外有一点需要特别注意,如果测试的代码是未发布的,也就是说版本属于开发版、测试版或体验版,那么必须在小游戏账号后台管理账号的成员管理页面中,将测试手机的微信账号设置为拥有管理员、开发者或体验者权限。

注意:微信开发者工具一直都在进化,关于项目创建、编译、预览等功能的界面设定,以后可能都会有变化,如果读者在阅读时遇到了软件界面与书上内容不完全一致的情况,以官方文档的最新描述为准,下面是官方的工具介绍地址:https://developers.weixin.qq.com/minigame/dev/guide/。

从上述讲解中我们发现,预览并不是完全自动的,无论采用哪种方式,都需要一些手动操作。那么有没有一种方式可以实现真正的自动预览呢?

基于文件监听实现自动预览

既然微信开发者工具可以通过HTTP服务或命令调用,或许我们可以通过监听文件的改动来自动触发微信开发者工具的预览功能。接下来我们尝试实现这个想法。注意,初学者只需了解即可,不需要动手实践。

下面先看一下HTTP服务是怎么使用的。打开微信开发者工具,依次选择菜单中的“设置”→“安全设置”→“安全”选项,开启服务端口,如图1-6所示。

图1-6 工具服务开启及端口设置界面

服务开启的端口号是23546,这个端口号会变化,记录下这个端口号,然后在浏览器中输入以下代码:

上面输入的分别是两个系统下的启动示例。URL后面的projectpath代表项目地址,等号右值是笔者创建的小游戏项目目录,读者在执行时需要换成自己的本地地址。

当尝试打开这个链接时,微信开发者工具将被唤起,并自动打开projectpath参数指定的小游戏项目。

这就是HTTP服务,URL地址中的open代表打开。在微信官方文档上还有其他命令及使用说明,感兴趣的读者可以在以下地址中查看:https://developers.weixin.qq.com/miniprogram/dev/devtools/http.html#自动预览。

这种方式有一个缺陷,即使用时微信开发者工具必须是已经启动的,但上面的那个服务端口号每次重启时都会变化。可见,使用HTTP服务实现真正的自动预览并不是最好的选择。

除了HTTP服务,还可以选择命令行。采用命令行的方式不需要预先启动微信开发者工具,也无须进行端口设置。以macOS系统为例,当我们在终端中执行下面这行命令时,微信开发者工具同样会被唤起并主动打开指定的小游戏项目。

以上是macOS系统上的外部调用方式,在Windows系统下的路径会有所不同,这取决于软件在系统上安装的路径。两个系统上的命令行工具地址如下:

如果Windows系统中安装了Git-SCM,则Git Bash窗口中微信开发者工具的安装地址如下:

那么对应的外部项目启动命令如下:

上面演示的是项目启动命令,如果是自动预览,则命令名称是auto-preview。以macOS系统为例,需要执行的完整命令如下:

注意:因为是在Git Bash窗口中执行的,所以命令中的项目路径是类Windows风格的,以“斜杠+盘符”开头。

执行完上述命令后,Git Bash窗口的输出如图1-7所示。

图1-7 命令行自动预览小游戏项目

命令执行后,如果小游戏项目最近在手机或PC端微信上运行过,便会在宿主环境中自动打开。

我们知道,Node.js有一个fs模块,其中fs.watch方法可以实现对本地目录的自动监控。当我们监控到项目文件有变动时,会自动执行预览命令,这样是不是就能实现真正的自动预览呢?

为了验证这个想法,我们在项目根目录下新建一个watch.js文件,内容如下:

上面是macOS系统的示例,如果是Windows系统,请注意替换脚本地址及项目地址。

在上面的代码中,我们使用了child_process模块,它的exec方法允许我们在JS中执行一条命令。调用语法如下:

其中,exec有如下3个参数。

□command:字符串,表示需要运行的命令,命令参数用空格分隔。

□options:键值对象,可以是一个对象字面量。其属性cwd表示子进程的工作目录,具体用法见watch.js文件第10行。上面的语法中不便给出,有兴趣的读者可以关注下。

□callback:回调函数,形式为(error,stdout,stderr)=>{}。

至此,自动预览的代码写好了,现在我们只要在项目的根目录下执行node watch_macos.js或node watch_windows.js就可以开启监听了。(这是两个系统的测试示例,在随课源码中可以看到。)当项目文件有修改时,手机或PC端微信就会打开项目。如果微信开发者工具未登录,终端将会打印如下错误:

此时只需使用开发者微信账号扫码登录即可。登录以后,文件监听及自动预览功能即可正常工作。唯一美中不足的是,这个自动预览会让手机微信频繁打开项目,甚至在手机上累计打开十几层之多,这种现象在手动操作时是不会出现的。真正使用时,可以考虑使用防抖动函数(debounce)改善监测代码。

除了上面介绍的通过HTTP URL及命令调用微信开发者工具以外,微信还提供了一个自动化SDK,供有自动化需求的开发者在外部操纵微信开发者工具。如果读者感兴趣,可以通过如下地址查看:https://developers.weixin.qq.com/miniprogram/dev/devtools/auto/。

现在我们已经成功创建了小游戏项目,也了解了小游戏项目如何测试,那么硬盘上已经默认创建的项目代码都有哪些功能呢?为什么默认项目要创建这些代码呢?

了解小游戏示例项目的项目结构

我们看一下已经创建的“小飞机”小游戏项目,它在微信开发者工具资源管理器中的截图如图1-8所示。

图1-8小游戏模板项目的结构预览

在图1-8中,game.js是游戏主文件,game.json是游戏配置文件,project.config.json是项目配置文件,audio目录存放的是音频文件,images目录存放的是本地图片。js目录文件较多,包括以下子目录及文件:

该项目下的所有文件,只有game.js与game.json对小游戏是必不可少的,js目录下的base、libs、npc等子目录,属于项目自定义目录。

小游戏所有的配置都是在game.json文件中完成的。在game.json里最常用的配置字段是下面的deviceOrientation与showStatusBar:

其中,deviceOrientation属性用于设定屏幕方向,有portrait(竖屏)、landscape(横屏)两个选项,默认为portrait。showStatusBar设置是否显示系统状态栏,默认为false,即显示全屏。系统状态栏是手机屏幕顶端的那一行窄区域,有Wifi、电量等标志。

现在我们对项目结构有了初步的理解,接下来我们了解一下小游戏如何发布。在微信开发者工具的工具栏右上角有一个“上传”按钮,如图1-9所示。

单击这个按钮即可将本地所有源码打包并上传至微信服务器。当用户在微信里访问小游戏时,是微信服务器在向用户提供在线网络服务。

图1-9 “上传”按钮

这里有一点需要注意,代码包有大小限制。目前每个小游戏的主包不能超过4MB,如果要分包,所有的包加起来总大小不能超过20MB,单个分包不限制大小。

可能有读者会觉得小游戏代码包限制太严格了,其实这已经比小程序好多了,目前微信小程序分包与主包的大小限制均为2MB。随着手机性能的提高,相信代码包限制会逐步放宽。

代码包虽然有大小限制,但是在项目里面,大多数的静态资源文件,如图片、音频、视频等,都是可以以网络资源的形式在项目中使用的,并不占用代码包的配额。代码包中的主要内容是代码文本,压缩之后又能最大限度地减少体积(最高可达70%),所以软件包大小并不值得过分关注。

在软件包上传后,开发者可以在小游戏账号后台(https:mp.weixin.qq.com/)看到待线上提交审核的版本。待审核通过后,小游戏就可以正式面向所有的微信用户发布了。

项目到了提交审核、发布这一步,操作就已经很简单了。在这之前,最重要的步骤还是开发与调试,尤其是在开发中遇到Bug时,需要尽快找到问题并解决,为此微信开发者工具也提供了全面的功能支持。

小游戏如何调试代码

Console接口基本在每个JS宿主环境中都有实现,在小游戏环境中也不例外,前面已讲解过如何在本地及手机上进行项目测试,接下来我们从整体上看一下小游戏如何调试代码。

JS是小游戏主要的开发语言,其调试方法依赖于宿主环境。在传统的网页开发中,可以这样调试代码:

□使用window.alert弹窗展示,或使用document.write方法将内容写到HTML页面中,或使用innerHTML写入HTML元素,在页面上呈现;

□使用console.log将调试信息写到浏览器控制台,这是最常见的一种显式调用方式;

□使用谷歌浏览器或其他IDE提供的断点调试工具,例如微信开发者工具调试区的Sources面板,进行代码步进调试;

□在Network面板中查看网络请求,在Storage面板中查看本地缓存数据。

小游戏底层嵌入了浏览器内核,上述调试方法除第1种外,其他3种都可以在微信开发者工具中使用。接下来我们分别看一下这3种调试方法。

1.使用Console接口调试

在小游戏开发中,一般使用Console面板调试JS代码,使用console.log、console.error等方法在Console面板中主动输出内容。

由于小游戏宿主环境存在差异,因此部分Bug虽然在微信开发者工具中显示不出来,但是在手机上存在,这时就可以在手机上调试。

在手机上运行小游戏后,单击屏幕右上角胶囊状按钮组中的形如三个点的菜单按钮,选择“打开调试”命令。此时小游戏会退出重启,待重新打开后,屏幕右下角会有一个绿色的vConsole按钮。单击这个vConsole按钮,便可以看到手机上的vConsole面板以及代码中使用console.log打印的内容了。

还有部分Bug是在用户的手机上发现的,在开发工具中和在自己的手机上都复现不了。这时,可以使用工具栏中的“真机调试”功能排查问题。单击“真机调试”按钮,会生成一个二维码,将这个二维码发给用户。用户扫码打开游戏后,微信开发者工具会自动打开一个新的浮动调试窗口,用户手机上的vConsole输出会自动同步到这个窗口来。远程真机调试是一个可以很方便地排查用户Bug的方法。

有一点需要注意,在使用微信开发者工具中的“预览”和“真机调试”功能时,测试用户必须注册为测试账号,不然是无法运行开发者的本地代码的。登录微信公众号平台:https://mp.weixin.qq.com/,使用管理员身份可以将用户(微信)添加为体验者,添加之后就可以作为真机调试的用户了。

2.在微信开发者工具中使用断点调试功能

使用Console接口打印,查看输出更简单;使用断点调试,查找问题更高效。如图1-10所示,在调试区打开Sources面板。

图1-10 调试区断点使用示例

以小游戏项目为例,在gameContext分支下找到相关文件的源码,例如js/runtime/main.js的源码,我们在第119行的行号上单击一下,即可添加一个断点,在断点上再次单击即可取消断点。

这个断点位于render方法内,代码执行时它会被持续经过。在Sources面板的右边栏有断点控制按钮,从左到右依次包括暂停/恢复执行(快捷键为F8)、步进(快捷键为F10)、步入(快捷键为F11)、步出(快捷键为Shift+F11)和跳过(快捷键为F9)等按钮。断点控制按钮下方是线程列表、观察列表和栈调用信息表。

当我们想观察某个变量在当前上下文执行环境中是否正常时,可以直接将鼠标移到该变量上。例如,想观察this.bg,可采用如图1-11所示的方法。

当把鼠标放在目标变量之上时,调试区会自动浮出一个小窗口,展示this.bg变量的内容。

图1-11 查看对象的值

我们还可以选中一个变量,如图1-12所示,打开右键菜单,在菜单中选择Add selected text to watches命令,这样这个变量便会出现在右边栏的观察列表中,便于我们在一定时间内多次观察该变量。

图1-12 为变量添加监听

3.使用Network面板和Storage面板

在调试区打开Network面板,如图1-13所示。

图1-13 调试区的Network面板

在小游戏项目中,所有的网络请求,包括接口请求、静态资源请求、云函数都会出现在这个面板中。在这个面板中,既可以查看每个请求的请求时长,也可以在整体上查看所有请求的先后顺序。如图1-14所示,当我们选择靠左的时间段时,请求列表中只有一个gamePage.html。

当向右滑动选择时间段时,网络访问就变多了,如图1-15所示。

图1-14 访问时间线初期对象

图1-15 访问时间线中的后期对象

在选中每个网络请求时,还可以查看其Headers及Response信息,如图1-16所示。

图1-16 查看网络请求对象的详细信息

当网络请求发生错误时,在Headers区域可以看到状态码(status code)不为200(该状态码代表网络请求正常)。如果状态码为200,但是返回的内容不对,则可以在Response区域比对返回的内容。

在Storage面板中,可以看到通过HTML5的localStorage.setItem接口或小游戏中的wx.setStorage接口设置的本地缓存,如图1-17所示。

图1-17 调试区的Storage面板

以上调试手段如何使用呢?在一般情况下,如果基本可以确定代码是正常的,可使用Console接口进行显式输出,输出以后在微信开发者工具或手机上即可查看输出结果,这种方法不会阻碍项目测试的正常进行;如果代码存在异常情况,可以通过查看Network、Storage等面板进一步尝试确定问题;如果操作后问题仍然没有确定,就打开Sources面板,设置断点,一步步查找可能出错的代码位置。

拓展:如何安装、配置Node.js和babel-node

本节看一下如何配置node或babel-node来测试JS代码。

测试JS需要一个宿主环境,简短的JS代码可以直接在谷歌浏览器的Console面板中执行,稍微复杂一点的代码可以使用Node.js测试。

Node.js的安装包下载链接为https://nodejs.org/en/download/。

下载后,按照自己的系统选择适用的安装包,依据提示默认安装即可。笔者安装与使用的版本是v10.22.0,推荐读者也使用这个版本,该版本在随书源码的software目录下也能找到。

安装后,可以用以下命令查看Node.js的版本:

在安装Node.js后,一般的JS代码都可以使用node命令测试。如果读者使用的是Windows系统,可能还需要安装一个Git SCM(网址为https://git-scm.com/)。

用它模拟类Linux终端环境,软件包的具体安装与配置方法详见《微信小游戏开发:后端篇》一书。

在微信公众号“艺述论”上下载的所有随书源码都在disc目录下。假设我们要测试“第1章/1.1/technology.js”这个文件,可以在终端中执行如下命令:

注意:这个文件是不能用node命令直接测试的,因为源码中包含了类的私有属性。截至笔者完稿时,私有属性还是一个实验功能,需要使用Babel先进行转化,之后才能测试。

一般的JS代码,直接使用Node.js测试就够了。但是Node.js在默认情况下是不支持import和export等ES6语法的,包括类的私有字段声明,如果我们在JS代码中想使用这些新的语法,需要使用babel-node代替node命令测试。

接下来开始安装与配置babel-node。

1.初始化目录

初始化目录的命令如下:

2.安装依赖包

安装依赖包的命令如下:

在使用npm或yarn安装模块时,最好指定版本号,避免版本不一致导致的异常情况。

3.配置.babelrc文件

.babelrc文件用于开启语法支持。在默认情况下,import和export等ES6语法是不开启的,需要通过配置文件显式开启。

在项目根目录下新建.babelrc文件,内容如下:

4.进行测试

测试命令示例如下:

注意,替换后面的文件路径为真实路径。

说明:Babel是什么?

@babel/node、@babel/core、@babel/preset-env,还有我们没有安装的命令行工具babel-cli等,都属于Babel工具链。Babel是一个JS版本兼容工具,由于JS标准在各个宿主环境中的支持情况不同,Babel可以帮助我们将使用ES6语法的代码转化为向后兼容的普通代码,从而保证代码在不同宿主环境下都能安全运行。

了解面向对象编程有关的基本概念

在正式开始项目实战之前,初学者还需要了解一些编程基本概念。有经验的读者可以略过本节。

在技术文档中我们经常会看到这些词汇:对象、类、构造器、对象实例、对象类型、方法、函数、成员、实例成员、类成员、实例属性、实例方法、类属性、类方法、类变量、实例变量、存取器等。它们在概念上有什么区别呢?

正确理解这些概念有助于理解全书内容。接下来,我们用一个示例详细解释这些概念,示例如代码清单1-1所示。

代码清单1-1 面向对象概念的综合示例

下面通过上述代码来说明相关概念。

□什么是对象?对象是存在于开发者脑海中的一个抽象概念,开发者将现实世界中的事物进行分析,提取其本质特征,然后用一个名词称呼它。例如用Human代表人类,Human就是一个抽象的对象概念。一个对象会具有开发者需要使用的一些特征信息,例如名称(name)、年龄(age)。不同开发者定义的对象不同,对象含有的信息也不同。

□什么是类?类是由开发者落实在代码中的对象的实际形态,例如第2行中的Technology,它就是一个类。

□什么是构造器?构造器是类中的一个特殊方法,在JS中名称固定是constructor,可以有参数(例如name、age)。当一个类被放在new关键字后面(第18行)时,表示实例化,此时构造器中的代码将被执行,同时有一个实例对象(t)返回。

□什么是对象实例?对象实例是类的一个具体形态,一个类可以有许多实例,每个实例都可以持有自己的数据,不受其他实例影响。在第18行中,t就是一个对象实例;在第23行中,f也是一个对象实例。t与f各自独立,不会互相影响。

□什么是对象类型?狭义地讲就是类。在JS中,有一些类型可以通过构造器函数定义,此时构造器函数也是类型。在第1行中,Technology是使用class定义的一个类,它是对象类型;在第20行至第22行中,Foo作为一个构造器函数,也是对象类型。

□什么是方法?什么是函数?在JS中,函数是一个很大的概念,所有使用function关键字定义的函数、所有箭头函数都是函数。在第16行中,print是一个方法,它也是函数的一种。一般我们认为,属于某个对象的函数称为方法,而不属于任何对象的函数才称为函数。全局函数不属于任何对象,通常情况下,我们会听到“全局函数”这种说法,但很少有人会说“全局方法”。

□什么是成员?一个对象的内部组成部分就是成员。第3行至第16行中的内容都是Technology的成员。

□什么是实例成员?什么是类成员(静态成员)?需要实例化才能访问的成员是实例成员;不需要实例化,直接通过类型名称就能访问的成员是类成员,或称为静态成员。例如在Technology中,存取器name、age、#name和print方法都是实例成员;而第2行和第3行中的#instance和getInstance则是静态成员。

□什么是实例属性、实例方法?通过对象实例才能访问的属性或方法,便是实例属性、实例方法。例如第7行至第14行中的name、age和#name都是实例属性;第16行中的print是实例方法。属性和方法是成员的细分概念。

□什么是类属性、类方法?通过对象类型直接就可以访问的属性或方法便是类属性、类方法。例如第3行中的#instance是类的静态属性,第4行中的getInstance是类的静态方法。

□什么是类变量、实例变量?通过对象类型可以直接访问的变量是类变量,例如第3行中的#instance;通过对象实例才能访问的变量是实例变量,例如第13行和第14行中的age和#name。

□什么存取器?存取器是类中的一种特殊的属性,用于转发对指定实例成员的访问和设置。例如,第7行至第9行是getter属性,它返回私有变量#name;第10行至第12行是一个setter属性,用于设置私有变量#name的值。第24行则调用了名称为name的setter属性。

另外,一般我们在讨论技术时提到的属性,会同时包括外部可以访问的存取器和变量;但如果只说变量,便不包括存取器。

以上便是常见的、易混淆的面向对象相关的概念。这里是以JS语言讲解这些概念的,如果换作Python或者C语言,示例及具体描述方式会有所不同,但所彰显的内在概念是相通的。

本课小结

本课源码参见disc/第1章/1.1。

这节课我们主要安装与配置了本地开发环境,学习了如何创建并运行第一个小游戏项目,还学习了如何调试代码,如何在微信开发者工具中及手机上查验问题。

调试是每个程序员的基本功,在程序员的职业生涯中发挥着极其重要的作用。下一课我们将深入探究示例项目的源码。