せっかくだから俺も3Dやってみた

phina.js Advent Calendar 2015の20日目です。

emadurandalさん
minimoさん

3Dのゲームを作るよ!

@emadurandal さんが昨日の記事でご紹介されていたとおりphina.jsにはThreeLayerというものがあり、three.jsと連携して3Dゲームを作ることが出来ます。

というわけでさっそくやってみました。

バトルシップ!

私が過去に作った大海戦!ヤマトさんというゲームを3D化したものを開発しています。

まだ作成途中ですが、three.jsのExampleフォルダに入っているWaterShader丸パクリ利用してみました。

また、MagicaVoxelのvoxファイルをjsで使うためのライブラリvox.jsを使い、20分でモデリングした大和型戦艦を登場させています。

今回の記事ではphina.jsとthree.jsを連携する上でいくつか気づいたことをまとめてみます。

phina.asset.AssetManagerでテクスチャをロード

three.jsではテクスチャに画像ファイルを使う際、ImageUtils.loadTexture()メソッドなどを使い画像をロードします。

1
2
3
4
var texture = THREE.ImageUtils.loadTexture( "textures/water.jpg" );
var material = new THREE.MeshPhongMaterial({
map: texture
});

phina.jsにはアセットを一括管理するしくみがありますので、3D用のテクスチャもこちらでロードしたいところです。

そこでこのようにしてみました。

  • ロード時
1
2
3
4
5
6
7
var loadingScene = phina.game.LoadingScene({
assets: {
image: {
"curescarlet": "./assets/curescarlet.png",
}
}
});
  • 利用時
1
2
3
4
var texture = new THREE.Texture(phina.asset.AssetManager.get("image", "curescarlet").domElement);
var material = new THREE.MeshPhongMaterial({
map: texture
});

ロード時は2Dスプライト用のテクスチャとまったく同じです。

利用時は画像アセット(phina.asset.Texture)のdomElementプロパティからimg要素を取得できるので、それをTHREE.Textureのコンストラクタに渡してあげればテクスチャオブジェクトを作ることが出来ます。

Tweenerでアニメーション

phina.accessory.Tweenerを使ったアニメーションは簡単かつ見栄えのする演出方法です。ゲームを作る上ではぜひ利用していきたいしくみですね。

phina.js Advent Calendar 2015でも @simiraaaa さんが記事を書いていらっしゃいます。

Tweenerを使いこなそう!

THREE.Mesh等の3Dオブジェクトでトゥイーンアニメーションを実現するには、phinaのエレメントでラップしてしまうと手っ取り早いです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
phina.define("ThreeElement", {
superClass: "phina.app.Element",
// THREE.Object3Dオブジェクトを受け取る
init: function(threeObject) {
this.superInit();
this.$t = threeObject;
},
// _accessorで座標のgetter/setterを定義する
_accessor: {
x: {
get: function(){ return this.$t.position.x },
set: function(v){ this.$t.position.x = v }
},
y: {
get: function(){ return this.$t.position.y },
set: function(v){ this.$t.position.y = v }
},
z: {
get: function(){ return this.$t.position.z },
set: function(v){ this.$t.position.z = v }
}
}
});
...
// three.jsのメッシュ
var shipThree = new THREE.Mesh(geometory, material);
// phina.jsのエレメントでラップ
var shipPhina = ThreeElement(_ship);
// アニメーション
shipPhina.tweener.to({
x: 1000,
y: 200
}, 3000, "easeOutBack");

カメラなどをスムーズに移動させたい場合に便利ですね。

今回はここまで

というわけで簡単ではありますが、phina.jsとthree.jsを連携する際に覚えておくと便利な使い方でした。