2DゲームエンジンPhaserの描画をthree.jsで3Dにする

小さなJavaScriptライブラリをガッチャンコしてゲームエンジンっぽいことをさせるのは可能なのかの微妙に続き。2DのHTML5ゲームライブラリPhaserを使うけど、描画は3Dライブラリのthree.jsを使いたい、みたいな組み合わせは、ちょっと工夫すればできることはできる。試しに作ってみた。

three.jsを初期化する時に、Phaserの画面サイズと同じサイズのthree.jsのrendererを作ってそのターゲットのcanvasからPIXIのtextureを作り、それをスプライトとして貼れば良い。

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(game.width, game.height);
var canvas: HTMLCanvasElement = renderer.domElement;
baseTexture = new PIXI.BaseTexture(canvas, PIXI.scaleModes.DEFAULT);
var texture = new PIXI.Texture(baseTexture);
var textureFrame = new Phaser.Frame(
    0, 0, 0, game.width, game.height,
    'texture', game.rnd.uuid().toString());
var sprite = game.add.sprite(0, 0, texture, textureFrame);

キャラクタを動かす時はPhaserのSpriteと一緒にthree.jsのmeshも作り、フレーム毎にSpriteのpositionに合わせてmeshの位置をアップデートすれば良い。

obj.mesh.position.x = (obj.position.x - game.width / 2);
obj.mesh.position.y = -(obj.position.y - game.height / 2);

Phaserに備え付けのP2物理エンジンと組み合わせても良い。bodyの回転に合わせてmeshのrotationをアップデートすれば回転方向も一致させることができる。

obj.mesh.rotation.z = -obj.body.angle * Math.PI / 180;

2DのSprite相当のものをレンダリングしているだけなので、座標的には2Dのままだが、three.jsでレンダリングできればその豊富なポストエフェクトやライティングを自由に使うことができ、絵作りの幅を広げることができる。工夫すれば背景に奥行きのある3Dの絵とかもできるだろう。

既存のJavaScriptゲームエンジンでも、描画周りを他のライブラリに差し替える、みたいなことは現状でも可能と言えば可能だ。ただ、他のライブラリのrendererで元のrendererを上書きする、みたいなところは裏ワザ的なことがどうしても必要で、先人の知恵に頼らないと厳しいことも多い。この辺がもうちょっと簡単になれば、いろんなライブラリを気軽に組み合わせてゲームを作ることができるんだけどね。