諸君!!A-Frameで簡易ホラーVRを作ろうではないか!!(多分その1)


オッサンは懐が寒くても呑むんですよ。
じゃないと凍え死んじゃうの(笑)

これからプログラミング的な投稿をしていくうえで考えたこととして、中途半端な僕なんかがプロフェッショナルにかなうわけがない、というのがありました。
しっかりした人がしっかりした知識でしっかり書いた投稿、それに勝るものを作らないと投稿する意味なんてないと思ったんです。
だったらどうするか?

もう「邪道」に走るしかないな、と!

……というわけで今後は軽口を交えながら、技術そのものについて説明することよりも、技術を拝借して実用したことを中心に投稿していくことにします。
Google検索して同じようなネタが20個以上乱立するようなものは作りたくはないですしね。

というわけで前置きが長くなっちゃいましたが、今回はHTMLタグだけでVR空間をブラウザ上に作れちゃうA-FRAME、そんな便利技術でちょっとお化け屋敷的なVR空間作っちまおうZE☆、ってな話です。

恐怖もののVRコンテンツ、今流行ってますね。
デパートの最上階で特設されていたりしますね。(2017年2月現在)
そんな流行コンテンツをもしかしたらお手製で、ブラウザでお気軽にできるんじゃね?って話をします。

そのために、「A-Frame」というイケイケなフレームワークを使います。

A-Frameとはなんぞ?

正体はThree.jsというWebGLを扱うJavaScriptライブラリを梱包して、HTMLのタグだけで3D空間、しかもVRに特化したインターフェースも用意してくれる気の利いたアンチクショウです。(Three.jsとかWebGLとかは各自で調べてください)
本来ならばJavaScriptでぐりぐりプログラミングして3Dグラフィックを書くものなのですが、「aframe.js」をHTML内で読み込みA-Frame専用タグを設置するだけで3D空間のリアルタイム描画できちゃうんですよ。
ヤバイっすよ、タモさん。
たとえシンプルなものしかできないとしても(これから先はまだ未知数)、「3DでVR作ってやったぜ★」という感動を簡単に味わえるのって素晴らしいことだと僕は思っています。

A-Frameホームページ(サンプルが12個も。ゲームもあります)
A-Frameドキュメント(「aframe.js」をどうするかはこちらを参考にしてください)

※全部英語ですけどなんとかなります。学生はむしろ今から英語になれるチャンスだ!!むしろやっておけ!!

前準備

  • テキストエディタ(ご時世的にUTF-8は使えた方がいい)
  • HTML5が動くブラウザ(ただしiPhoneのSafariは推奨できない)
  • aframe.js(僕はA-FrameのドキュメントからDLしてきました)
  • 画像(暗黒工房さんから戴いてきました)
  • 音声(ザ・マッチメイカァズさんから戴いてきたのと、自分で録った音声も使ってます)
  • PCとスマホ(どっちでも試せた方がいい)

でさ、どんなのを作るのん?

もう既に最小限までできているので、そいつを見てもらいましょう。
リンク:In the dark
QRコード:

PCブラウザでもスマホブラウザでも視聴可能です。
PCではマウスドラッグで視点変換、WASDで移動できます。
スマホは移動はできませんが、スマホの向きや角度を変えることで視点を変えられます。
またカードボードボタンを押すことで立体視モードに変更、カードボードなどで立体視を楽しめます。

※カードボード(ハコスコ)

起動すると目の前に既に変なのがいますね。
ヒグラシの鳴き声が耳に気持ちいいですが、かすかに気持ち悪い笑い声が聞こえます。(まあ僕の声なんですがw)

上を見上げれば月。(板ポリに画像貼っただけなんで雑です……すみません)

後ろに、何かいる。

何かいた。

立体視モード(Android、Chromeの場合)

こんなのが100行もない1枚のHTMLファイルでできているんですよ。
ちょっと試したいだけなら、十分すぎる仕様ではないですか。

HTMLコード

