池袋晶葉ちゃんのあたまポンポンしたくて頑張った話

# 画面の向こうの池袋晶葉ちゃんのあたまをポンポンしたい

[Obniz Advent Calendar 2018](https://qiita.com/advent-calendar/2018/obniz) 16日目の記事です。

本アドベントカレンダーのお誘いを受け、さてさて何を作ったものかなーといろいろ考えて、**池袋晶葉ちゃんのあたまをポンポンすることにしました。**

二次元の女の子のあたまをポンポンして、ちょっと頬を赤らめつつ、はにかんでもらいたい。

そんな願いをかなえてくれるのが**obniz**です。
**そうなのか？**

ちなみにobnizでは過去にこんなのを作りました。

[池袋晶葉ちゃん誕生日に向けてobnizで動くウサちゃんロボを作った](https://qiita.com/youdie_/items/b7aa7c9b37b416e5e234)
[池袋晶葉ちゃんSSRが可愛いので衣装の一部をobnizで再現した](https://qiita.com/youdie_/items/a128cd285b022eb22cb0)

**え、池袋晶葉ちゃんをご存じない？**

それではぜひ**アイドルマスターシンデレラガールズ**を始めてプロデュースしてみましょう。
リズムゲームの**スターライトステージ**でもいいよ。
**ほら、わるいことはいわないから（早口）**

## やったこと

1. 絵を描く
2. 描いた絵をアニメにする
3. JavaScriptでアニメを制御する
4. obnizと赤外線センサーでなでなでする

順番に見ていきましょう。

### １．まず絵を描く
当然というかなんというか、**これが一番時間かかった。**

その苦労の一方で、この記事では特に語ることはありません（ただのお絵描きだし）
まあしいて言うならば、のちに動かすために髪の毛、目、口などのパーツを細かいレイヤーに分けて描いています。

描けた絵がこちら。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">生徒手帳の写真みたいな池袋晶葉です <a href="https://t.co/T6lSK26xfu">pic.twitter.com/T6lSK26xfu</a></p>&mdash; ud (@youdie) <a href="https://twitter.com/youdie/status/1068530254027747330?ref_src=twsrc%5Etfw">2018年11月30日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

なでなでしてもらうために正面向きです。

### ２．Live2Dでアニメーションにする
最初は**JavaScriptとCSSのいにしえパワー**でゴリゴリ動かそうかと思ったんですが、考えれば考えるほど大変そうだったので、ここは専用のソフトを使うことにしました。

近頃のVTuberブームもあってすっかり広まった**Live2D**を導入します。
![Live2D logo square.png](https://qiita-image-store.s3.amazonaws.com/0/249864/22da18d2-5263-10f0-8902-ba0a4086d68c.png)
**[Live2D](https://www.live2d.com/ja/about/whats_live2d)**とは静止画を不思議な力で3Dアニメっぽくできるソフトです。

公式のチュートリアルが大変充実しており、シンプルなUIも相まって結構簡単に絵が動かせるようになりますし、**なにより無料でかなりいろいろできます。**

実際今回の記事のために初めてインストールしたんですが、一日かからずに必要な部分は作れました。

さて、絵を描いた時点で細かめに分けたパーツは、実際これくらい分かれてました。

![texture_00.png](https://qiita-image-store.s3.amazonaws.com/0/249864/1ed4bb2c-88a6-8946-90f5-561db955dae2.png)

これらひとつずつに「目の開閉」「頬の赤らみ」「髪の揺れ」などのモーションを付けていくわけです。
そしてそのモーションたちを色々調整し、最終的に1秒ちょっとのアニメーションとして作成します。
~~あれ、obnizの記事なのにLive2Dの解説になってきたぞ。~~

![akiha_anime0.gif](https://qiita-image-store.s3.amazonaws.com/0/249864/2295769d-0047-dfff-2da0-e93643f84574.gif)

この時点でもめちゃくちゃ可愛いのでもう満足度高いんですけど、**あたまポンポン**が最終目標なのでまだまだ続きます。
**というかまだobniz使ってねえ。**

### ３．JavaScriptで動かす
上のアニメはGIFですが、これだと決まったモーションを無限ループすることしかできません。
これをJavaScriptで制御するための仕込みをします。

まずは動画素材の準備。
Live2Dさんは色々出力の形式があるのですが、今回は**連続静止画**にします。
要はアニメを一コマずつのフィルムに分けるイメージですね。

![akihagaippai.png](https://qiita-image-store.s3.amazonaws.com/0/249864/fdc2a36a-a086-e4b3-b50b-a0d6ca25e91f.png)

**池袋晶葉の群れ。**

これらをJavaScriptで高速紙芝居すればアニメーションになります。
準備が整ってきました。

まずは画像の読み込みからです。

```html:HTML
    <div id="view"></div>
```
```JavaScript:JavaScript（画像の読み込み）
    const imgPath = "./src/img/akiha_{0}.png";  //画像のパス
    const frameCount = 49;                      //画像枚数
    var loadCounter = 0;                        //ローディング画面用のカウンター

    //初期表示時に画像を全部読み込む処理
    for (let i = 0; i <= frameCount; i++) {
        var id = ('000' + i).slice( -3 );
        var img = $("<img />").attr({
            "id": id,
            "src": imgPath.replace("{0}", id)
        }).one("load",()=>{
            //loadイベントで読み込んでいる画像の数を監視
            loadCounter += 1;
            $("#count").text(Math.round(loadCounter / (frameCount + 1) * 100) + "%");
        }).appendTo("#view");
    }

    //すべての画像の読み込みが終わったらローディング画面を非表示に
    var itv = setInterval(()=>{
        if (frameCount < loadCounter) {
            clearInterval(itv);
            $("#waiting").hide();
        }
    }, 10);

```
`var`と`let`の使い分けがめちゃくちゃなのは即興で作ったやつなので許してほしい。
本当はかっこよく今時っぽいフロントのフレームワーク使いたかったんですが、いにしえのWeb技術者なので「これくらいならDOM操作でいけるべ」とゴリゴリjQueryでやってます。

んで、ここでやっていることとしては、**HTMLの初期表示時に全部の画像を読み込むこと。**
いや何を当たり前のこと言ってんだって話ですけどね、これが結構大事で。

HTMLってブラウザにもよりますけど基本的には**画像の読み込みはパラレルで行われます。**
だからパラパラアニメするにも**事前に全部の画像が読み込めていないといけない**ので、全部が読み込み終わるまで待たなくちゃいけないんですよ。

そのためjQueryのoneメソッドとloadイベントをうまいこと使って、全部の読み込みが終わるまで監視しつつloading画面的なものを表示するようにしています。

では準備ができました。
まずは晶葉を動かせるようになりたいので、`range`コントロールを使ってバーの操作でアニメできるようにしましょう。

```html:HTML（抜粋）
    <div>
        <input type="range" id="range" value="0" min="0" max="49" step="1" />
    </div>
```

```JavaScript:JavaScript（バーを動かしてアニメにする）
    var $images = $("#view").children();
    $images.hide();
    $images.eq(0).show();

    $("#range").on("input", ()=>{
        var val = $("#range").val();
        var id = ('000' + val).slice( -3 );
        $images.hide();
        $images.filter("#" + id).show();
    });
```

大したことはしていません。
`range`コントロールのバーの値を`input`イベントで監視して、値に一致する画像だけを表示しています。

実際に動かすとこんな感じです。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ふむふむ <a href="https://t.co/4eUXcR15we">pic.twitter.com/4eUXcR15we</a></p>&mdash; ud (@youdie) <a href="https://twitter.com/youdie/status/1069608631996305408?ref_src=twsrc%5Etfw">2018年12月3日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これでバーの動きに応じて晶葉を動かせるようになりました。
ゴールが近づいてきましたよ。

### ４．Obnizと赤外線センサーをつなぐ
**Obniz出てくるの遅くない？**

いや、しかしこれが結構重要なところで、obnizのコーディング量って実際めちゃくちゃ少ないんですよ。
この辺についてのポエムは後で書きます。


はい、今回の電子工作部品はこちら。
**GP2Y0A21YK0F**というシャープ製の赤外線距離センサーです。
![DSC_0061_2.JPG](https://qiita-image-store.s3.amazonaws.com/0/249864/601121c3-81a1-d5ce-37e2-7ba11f20c6ea.jpeg)



センサーからの距離がobnizを経由してリアルタイムでJavaScriptで取得できます。
部品やAPIの詳細は**[こちら](https://obniz.io/sdk/parts/GP2Y0A21YK0F/README.md?!iframe=false)**を参照。

今回はこのセンサーを使って、手との距離に応じてアニメーションを動かそうと思います。
つまり**晶葉のあたま付近（＝PCのディスプレイの上）に手をかざすことでアニメーションが動くようにする**わけです。

```javascript:JavaScript（距離センサーの組み込み）
    var obniz = new Obniz("XXX-XXXX");
    obniz.onconnect = async ()=> {
    
        var $range = $("#range");
        const buffer = 60;
        var sensor = obniz.wired("GP2Y0A21YK0F", {vcc:0, gnd:1, signal:2})
        sensor.start(async (distance)=>{

            await obniz.wait(1);
            var availableDistance = (frameCount + 1) * 2 + buffer;

            if(availableDistance < distance) {
                return;
            }

            var val = frameCount - Math.round(((distance - buffer) / 2) - 1);
            if (val < 0) val = 0;
            $range.val(val).trigger("input");

        })
    }
```
はい、これだけです。
なんかバッファとったりいろいろやってますがその辺は変化量の調整です。

obnizのAPIでは、赤外線センサーで距離の変更を検知するたびに`sensor.start()`メソッドに渡した関数が動き、その時の距離が引数として渡されます。
この値をもとに、先ほど設定した`range`コントロールを動かしてあげれば、センサーと手の距離で晶葉ちゃんが赤面してはにかんでくれます。

センサーをこんな感じでPCの裏側に貼り付けてあげれば完成です。
![DSC_0186.JPG](https://qiita-image-store.s3.amazonaws.com/0/249864/df2b2118-4418-6d6a-5a13-fb27a9380ba4.jpeg)

それではお楽しみの時間…

### なでなでする
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なんか色々やって池袋晶葉ちゃんの頭をぽんぽんできる仕組みをこしらえました <a href="https://t.co/5LzLnTcU9J">pic.twitter.com/5LzLnTcU9J</a></p>&mdash; ud (@youdie) <a href="https://twitter.com/youdie/status/1071362632014168064?ref_src=twsrc%5Etfw">2018年12月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

はー可愛い。

無限にポンポンしていたい。
**ねえ、無限にあたまポンポンしてたくなりませんか？？**

---
今回作ったものの解説は以上です。

仕組み自体は結構簡単に作れて、あとはアニメーションするのにちょうどいいセンサーの距離とか、アニメーションのフレームレートとかの調整にかかった時間がほとんどでした。

obnizで扱えるセンサーの類はまだまだいろいろあるので、こういうアニメ技術との組み合わせはいろいろ夢がありそうですよね。

何より作ってて楽しかったし自分的にも満足度の高いものが作れたので、**今後仕事に疲れた夜には晶葉をなでて癒されようと思います。**

## obnizとIoTについて思うこと（蛇足ポエム）

こっからは読み飛ばしてもらって結構。

本当は**晶葉をなでられてよかったね可愛いね**で終わろうと思ってたんですが、12日目の@KiKiKi_KiKiさんの記事を読んで、自分も電子工作初心者として思うところがあったのでちょっとつらつら書きます。
当該記事はこちら↓
**[IoT初心者がobnizと戯れてみて、"簡単に"とは何かについて考えてみたメモ。](https://chaika.hatenablog.com/entry/2018/12/12/170000)**

---

先述のコードを見てもらうとわかるように、**obnizってちょこっと書くだけで簡単にIoTできるのが本当にいいところなんですよ。**
だから自分のような門外漢でもアイディアさえ出てくればすぐに実現できるわけで。
この手軽さはJavaScriptという今最大級に技術者の多い言語がベースだからってのがもちろん第一にあります。

**でもそれ以上に大きいのが、obnizのAPIの有能さ。**

obnizのAPIを使うと、本来であれば理解するべき「どのPinがgndでvccで」みたいな、**電子工作においてはそれこそ必須であろう知識が全くいらないんですよ。**
**なんなら自分は今のところさっぱりわかっていません。**
それでもIoTって言えるものができちゃうんですよ。

先ほどの記事では、この手軽さを受けて
>一方、そこからリファレンスにないパーツを使ったりした独自の仕組みを作れるようになるステップアップの方法が"簡単"さを実現するために難しいくなっている気がします。回路的な知識を得ることができるようなコンテンツが用意されれば、よりobnizを選択する動機づけになるのではないかと感じました。

という意見を挙げられていました。

確かに、これを入り口に電子工作自体に興味を持つ人が増えて、回路的な知識をもっと学べるようになり、その方面の知識が増えていくのはいいことだと思うんですよ。
そちら方面の技術者ももっともっと盛り上がっていただきたい。

でも自分としては、obnizには**「簡単に」**の方向にガンガン舵を切ってもらいたいと思っていて。

もちろん、回路とかの知識はIoTやる上ではあってしかるべきで、学ぶこと自体とても有意義だとは思うんですよ。
でも、**目的のものを作るための学習コストは少なければ少ないほどいうのが自分の考えです。**

最終的にはobnizと電子部品のつなぎ方が標準化されて、プログラマーは全く電子工作的な知識を意識する必要なく、めちゃくちゃ手ごろなIoTが可能になってほしいとまで思っています。

昨今のOSSやらサーバーレス技術やらの一番偉いところって、Web開発におけるいろんな煩わしさをショートカットできることで、開発からローンチまでのスピードを大幅に向上させたことにありますよね。
**目的を達成するために必要な手順が少なくなることこそ、システム化の神髄と言ってもいい。**

だからIoT界隈もこういうフレームワークがどんどん成長して、開発がスピードアップすれば、敷居が下がって開発者も増えて活性化すると思うんですよね。

**「こういうのやってみたいけどIoTってWeb向けの開発と違って面倒くさそう！」**
**「CとかLinuxとか今更勉強したくない！」**
っていう人たちは絶対に多いでしょうし。
というか、まともに使える言語といえばC#/VB.NETとJavaScriptくらいしか能のない自分がまさにそうでしたから。
~~大規模案件に長期参入していると新しい言語に全然チャレンジできない業務SEの悲哀~~

とにかく思いついたらすぐにプロダクトが出せる昨今のWeb系技術の流れに、IoTも寄り添い始めてきたんじゃないかな？っていうワクワクをobnizに見たよという話でした。

・・・なーんてことを考えてたらobnizの方がインタビューでまさにそんな感じのことをおっしゃってましたね。
[ラズベリーパイより簡単にIoT電子工作ができる「obniz」が1億円を調達、コンセプトは“ハードウェアのAPI化”  |  TechCrunch Japan](https://jp.techcrunch.com/2018/11/22/cambrianrobotics-fundraising/)

以上、長々とした蛇足失礼いたしました。