グリグリリック 開発秘話

2020年12月8日(火) 4時30分37秒 | 159 view |

TL;DR

マジカルミライプログラミングコンテストで拙作「グリグリリック」が入選しました。本記事ではグリグリリックの作り方についてブレイクダウンして解説していきたいと思います。

マジカルミライプログラミングコンテストとは

このブログでも何回か取り扱っていますが、マジカルミライ2020に合わせてクリプトンと産総研で共同開催されたマジカルミライ初のプログラミングコンテストです。



TextAliveApp APIというこのコンテストに合わせて公開されたAPIを活用して、歌詞を音楽に合わせて表示するアプリケーション”リリックアプリ”を開発し、表現力を競うプログラミングコンテストです。
投稿形式はWebフロントエンドで動くアプリケーション限定。以下の審査基準をもとに応募作品31作品から入選作10作品が選ばれました。

クリエイティビティ
Webアプリケーションの演出が楽曲と同期して魅力的に見えるか
イノベーション
Webアプリケーションを支えるアイデアがユニークで、未来の創作文化を予感させるものであるか
完成度
Webアプリケーションが一般的なWebブラウザで正常に動作するか、実装が技術的に優れているか

成果物

グリグリリックという3D弾幕アプリケーションを作りました


今すぐプレイ:
https://magicalmirai.com/2020/procon/entry/entry09
ソースコードも公開しています:


「マジカルミライ2020大阪」内ステージで紹介されました


グリグリリックができるまで

技術要素

WebフロントエンドはWebGLで、フレームワークはPlayCanvasを利用しています。


PlayCanvas

Web向けの3Dゲームエンジンです。
JavaScriptで動作するゲームエンジンとそれを簡単に扱えるWebエディターがセットになっています。
物理エンジンやフォントレンダリングなども機能として入っているので今回はすべてPlayCanvasべったりで開発しています。
また、マルチプラットフォームなアプリが作れる前提のエンジンなのですが、今回のコンテストでは結構評価ポイントでマルチプラットフォームな点が評価されたのは、完全にPlayCanvasのおかげです。

設計

シーン一つで構築しています


マウスやタッチでのカメラ移動は公式のmodel viewer starterkitをそのまま転用しています
https://playcanvas.com/project/446385/overview/starter-kit-model-viewer

3Dでの演出を考える際に、まず過去に作ったwarawaraという作品をイメージして実装を開始しました

https://playcanvas.utautattaro.com/warawara/

この動きを歌詞に合わせて動かし、終息と発散を繰り返して画面が構築されていくような仕組みで作ることにしました。

TextAliveApp APIの読み込み

公式機能のEXTERNAL SCRIPTSで実現しています

透過キャンバスにして背景にDOM表示

ますTextAliveApp APIではデフォルトでスモールウィンドウで連携されたYouTube動画が挿入される仕様になっています。
今回はPVに合わせた画作りをするため、背景すべてに広げ、リリックオブジェクト以外はPlayCanvasのcanvasを透過させるような仕組みにしました。
PlayCanvasの透過キャンバス作成は以下の方法で簡単にできます



デフォルトではiframeで挿入されるYouTube動画のサイズが小さいためスクリプトのイニシャライズで以下のCSSを挿入します

let sty = document.createElement("style");
sty.innerHTML = "iframe {position:absolute} #application-canvas {z-index:1000;}";
document.body.appendChild(sty);


歌詞の描画

歌詞はPlayCanvasのelement componentでシンプルに実装しています

ワールドの重力は0,0,0となっており、それぞれの歌詞は球体の当たり判定を持ち、通常時は座標中央(0,0,0),サビの時にはカメラに寄っていくような動きをスクリプトで加えています。

var pos = this.entity.getPosition();
var vec;
if(sabi){
    vec = this.app.root.findByName("Camera").getLocalPosition().clone().scale(0.5);
}else{
    vec = new pc.Vec3(0-pos.x*2,0-pos.y*2,0-pos.z*2);
}
    
if(this.entity.rigidbody){
     this.entity.rigidbody.applyForce(vec);
}


また、歌詞はビルボード表示されており、常にカメラを見続けるような処理にしています

Lookatfor.prototype.update = function(dt) {
    this.entity.lookAt(this.app.root.findByName("Camera").getPosition());
};

もう少しやりたかったこと

・テンポに合わせてもう少し動きをつけたかった
ビートに合わせて歌詞が波打ったり、盛り上がり・盛り下がりを検出して何か表現できたらやりたかったです。
TextAliveAppAPIではきっとそういった要素も取れるかと思うのですが、いかんせん自分の音楽関連知識が不足していて専門用語がよくわからず断念しました。
・画作りしたかった
自分は絵も3Dも作れないプログラマーなので、今回はPVの上にコンテンツを乗せる形で実装しました。次回はなにか画作りからできるような形で作りたいです
・インタラクティブ性をもっと出したかった
せっかく動画じゃなくてアプリケーションなので、だれが実行しても同じ結果になるアプリは作りたくないなあと思っていました。物理エンジンは決定性がないので、放置していてもランダムのようにふるまうのですが、今回は自由カメラ視点によってさらにインタラクティブ性が出せた気がしたのですが、最後までやりたいと思えるようなレベルまでは今一つだったかなと思います。ゲーム要素とか入っている他作品を見て、やられた!と思いました。

まとめ・感想

ということでありがたいことにマジカルミライ プログラミングコンテストで入選しました。
今回評価されたインタラクティブ性やマルチプラットフォームで問題なく動く完成度はPlayCanvasの力がとても大きいです。
リリックアプリの開発は初挑戦でしたが、動画作品も案外作れるなあという印象でした。ただ見るだけの動画と体験可能なアプリで大きく表現力が変わるはずなので、アプリにしかできない表現を探すのは楽しそうだなと思いました。
次回あればぜひまた参加したいです。