※説明にいらないものは実際のコードから削ってあります

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>In the dark.</title>
<meta name="description" content="In the dark.">
<meta name="apple-mobile-web-app-capable" content="yes">
<script src="./js/aframe.js"></script>
</head>
<body>
<a-scene>
    <!-- ここでロード時にファイルを読み込んでおく(※1) -->
    <a-assets timeout="15000">
        <img id="moon" src="img/mika11.gif">
        <img id="candle" src="img/rouc03ani2.gif">
        <img id="bigface" src="img/bigface08.jpg">
        <img id="bone" src="img/braineat02.jpg">
        <!-- 
        <audio id="loopsound0" src="sound/laughing.mp3" preload="auto">
        <audio id="loopsound1" src="sound/higurashi.mp3" preload="auto">
         -->
    </a-assets>

    <!-- 空の色。真っ暗。セグメントは細かすぎると処理落ちしますよー -->
    <a-sky color="#040404" segments-width="16" segments-height="4"></a-sky>

    <!-- 月を配置。板ポリに三日月の絵を貼っただけです -->
    <a-image id="moon" rotation="0 0 0" width="5" height="5" src="#moon" color="#FFF" position="0 12 -8">
        <a-mouseenter color="#900"></a-mouseenter>
        <a-mouseleave color="#FFF"></a-mouseleave>
    </a-image>

    <!-- うしろにいるやつ -->
    <a-image rotation="-10 0 0" width="3" height="3" src="#bigface" position="0 2 1">
    </a-image>

    <!-- 骸骨、彼から笑い声を出すようにしました(※2) -->
    <a-image rotation="0 0 0" width="4" height="4" src="#bone" 
        sound="src:sound/laughing.mp3; loop:true; autoplay:true" position="0 1 -25"></a-image>
    <!-- 
    <a-image rotation="0 0 0" width="4" height="4" src="#bone" sound="src:#loopsound0;" position="0 1 -25"></a-image>
    -->

    <!-- 蝋燭、たくさん立てました。これも板ポリに画像を貼っただけ -->
    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="-4 1 -10"></a-image>
    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="4 1 -10"></a-image>

    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="-4 1 10"></a-image>
    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="4 1 10"></a-image>

    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="8 1 -6"></a-image>
    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="-8 1 -6"></a-image>

    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="8 1 6"></a-image>
    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="-8 1 6"></a-image>

    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="12 1 2"></a-image>
    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="-12 1 2"></a-image>

    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="12 1 -2"></a-image>
    <a-image rotation="0 0 0" width="0.2" height="0.4" src="#candle" position="-12 1 -2"></a-image>

    <!-- カメラ。wasd-controls-enabledはキーボードで移動させたいときにtrueに -->
    <a-camera wasd-controls-enabled="true" position="0 1.8 0">
        <a-cursor color="#2E3A87"><!-- カーソルはカメラのタグ内に。 -->
        <!-- ひぐらしの音声データ、両サイドから。片方をコメントアウトするとおもしろいよ(※3) -->
        <a-entity id="sound_self00" geometry="primitive: plane" material="color: blue;opacity:0"
          position="-25 5 2" sound="src:sound/higurashi.mp3; loop:true; autoplay:true"></a-entity>
        <a-entity id="sound_self01" geometry="primitive: plane" material="color: blue;opacity:0"
          position="20 7 1" sound="src:sound/higurashi.mp3; loop:true; autoplay:true"></a-entity>
        <!-- 
        <a-entity id="sound_self00" geometry="primitive: plane" material="color: blue;opacity:0" position="-25 5 2" sound="src:#loopsound1;"></a-entity>
        <a-entity id="sound_self01" geometry="primitive: plane" material="color: blue;opacity:0" position="20 7 1" sound="src:#loopsound1;"></a-entity>
        -->
    </a-camera>
</a-scene>
</body>
</html>

詳細な説明は端折りましたが、本当にこれだけしかやってません。
あとは同じディレクトリにjs,image,soundの3つのディレクトリを用意して、aframe.jsと画像と音声ファイルをおいたくらい。
ちょっとVR制作をためしたいくらいなら、これくらい簡単だと助かりますよね?

気になってる点

音声ファイルの事前ロードと再生

上記のHTMLコードの※1,2,3でコメントアウトした箇所3点、

『音声ファイルを!!ページロード時に読み込み!!それを!!アイドリング中に!!ループで!!鳴らし続ける!!覇ァッッッ!!』

……というつもりだったのですが、なぜか鳴らないんですよねー、これがー。
使い方をおそらく間違ってるんですが、これは今度の投稿のネタかなあ。

iPhone/iPod Safariでは音が鳴らない

残念ながら音が再生されません。
これ、本当になんとかしたい。
Safari自体、Live2Dをブラウザで動かしたり、音声合成や音声入力のときも動かなかったことがありましたが、Apple製品はブラウザ技術の自由を制限しすぎている感があります。
自由過ぎることがセキュリティホールになる可能性は確かに否定できないんですがね。
HTML5が騒がれだしたときに、HTMLを標準化という錦の旗がありましたが、あれはいったいなんだったのか。

カメラと光源と3Dオブジェクト、インタラクティブ性

カメラと光源をもっとじっくりいじれば、もっと楽しいことができそうです。
また今回は板ポリゴンに画像を貼っただけですが、MMDのモデルとかつかえたらもっと楽しいでしょう。
Three.jsでそうしている方がいるので、Three.js経由でできないことはないのかな?
それと、インタラクティブ性!
これがないとつまらない!
お化けが出たり消えたりとか、目が合った瞬間に変身したりこっちに迫ってきたりとか。
そこまでくるとJavaScript様の出番なのですが、そのうちいずれやりましょう。

とりあえず中途半端ですが、今回はここまでー。