twitter buttonfacebook buttongoogle plus buttonhatena bookmark buttonpocket button
ちょっと小さいのはたしかですが。
2016年12月6日

モナドのまほう 第9話『サウンドエフェクトの作業をしてコーディングで荒んだ心を癒やします』

JavaScriptWebGLゲーム制作purescriptREAPER


ゲームを作る日記です。オーディオ作業は難しい理屈とか要らなくてフィーリングだけでできるので心が癒されます。

環境音

音がないとどうも寂しいということで、森の中っぽい環境音をつけることにしました。さすがにサウンドエフェクトまで自分で録音してくるというわけにはいかなかったので、フリーの素材を探します。freesoundがいろいろな素材があっていい感じです。このなかからCreateive Commons Attribution 3.0 Unportedなライセンスのものを借りることにします。

  • https://www.freesound.org/people/HerbertBoland/sounds/28239/

説明によると初夏のイギリスのカントリーハウスで採ったものだとか。おしゃれですね。ただ、これはあくまで「素材」であって、実際にゲーム内で使うためにはいろいろと加工が必要です。この素材の場合は、一部に虫の羽音が入っていたり、トンという何かの物音(鳥追い用の銃声?)が入っていたので、これを除去します。

Reaperでファイルを再生しながらノイズを探します。「トン」というノイズがあったところの波形をみると、確かにちょっとだけ波形に山があるのがわかりました。

sound1.png

それではオペを始めます。よろしくお願いします。Item -> Split item at cursorsで該当部分に切れ目を切れます。それから患部を切除します。

sound2.png

あとはアイテムを少しずらして縫合するだけ。重なった部分はReaperが自動的にフェードイン・フェードアウトをかけて滑らかにしてくれるので簡単です。音楽だとこうはいきませんが、こういう環境音ならいくらでも誤魔化しが利きます。あとは試しに聴いてみて違和感がなければ、Item -> Glue itemsでアイテムをマージします。

これで終わりでもいいんですが、サウンドエフェクトがループする瞬間に無音になってしまうので、なるべく継ぎ目を目立たなくさせるために全体をコピペで複製して2分くらいの長さにしました。それから全体の最初と最後の部分にフェードイン・フェードアウトを効かせます。

sound4.png

本当はコンプレッサをかけて音量調節なんかもしたほうがいいですが、とりあえずはこれで問題なさそうなのでこれで。あとはMP3形式で書き出してフィニッシュ。ちょっとファイルサイズが大きいですが、そのあたりはまたいつか調整しようと思います。

babylonjsに音声再生の機能があるので、プログラミングの方も簡単です。BABYLON.SoundクラスのコンストラクタをラップしたloadSound関数を用意したので、音声を読み込むにはこれを呼ぶだけです。autoplayオプションを指定しているので、読み込みが完了したら自動的に再生が始まります。またloopオプションを指定しているので、再生が終わったら自動的にループします。しかもこの関数は非同期処理モナドAffのモナディックな作用になっていて、音声の読み込みが完了するまでゲームの開始を待機する処理が簡単に書けます。

forestSound <- loadSound "forest.mp3" "forest.mp3" scene defaultCreateSoundOptions { autoplay = true, loop = true }

実際にこの環境音を聴いてみたい人は前回出したデモをどうぞ。

一人称視点

一人称視点も実装しました。Pointer Lock APIを使って、FPSのゲームみたいにマウスで直接向きを変えながら操作できます。一人称視点は直感的ではあるんですが、キャラクターの動きを見せられないのがちょっと残念です。マインクラフトみたいに割りきって完全にストーリーを省く場合は、キャラクター性がなくてもいいとは思うのですが……。

First Person Shooterのようなゲームでの操作に慣れている人が多いので、一人称視点ではWASDで移動、マウスムーブで向きの変更という操作にせざるを得ません。その場合画面上に配置したボタンをマウスで押せなくなるので、いろんなモードの切替がちょっと不便です。その一方で、三人称視点では向きを変更しなくてもある程度自分の周囲の状況がわかるので、向きの変更がそれほど頻繁には必要なくなります。そのためマウスポインタをロックしなくても大丈夫で、マウスポインタを画面上のボタンを操作するために使えます。

また、ブロック建築ではとくに三人称のほうが便利です。一人称だと、足元のブロックの奥の面が見えにくいので、水平にブロックを継ぎ足して伸ばしていくのがやりにくいのです。操作性にもいろいろとこだわりたいです。

UIライブラリ

グラフィックは見た目はあまり変わっていませんが、プログラムの中身のほうは大幅なリファクタリングが行われています。一番大きい変化は、UIがすべてpurescript-halogenというライブラリ上へと移行したことです。今まではいきあたりばったりにFFIを呼んでDOMを動かしていたんですが、今後ユーザインターフェイスが複雑化するのを見込んですべて書き換えました。

ゲーム向けという特殊な利用に耐えられるのか心配でしたが、なんとかなりそうです。UIの状態が変更されるとDOMの再描画が走ってしまうので、ゲーム向けでは毎フレームDOMの再描画が起きてしまいかねないので効率に問題がありそうな気がしていたんですが、UIの状態とリアルタイムで変化する状態を分離することでうまくいきそうです。UIの状態は基本的にクリックなどのユーザ入力のときだけ変更されるようになっています。

輪郭線

キャラクターに輪郭線を表示してみました。背面法という古典的な方法を使っています。少しキャラクターの印象が引き締まるのはいいのですが、このゲームではいまのところカメラが引いている場面が多いので、それほど印象が変わるわけではないように思いました。輪郭線なしでも見栄えは問題ない気がします。たしかにアニメっぽくはあるのですが、アニメの再現を目指しているわけでもないですし。どんどんモデルが重くなっていく……。

outline.png

あと、Blenderでモデルを作ってbabylonjsに書き出したい人は、以下のTipsは必ず読んでおいたほうがいいと思います。知らないとモデルの表示が崩れてハマります。要するに、ひとつの頂点は最大4つのボーンからの影響しか受けられないのですが、それを超える頂点があったとしても警告が出るだけで書き出しが成功したように見えます。でもボーンを動かすとウェイトが足りないのでぐにゃっとモデルが崩れます。もうこれ警告じゃなくてエラーでいいと思うんですけどね。

https://doc.babylonjs.com/exporters/Blender_Tips

今後の(ずさんな)計画

  • まずはコードをリファクタリングしまくる(めんどくさい)
  • 自動化されたテストが欲しいです(ぶっちゃけ最優先で必要だけと、いい方法が思いつかない)
  • 自由に走ったり飛んだりできすぎるので、キャラクターのコリジョンをどうにかしたいです。現時点では物理エンジンを使わずに自前で実装する構え
  • 現状のキャラクターモーションは不自然すぎるので調整したい。あと「立ち」と「走り」だけじゃ不自然なので、「ジャンプ」と「着地」くらいは欲しいです (いつでも着手できるので優先順位低)
  • babylonのバグで上手く動かないので、水面マテリアルの移植 (優先順位低)
  • 現状では無限に動きまわれる&無限に掘れる&無限に積めるなので『ゲーム』にはなっていないです。せめて周囲の探索→素材集め→建築の流れができるようにしたいです。それができれば最低限『ゲーム』の体裁がつきます
  • それができたらFirebaseに統合してマルチプレイヤー化。ひとりだとゲーム内でたくさんの課題を与えないと飽きやすいですが、他のプレイヤーの気配があると飽きにくいので
  • シングルプレイモードとマルチプレイモードを用意したい(願望)

次のお話