【转】利用 three.js 开发微信小游戏的尝试
前言
这是一次利用 three.js
开发微信小游戏的尝试,并不能算作是教程,只能算是一篇笔记吧。
微信 WeChat 6.6.1 开始引入了微信小游戏,初期上线了一批质量相当不错的小游戏。我在查阅各处的文章时候,发现其中有几款是基于 three.js 开发的,目前火爆朋友圈的《跳一跳》就是其中之一。这引起了我的注意,想起几年前也做过不少 WebGL 的尝试,于是禁不住想要弄到微信小游戏平台上试试。
准备工作
另外补充一点:需要足够的耐心,微信开发者工具问题多多,编辑器也各种问题,我是使用 WebStorm 来编写代码,您不妨也试试。遇到奇怪的问题的时候,可能需要多启动几次开发者工具,非常令人恼火。
找一个之前的 WebGL 演示
我随便找了一个很久以前做过的演示代码,如下:
(无法嵌入,如要查看请看原文)可以拖动旋转,滚轮缩放
利用 three.js 开发微信小游戏的尝试indienova.com
创建微信小游戏项目
好啦,现在可以进入开发者工具尝试移植了。
首先,创建一个标准的小游戏项目。
选择“小游戏”项目进行创建,并选择一个空的目录作为项目目录
点击“确定”就会打开一个模板项目,是一个射击游戏,大致的结构如下:
├── game.js
├── game.json
├── project.config.json
├── README.md
├── js
| ├── databus.js
| ├── main.js
| ├── base
| | ├── animation.js
| | └── ...
| ├── libs
| | ├── symbol.js
| | └── weapp-adapter.js
| ├── npc
| | └── enemy.js
| ├── player
| | ├── bullet.js
| | └── ...
| └── runtime
| ├── background.js
| └── ...
├── audio
| ├── bgm.mp3
| └── ...
└── images
├── Common.png
└── ...
基于这个模板,我们可以将不需要的内容暂时删除,以便跑我们自己的项目。其中,射击游戏相关的内容都可以移除了,但是我们要保留一些关键的代码和配置文件,清理以后,大概会是这个样子:
├── game.js
├── game.json
├── project.config.json
├── README.md
├── js
| ├── main.js
| └── libs
| ├── symbol.js
| └── weapp-adapter.js
└── images
- 其中,
images
目录里面放置我们需要使用到的图片,在这个例子中,我放了粒子图片和 indienova Logo 图片在里面; - 将我们必然会用到的
three.js
(使用three.min.js
也可以,但是后面需要修改这个文件,所以建议使用没有 minified 的版本)放入js/libs
; - 如果有其它资源,比如音频文件什么的,也可以自建目录放进去;
- 然后需要修改一下配置文件,简单的说,只要修改
project.config.json
中的projectname
即可; - 保留
game.js
不变,这个是入口,会引入main.js
并执行; - 将
main.js
清空,我们的新代码会在这里完成。
我们还保留了两个 js 文件,libs
中的 symbol.js
和 weapp-adapter.js
。这里需要注意的是 weapp-adapter.js
很重要,官方解释如下:
小游戏的运行环境在 iOS 上是 JavaScriptCore,在 Android 上是 V8,都是没有 BOM 和 DOM 的运行环境,没有全局的 document 和 window 对象。因此当你希望使用 DOM API 来创建 Canvas 和 Image 等元素的时候,会引发错误。
…………
这些使用 wx API 模拟 BOM 和 DOM 的代码组成的库称之为 Adapter。顾名思义,这是对基于浏览器环境的游戏引擎在小游戏运行环境下的一层适配层,使游戏引擎在调用 DOM API 和访问 DOM 属性时不会产生错误。Adapter 是一个抽象的代码层,并不特指某一个适配小游戏的第三方库,每位开发者都可以根据自己的项目需要实现相应的 Adapter。官方实现了一个 Adapter 名为 weapp-adapter, 并提供了完整的源码,供开发者使用和参考。…………
除此之外 weapp-adapter 还模拟了以下对象和方法:
document.createElement
canvas.addEventListener
localStorage
Audio
Image
WebSocket
XMLHttpRequest
等等...需要强调的是,weapp-adapter 对浏览器环境的模拟远不完整的,仅仅只针对游戏引擎可能访问的属性和调用的方法进行了模拟,也不保证所有游戏引擎都能通过 weapp-adapter 顺利无缝接入小游戏。直接将 weapp-adapter 提供给开发者,更多地是作为参考,开发者可以根据需要在 weapp-adapter 的基础上进行扩展,以适配自己项目使用的游戏引擎。
原文请参阅:这里。
可见,微信团队已经为我们开发游戏做好了一些准备,比如露出的 canvas
,我们到时候直接拿来使用就是。
将之前的代码移植到项目中
开始将之前写好的代码移植过来,注意由于要使用 ES 6(EMCAScript 6)标准,所以之前的代码可能要做相应的调整,不过大部分都是语法的调整,有一些方法的使用需要增加 bind(this)
,具体的还请大家参阅我们提供的链接地址,就算不看书,随便尝试一下也能很快有所了解。
新的 main.js
的主体代码看起来是这样:
import * as THREE from 'libs/three.js'
let ctx = canvas.getContext('webgl')
let scene
let renderer
// ... 其它变量/常量 ...
/**
* 游戏主函数
*/
export default class Main {
constructor() {
this.start()
}
start() {
// 初始化
scene = new THREE.Scene()
renderer = new THREE.WebGLRenderer({ context: ctx })
//... 其它代码块 ...
// 开始循环
this.loop()
}
// UPDATE 更新
update() {
// ... 数据更新代码块 ...
}
// RENDER 渲染
render() {
// ... 渲染代码块 ...
}
// 实现游戏帧循环
loop() {
this.update()
this.render()
window.requestAnimationFrame( this.loop.bind(this), canvas )
}
}
一些要点:
由于微信已经为我们准备好了的 canvas
,所以我们无需自己再进行创建,只需要取得的 canvas
的 context
就可以了,这里我们使用的不是 2d
,而是 webgl
。
let ctx = canvas.getContext('webgl')
然后我们在创建 WebGLRenderer
的时候,直接使用这个 context
就可以了。
renderer = new THREE.WebGLRenderer({ context: ctx })
这两点做到了,基本上就不会有太大问题了。
一切正常的话,开发者工具里面应该就能跑得起来了。
能跑起来并不算完,还需要真机测试
真机调试
真机调试不复杂,微信开发者工具提供了真机预览功能,只要点一下“预览”,就会上传代码,并生成二维码供测试。
https://mp.weixin.qq.com/a/~~KXw-v1yT0Xw~q6neR3F6N1Q9g8Uzb0yOVA~~ (二维码自动识别)
开发者用微信扫描这个二维码,就可以打开测试。
如果您没有修改过 three.js 源文件,那么很有可能只看到一个黑屏。
还好,微信小游戏提供了一个调试开关,我们可以选择打开调试:
然后再次扫码进入,就可以查看调试信息了:
可以清晰的得知,createElementNS
不被支持,那么我们可以将所有 createElementNS
改为 createElement
:(注意,这只是暂时解决方案,此方法并不是理想方案,我们以后应该会有更好的解决方法,通过修改 adapter 应该就可以减少 three.js 源文件的修改。)
document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
// 改为 ==>
document.createElement( 'canvas' );
不止这一处,而且也不止是针对 canvas 的创建,还有针对 img 的创建,可以都修改掉。
另外由于真机上跑的是 OpenGL ES 1.x/2.x/3.x,所以还有一句要处理:
var version = parseFloat( /^WebGL\ ([0-9])/.exec(gl.getParameter(gl.VERSION))[ 1 ] );
// 改为 ==>
var version = parseFloat( /^(WebGL|OpenGL ES)\ ([0-9])/.exec(gl.getParameter(gl.VERSION))[ 1 ] );
这样改过后,重新再尝试一下看,是不是已经可以了?
2018-01-08 更新
临时解决方案使用后,我后来尝试修改 weapp-adapter.js
,就不需要再对 three.js
进行修改了:
createElementNS: function createElementNS(nameSpace, tagName) {
return this.createElement(tagName)
}
方法很简单:我们在 document
的定义中添加 createElementNS
,然后忽略掉 NameSpace 即可。
结束语
好了,简单的介绍了一下怎么利用 three.js
开发微信小游戏,这并不是一篇教程,只是在目前信息和资料不完善情况下的一种尝试,也希望大家一起参与到开发和研究中来,互相交流。
欢迎加入我们的小组:微信小游戏小组
微信小游戏 | indienova 独立游戏indienova.com
源代码
为了方便大家参考,特提供源代码。其中包括一个微信小游戏项目和原始的 WebGL 项目。
Github 源代码下载
eastecho/WeChatGame-three-jsgithub.com
参考链接
这几天研究这部分内容的时候,遇到不少奇怪的问题,这部分内容又很难依靠 Google 和 StackOverflow 来解决,还好找到了交流的 QQ 群,以及群中成员的交流心得,才算完成了这次尝试。
- 参与的微信小游戏 QQ 群:117844722
- 参考的文章:在微信小游戏中使用 three.js 显示3D 图形
其它相关链接
请先阅读:微信小游戏官方文档
目前,Cocos、Egret、Laya 已经完成了自身引擎及其工具对小游戏的适配和支持,访问对应的官方文档可以更快地接入小游戏的开发
- Cocos:http://docs.cocos.com/creator/manual/zh/publish/publish-wechatgame.html
- Egret:http://developer.egret.com/cn/github/egret-docs/Engine2D/minigame/introduction/index.html
- Laya:https://ldc.layabox.com/doc/?nav=zh-as-3-4-5
您可能感兴趣的
原文链接:https://zhuanlan.zhihu.com/p/32648805
【转】利用 three.js 开发微信小游戏的尝试的更多相关文章
- 使用Laya引擎开发微信小游戏(上)
本文由云+社区发表 使用一个简单的游戏开发示例,由浅入深,介绍了如何用Laya引擎开发微信小游戏. 作者:马晓东,腾讯前端高级工程师. 微信小游戏的推出也快一年时间了,在IEG的游戏运营活动中,也出现 ...
- 用Vue.js开发微信小程序:开源框架mpvue解析
前言 mpvue 是一款使用 Vue.js 开发微信小程序的前端框架.使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为 H5 和小程序提供了代码复用的能力.如果想将 H5 项目改造为小程 ...
- 使用Laya引擎开发微信小游戏
在支持微信小游戏的游戏引擎中,Cocos,Egret,Laya都对小游戏的开发提供了很多强大的支持.前段时间正好抽空研究了一下这块的内容,现做一个总结,针对如何使用Laya引擎开发微信小游戏给大家做一 ...
- MPVUE - 使用vue.js开发微信小程序
MPVUE - 使用vue.js开发微信小程序 什么是mpvue? mpvue 是美团点评前端团队开源的一款使用 Vue.js 开发微信小程序的前端框架.框架提供了完整的 Vue.js 开发体验,开发 ...
- 使用Laya引擎开发微信小游戏(下)
本文由云+社区发表 6. 动画 6.1 创建伞兵对象 在src目录下创建一个新目录role,用来存放游戏中角色. 在role里创建一个伞兵Soldier.ts对象文件. module role{ ex ...
- Egret白鹭开发微信小游戏排行榜功能
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 我的个人博客 最近事情特别多,今天终于实现了排行榜功能,记录下来大家一起学习学习. 一.调用默认排行榜 首先我们需要了解: 1.白鹭开 ...
- Egret白鹭开发微信小游戏分享功能
今天给大家分享一下微信分享转发功能,话不多说,直接干 方法一: 1.在egret中打开Platfrom.ts文件,添加代码如下(当然,你也可以直接复制粘贴) /** * 平台数据接口. * 由于每款游 ...
- Egret白鹭开发微信小游戏程序跳转功能(由一个小游戏跳转到另一个小游戏)
假设我们要实现的功能是从小游戏A跳转到小游戏B 对于小游戏A: (1)在platform.ts中添加代码如下: /** * 平台数据接口. * 由于每款游戏通常需要发布到多个平台上,所以提取出一个统一 ...
- cocos creator开发微信小游戏记录
先用cocoscreator实现游戏逻辑 在cocoscreator项目里可以调用微信小游戏api 在cocos里面判断小游戏的运行环境 if (cc.sys.platform === cc.sys. ...
随机推荐
- Cocos2D中相关问题提问的几个论坛
如果和SpriteBuilder相关可以到: http://forum.spritebuilder.com 提问. 如果是Cocos2D的问题,则可以到以下论坛询问: http://forum.coc ...
- saiku运行时报错max_length_for_sort_data 需要set higher
infiniDB或者mysql数据库,运行时,按某个字段排序会出错.报错:max_length_for_sort_data ... set higher. saiku报错, 也是这样. 这是数 ...
- OSB开发常用资料
成功搭建OSB环境并运行HelloWorld项目 http://www.beansoft.biz/?p=2066 Oracle Service Bus 11gR1开发环境安装文档 http://www ...
- linux下ruby使用tcl/tk编程环境设置
正常情况下最新的ruby都是不带tcl/tk选项编译的,所以我们在运行tcl/tk代码时都会发生找不到tk库的错误.解决办法很简单只要以tcl/tk选项编译ruby即可. 这里以ubuntu 15.0 ...
- Java线程专栏文章汇总
转载自 http://blog.csdn.net/ghsau/article/details/17609747 JDK5.0之前传统线程 Java线程(一):线程安全与不安全 J ...
- 网站开发进阶(三)Windows NAT端口映射
Windows NAT端口映射 由于有需求进行端口映射,又不想装乱七八糟的软件,Windows本身自带的路由远程访问配置太麻烦,还要两块网卡,坑爹啊. 其实Windows本身命令行支持配置端口映射,条 ...
- sql记录去重(SQL查询或者删除表中重复记录)
.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select*from people where peopleIdin (select peopleIdfrom peopl ...
- 【49】java内部类剖析
什么是内部类: 定义在其他类(outer class)中的类被称作内部类.内部类可以有访问修饰服,甚至可以被标记为 abstract 或 final. 内部类与外部类实例有特殊的关系,这种关系允许内部 ...
- linux下将eclipse项目转换为gradle项目
本文针对于在linux环境下,不使用eclipse而把一个eclipse项目转换为gradle默认结构的项目的情况,脚本可能在mac下也适用,未验证. windows中的转换问题,以及使用eclips ...
- PS 滤镜算法原理——拼贴
%%%% Tile %%%%% 实现拼贴效果 %%%%% 将原图像进行分块,然后让图像块在 %%%%% 新图像范围内进行随机移动,确定移动后的边界 %%%%% 将移动后的图像块填入新图像内 clc; ...