phina.js + three.jsでモーションコントローラー作った

JavaScriptで本格的な3Dゲームが作りたいんだ!アニキ!

そろそろJSでも3Dゲームの時代ってことで、俺が愛してやまないphina.jsとそれほどでもないthree.jsでゲームを作ってる。

モーションを再生したいんだぜ!

3Dでゲームつったらやっぱボーン入れてモーションつけて動かしたいわけです。

three.jsにはblenderからデータを読み込む仕組みがあるので、これを利用してちょっとしたモーションコントローラーを作ってみた。

Unityのやつを参考にしたのでわりと似ている。

上記のサンプルはblenderで作成したモーションを読み込んで動かしてる。

使い方はこんな感じで。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 敵キャラをロードしてシーンに配置
let enemy = SkinnedMesh("enemy3").addChildTo(this);
// アイドルモーション
let motionIdle = enemy.getMotion("idle");
// アイドルモーションはループON
motionIdle.setLoop(true);
// 攻撃モーション
let motionAttack = enemy.getMotion("attack0");
// アイドルモーションにトランジションを追加。
// タップフラグが立ったら攻撃モーションへ移行する。
motionIdle.addTransition(() => tapFlag, motionAttack, 10);
// 攻撃モーションにトランジションを追加。
// モーションが「完了」したらアイドルモーションへ移行する。
motionAttack.addTransition("finished", motionIdle, 10);
// 敵キャラのモーションをアイドルモーションにスイッチ。
enemy.motionController.switchMotion(motionIdle);

まず、SkinnedMeshというクラスを用意した。

これはthree.jsのBlendCharacterというクラスを単純にラップしたものだ。phina.js のシーングラフに追加できるようにphina.app.Elementを継承している。

さらにMotionControllerというクラスを実装した。こちらはSkinnedMeshに付与できるアクセサリだ。

SkinnedMeshオブジェクトからはgetMotionメソッドでモーションオブジェクトを取り出すことが出来る。

1
2
// アイドルモーション
let motionIdle = enemy.getMotion("idle");
1
2
// 攻撃モーション
let motionAttack = enemy.getMotion("attack0");

指定しているモーション名はblender上で名付けたやつだね。

blenderのAction

このモーションオブジェクトにはaddTransitionというメソッドが生えていて、他のモーションへの移行を条件とともに登録することができる。

1
2
3
// アイドルモーションにトランジションを追加。
// タップフラグが立ったら攻撃モーションへ移行する。
motionIdle.addTransition(() => tapFlag, motionAttack, 10);
1
2
3
// 攻撃モーションにトランジションを追加。
// モーションが「完了」したらアイドルモーションへ移行する。
motionAttack.addTransition("finished", motionIdle, 10);

この条件の監視やモーションの移行を司っているのがMotionControllerというわけ。

目玉としてはこのモーションのトランジションにはdurationを指定できて、モーションとモーションの間をなめらかにつなぐことが出来る。この機能には当然、みんな大好きphina.jsのTweenerを使っている。

今後どうすんだよ!

とりあえず10月くらいまでにゲームを完成させたい。

んで、出来た機能はまとめてphina.js用のプラグインとしてリリースしたいと思っている。

ソースとか

サンプルのソースはこちら