Run Phaser3 on WeChat Minigame Platform
1. Customise Image loader
WeChat platform doesn’t support blob
for the time being hence Phaser’s way of
loading images won’t work here. Some modifications to the source code are neccessary.
> git clone https://github.com/photonstorm/phaser3-custom-build
> cd phaser3-custom-build
> npm install
Go to node_modules/phaser/src/loader/filetypes/ImageFile.js
and change it as following:
...
+ load: function()
+ {
+ this.loader.nextFile(this, true);
+ },
onProcess: function ()
{
this.state = CONST.FILE_PROCESSING;
this.data = new Image();
this.data.crossOrigin = this.crossOrigin;
var _this = this;
this.data.onload = function ()
{
File.revokeObjectURL(_this.data);
_this.onProcessComplete();
};
this.data.onerror = function ()
{
File.revokeObjectURL(_this.data);
_this.onProcessError();
};
- File.createObjectURL(this.data, this.xhrLoader.response, 'image/png');
+ this.data.src = this.url;
},
...
Save it and then:
> cd phaser3-custom-build
> npm run buildfull
Copy ./dist/phaser-full.min.js
to your libs directory, in my case, ./js/libs/
.
2. Update weapp-adapter
> git clone https://github.com/xiandew/weapp-adapter
> cd weapp-adapter
> npm install
> npm run build
Copy ./dist/weapp-adapter.js
to your libs directory.
2.1. If you want to use Phaser’s scene level input manager
If you want Phaser’s scene.input.on("pointerup")
(or plugins that relies on that, e.g. rexvirtualjoystickplugin
) to work properly, you need to add target
to changedTouches
:
Locate the following line in src/EventIniter/TouchEvent.js
:
event.changedTouches = rawEvent.changedTouches
and change it to
event.changedTouches = rawEvent.changedTouches.map((touch) => {
touch.target = event.target
return touch
})
Rebundle the file and copy it to you libs directory.
3. Introduce DOMParser
WeChat minigame doesn’t support DOMParser, which will cause problem if you want to use Phaser’s Bitmap fonts.
xmldom.DOMParser
is used for the DOMParser. I made a custom build to it
so we only need to put a single file under our libs directory rather than a folder.
> git clone https://github.com/xiandew/xmldom-custom-build
> cd xmldom-custom-build
> npm install
> npm run build
Copy ./dist/dom-parser.min.js
to your libs directory.
4. Import
Import the following to whichever file you want to use Phaser.
import './js/libs/weapp-adapter';
import Phaser from './js/libs/phaser.min';
// Only required if you're having issue with parsing XML files.
window.DOMParser = require('./js/libs/dom-parser.min');
5. Expose the global canvas to Phaser
When setup Phaser, make sure to expose WeChat’s global canvas.
var config = {
type: Phaser.CANVAS,
canvas: canvas,
...
};
6. Make sure to switch on touch support
You have to specify input.touch = true
explicitly in config
for Phaser’s touch support.
var config = {
type: Phaser.CANVAS,
canvas: canvas,
input: {
touch: true
}
...
};
7. If you want to make use of WeChat Relationship Chain Data
Making use of WeChat Relationship Chain Data involves sensative privacy of WeChat users so WeChat introduces the idea of “open data domain (ODD)” which is the only place that the relationship chain data can exist.
There are lots of limitations after enabling the ODD. One of them is that the sharedCanvas cannot call getContext
and it breaks Phaser3’s way of rendering CanvasTexture
.
So as a work-around, we need set the sharedCanvas
as the texture directly using texImage2D
(since I’m on WebGL
mode) instead of setting its pixels which are not available in this case.
Once we are clear of that, modifications are pretty simple.
Goto node_modules/phaser/src/textures/CanvasTexture.js
and change as following:
...
function CanvasTexture (manager, key, source, width, height)
{
Texture.call(this, manager, key, source, width, height);
this.add('__BASE', 0, 0, 0, width, height);
/** ... */
this._source = this.frames['__BASE'].source;
/** ... */
this.canvas = this._source.image;
/** ... */
this.context = this.canvas.getContext('2d');
/** ... */
this.width = width;
/** ... */
this.height = height;
+ this.pixels = this.canvas;
+ return;
/** ... */
this.imageData = this.context.getImageData(0, 0, width, height);
/** ... */
this.data = null;
if (this.imageData)
{
this.data = this.imageData.data;
}
/** ... */
this.pixels = null;
/** ... */
this.buffer;
if (this.data)
{
if (this.imageData.data.buffer)
{
this.buffer = this.imageData.data.buffer;
this.pixels = new Uint32Array(this.buffer);
}
else if (window.ArrayBuffer)
{
this.buffer = new ArrayBuffer(this.imageData.data.length);
this.pixels = new Uint32Array(this.buffer);
}
else
{
this.pixels = this.imageData.data;
}
}
},
...
One thing that might be worth mentioning here: don’t expect there are anyhting on the sharedCanvas
after you set its size since resizing it will clear everything drawn.
Ready to go!