Nintendo Lab のフォロアーになるべくゲームを作ってみた

## ハード + ソフト
![screenshot-title.png](https://raw.githubusercontent.com/noolbar/my-blog-paperdoctor/master/res/screenshot-title.png)

ゲームの面白さは画像の美麗さで決まるわけではないはず。ということで今回はダンボールゲームを作っていこうと思います.

github repository
<https://github.com/noolbar/my-blog-paperdoctor>

## これからのゲームは

任天堂からNintendo Labというダンボールを使ったゲームが発表されました。限られた中で想像を働かせて遊ぶのに必要なものなんてないなっと改めて気付かされます。昔は広場に四角を書くだけで、ゴールにも刑務所にも見立てていつまでも遊んでいられました。

Nintendo LabにはGarageというユーザが自由にプログラムすることのできる機能が含まれています。しかし、これはかなり機能が制限されており、メーカが用意したソフトと並ぶものは作ることができません.

こうした制限を受けず、自由に作っていきたいので`Obniz`を中心にダンボールで外側を作っていきます｡
ダンボールで作成するということで、プラスチックでは制作ができないある程度大きなサイズのものを作っていきたいです。また、PCやタブレットと連動して遊べるものがいいです。映像だけでなく音やネット環境など表現の広がりが出てきます。

## なに作ろう
私は子供の頃に歯医者へ行くのが好きでした.泣き叫ぶ子供の声が好きなわけでもなければ美人の歯科助手がいるからでもなく、ドリルや吸引器などが並んだあの椅子が選ばれし者しか座ることの許されない特別な場所に見えたからでした。そんな動機から、歯医者のセットを作っていくことにします。

記憶を頼りに方針を決めていきます。

- 患者をタブレットに表示させて、治療を行う
- ハードウェアでドリル、吸引器、型採りなどできるだけ再現
- 歯を照らすライトを傾けるとタブレットの画面と連動して、照明が変化
- ライトを取り付けた動くアームと器具を置いておく動くテーブルはダンボールで再現
- かわいいの助手キャラクターを設定

## 歯医者とは
歯の治療のことを何もわからないので、調べてみます。
まずは歯科の専門器具について

- ドリル : 医者の世界ではタービンと呼びます.バーと呼ばれる先端がいくつかある
- デンタルミラー : 口の中に入れる小さい鏡.見えにくいところを見る
- ピンセット : 小さいものをつかむ
- プローブ: 虫歯の部位や深さなどの診査に使用
- エキスカベーター : 小さいスプーン.虫歯の除去などに使用
- 充填器 : 充填物を詰めたり除去するヘラ
- バキューム : 唾液や水を吸取る
- 注射器 : 麻酔をおこなうために使用
- 歯ブラシ : 歯のクリーニングに使用
- レントゲン : 見えない虫歯を見つける

器具を使って何をするかもわからないので調べます

- 抜歯で歯を抜く。いたい
- 消毒で感染症などを防ぐ
- 詰め物のため歯型をとる
- 咬み合わせをとる
- 詰め物を歯にセットする
- 神経をとる
- 歯石をとる
- 歯茎のケア

そのまま表現すると量が多く痛々しいのでデフォルメと実現難易度を踏まえて、ゲームに採用していきましょう。聴診器などは歯医者では使わないですが、イヤホンなどで表現できると面白いと思います。

## ハードウェア
歯医者コントローラは以下のようになっています｡

![tools-whole.jpg](https://raw.githubusercontent.com/noolbar/my-blog-paperdoctor/master/res/tools-whole.jpg)

- 器具
    - ドリルやデンタルミラーなど
- トレー
    - ユーザが使用する器具をおいておく台
- ライト
    - 超音波センサで床との距離を計測


トレーについては、使用中の器具をタッチパネルで認識できるようにしており、ユーザが操作する際に最も使用するものです。
ダンボールそのままではタッチパネルで反応しませんが､アルミホイルを画面と自分に接触するように貼り付けてやると反応します｡

トレーには、現在ユーザがどの器具を使っているかわかるように工夫があります。磁石で器具とトレーを電気的に接続させており、器具にはそれぞれユニークな抵抗値をもっています。

![tool-joint](https://raw.githubusercontent.com/noolbar/my-blog-paperdoctor/master/res/tool-joint2.jpg)

小さく安いネオジム磁石
[amazon.co.jp](https://www.amazon.co.jp/%E3%83%8D%E3%82%AA%E3%82%B8%E3%82%A6%E3%83%A0-%EF%BC%91%E5%80%8B%E3%81%A7A4%E3%82%B3%E3%83%94%E3%83%BC%E7%94%A8%E7%B4%99%EF%BC%93%E6%9E%9A-%E3%82%AA%E3%83%9E%E3%82%B1N35%CF%863x1mm10%E5%80%8B-N35%CF%863x2mm5%E5%80%8B-%E5%85%A8%E3%82%B5%E3%82%A4%E3%82%BA%E7%B7%8F%E9%A1%8D%E6%9C%80%E5%AE%89%E9%80%81%E6%96%99100%E5%86%86/dp/B0752XN6GM/ref=sr_1_17?s=office-products&ie=UTF8&qid=1527088973&sr=1-17&keywords=%E3%83%8D%E3%82%AA%E3%82%B8%E3%83%A0%E7%A3%81%E7%9F%B3)

2つの道具を同時に使わないことを条件に抵抗値をポーリングで確認することで、どの器具が使用中であるのか判別しています｡
ObnizにはA/D変換がどのpinからも使用できますが､MPUを使う場合には､以下のようなモジュールを使用するとよいかと思います｡

ＭＣＰ３４２５（１６Ｂｉｔ　ＡＤＣ　Ｉ２Ｃ　基準電圧内蔵）搭載モジュール
<http://akizukidenshi.com/catalog/g/gK-08018/>

Ｉ２Ｃは少ないピンで使用できるので､便利なインターフェイスです。Raspberry Piでも使用することができます｡

Raspberry Piの I2C機能を有効化する方法、最新の Raspbian Stretch対応 2018年版
<http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_enable_i2c_2018_raspbian_stretch/>

今回は分圧した値を読み取り、1つのA/D変換値から5つのツールのうちどれを使用しているか確認していますが、数が増えそうであればＩ／Ｏエキスパンダーを使ってioピンを拡張してやると足りないピンを補うことができます｡

１６ｂｉｔ　Ｉ２Ｃ　Ｉ／Ｏエキスパンダー　ＭＣＰ２３０１７
<http://akizukidenshi.com/catalog/g/gI-09486/>

それぞれの器具にユニークな値が設定してあるのでトレーのどの位置に器具を戻しても間違いなく、何を使用しているのか認識できるようになっています。ただし、接続抵抗が値に影響しないように設計時に意識する必要があります｡トレーはどの位置に戻してもいいように接続部分が共通になっています｡

ライトは、ライトスタンドのように首を好きな位置に動かせるようになっています｡仕組みは、筒状のダンボールの中に細番線が入っており針金の力で固定しています。
超音波センサが先端のカゴに取り付けられており､ここで距離を測っています｡センサが傾くと距離が変化してしまうため､カゴは2軸ジンバルになっており地面に対して常にセンサが水平になるようになっています｡
![arm1](https://raw.githubusercontent.com/noolbar/my-blog-paperdoctor/master/res/arm1.jpg)
![arm2](https://raw.githubusercontent.com/noolbar/my-blog-paperdoctor/master/res/arm2.jpg)

all-hc-sr04 Ultrasonic Distance Sensor Module Set A Few More The Price Is More Cheap. For Arduino
[amazon.co.jp](https://www.amazon.co.jp/gp/product/B004U8TOE6/ref=oh_aui_detailpage_o09_s00?ie=UTF8&psc=1)

下の部分は吸盤で平らな面につくようになっています｡先端のカゴは逆さまにしても大丈夫です。
今回は見送りましたが、ライトの先端に傾きを検知するために加速度センサーも良いと思います｡

３軸加速度センサモジュール　ＡＤＸＬ３４５（ＳＰＩ／Ｉ2Ｃ）
<http://akizukidenshi.com/catalog/g/gM-06724/>
使い方
<http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_i2c_accelerometer_adxl345/>

## Asset
制作の大変な3dモデルや音楽、SEなどは、以下のサイトから使用させていただきました。
- Detailed Human Skull (Wip) 3d model <https://free3d.com/3d-model/accurate-human-skull-wip-35571.html>
- 星宝転生ジュエルセイバー <http://www.jewel-s.jp/download/>
- Empty box <https://poly.google.com/view/86_1dd-Z27K>
- 魔王魂 <https://maoudamashii.jokersounds.com/>
- NoCopyrightSounds <https://www.youtube.com/channel/UC_aEa8K-EOJ3D6gOs7HcyNg>
- くらげ工匠<http://www.kurage-kosho.info/system.html>

## かわいいキャラクター
ゲームの顔になる部分ですので，とても重要な要素です.私は絵心がないので他の方作成されている作品をしようしたいのですが、3Dモデルやイラストの界隈ではライセンスに対してあまりしっかりしたものが無いようです。`フリー`と検索してみても再配布禁止や商業利用禁止となっているもの、許可の範囲が不明なもの、そもそもライセンスがないものなど昔のフリーウェアソフトのような状況です。

Unityは、アセットにはGUIDが振り当てられており(<http://tsubakit1.hateblo.jp/entry/20140201/1391238348>)プロジェクトを壊すことなく特定のアセットを除いてオープンソース化できる仕組みがありますが、Unityのアセットストアは品質を保つため、クリエータが自由にアップできる状況ではなく、Unity以外での使用はできないことも問題です.新しいゲームエディタが雨後の竹の子のように出ていますが、ここら辺の問題を解決できる仕組みがあるといいなと思います。

今回はキャラクタージェネレータでキャラクタを作成します。

キャラクターなんとか機
<http://khmix.sakura.ne.jp/>

みなさん｢うにゅう｣というソフトをご存知でしょうが、かなり前に流行った(?)デスクトップに常駐してPC上のインテリアとして無駄な情報を表示してくれるキャラクターなのですが、上記のソフトはそのGhostを作成するものとして使われているものです。今であれば、Goolge Assistantsと連動したりして、いろいろできそうです。(むしろそれらの元祖ともいえます)

`キャラクターなんとか機`はパーツの差し替えができるため、自作のカスタムを公開されている作者様がいらっしゃいます。以下のサイトでは雰囲気にあうかわいい女の子が自動生成出来ます.「キャラクターなんとか機」用パーツセット「少女セット」 (●**R-18** ●性的・猟奇的な表現のあるパーツを含みます。)
<http://seizonkakuninbasyo.web.fc2.com/>
[Pixiv 作者様](https://www.pixiv.net/member_illust.php?mode=medium&illust_id=63391966)


こんな感じのキャラクターを作ることができます｡
![heroin_sekkyou.png](https://raw.githubusercontent.com/noolbar/my-blog-paperdoctor/master/res/heroin_sekkyou.png)


## Unityを使った画面づくり
ハードウェアと平行でゲームを作る必要がある場合デバック用のUIを作りそのUIを使いソフトウェアを作り込んで行きます。
今回は、ハードウェアがなくてもゲームができるように、デバック用のUIをそのまま表示させています｡

ゲーム作成ではUnityを使用した例が多く存在しており、Webからいろいろなノウハウを得ることができます｡画面づくりはコードよりも実行画面を見ながらできると良いので､Unityを使用することにしました。
しかし､UnityからHTMLで実行できる形式に出力するには、コードに複数の変換を繰返して生成されるため何が出力されているのか全くわかりませんでした。

コードをきれいな形で実行できるようにしたいと探していると`Babylon Tool Kit`でUnityからBabylon.jsをベースにしたモジュールを出力する方法が紹介されていました。
<https://www.crossroad-tech.com/entry/Babylonjs_Unity3>
<https://github.com/BabylonJS/Exporters.git>
<https://github.com/flushpot1125/BabylonJS_UnityExportSample>

メリット

- 位置関係やマテリアルの把握がすぐできる
- 3dをコードで扱う際の煩わしさが軽減される

デメリットとしてはUnity自体も含めて結構頻繁にバージョンアップしてるので、追従が難しいかもしれません。

また、Toolkit自体の使い方になれないといけません。今回の例で言えば、カメラの縦横の比率を固定する方法がよくわからなかったので､16:9のタブレットで全画面表示した場合に良い感じに表示されるようにします｡スクリプトでいろいろな画面サイズに対応しようとすると文字の大きさなども考えないといけないため妥協します。(フリーゲームなどでは全画面表示オンリーだったりしますし)

出力できるものには限りがあり､以下のURLに箇条書されています｡ここにないので、Unityに標準で搭載されている`Particle System`は出力できないようです。
<https://doc.babylonjs.com/resources/intro>

その代わりに`Custom Script Components`というコンポーネントによって、表示させることができるので今回使用しています｡

アニメーションをUnityで作成して操作をすることができます｡
<https://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons>

Babylon.jsの使い方については､ここのUnityのタグにまとまっています｡
<https://doc.babylonjs.com/resources/>
<https://www.babylontoolkit.com/>

どんな関数が用意されているかについては、ドキュメントが整備されておりサンプルを参照できます｡
<https://doc.babylonjs.com/api/globals>



# 問題
toolkitはTypeScriptで記述されたスクリプトをUnityのC#のスクリプトのように使用できるのですが､私の環境ではエラーが発生してうまく動作しませんでした。
変換はプロジェクト全体がシーンごとにJson形式で出力されるため、コードはtoolkitから出力された`Export`フォルダの中にある`Index.html`を書き換えてUnityの管理下にないjsファイルを読み込んでいます｡

また、UnityのuGUIは、Toolkitでは出力できないので､UIに関してはUnityの機能をそのまま使うことは期待できません。
UIは表示するだけしておけば良いものもとそうでないものに分けて、表示だけのものはUnityで配置しています。

![gamascene-ui](https://raw.githubusercontent.com/noolbar/my-blog-paperdoctor/master/res/gamascene-ui.png)

表示だけのアクセサリ的なものであっても画面がゲームっぽくなります｡それでもまだ寂しい感じがしますが､どうしたら良いのかわからないので取り合えず切り上げました｡

# コード
コードの書き方は、一本道のストーリをテキスト形式で書いてから、コードに落とし込んでいます｡
今回のようなゲームに限らず私がコードを書くときは、わからない部分があっても全体を通して書いて、その後動くように修正していきます｡

イテレータにGameControllerの役割をもたせて、ユーザのアクションに合わせてストーリを表示させていきます｡
イテレータの実装はここが参考になりました。
<https://qiita.com/townewgokgok/items/925b7024ff6dd204c770>

ノベル部分は大体イメージ通りに行きましたが、ゲームパートではやりたいことを追加していくとかなりごちゃごちゃとなってしまいました。TypeScript周りの設定がうまく行けばUnityでスクリプトの管理ができるのでわかりやすくなると思います｡

# まとめ
単純なアイディアであっても、実装までに多くの時間がかかるとやる気が完成まで持たずに、半端なところで飽きが来てしまいます｡
短期で達成する事のできるゴールを設定してやることで､ゲームを作ることをゲーム感覚で進めることができます｡

今回使用したUnity、Obniz、BABYLON.jsなどのアイディアを具現化する道具はたくさんありますので､みなさんもチャレンジして見てください。