Noodlでカウントダウンタイマのゲームを作る

#概要

 Noodl Adent Calender 20日目！
クリスマスまであと５日、待ち遠しいですね。
そして気づいたら年越し。皆さんは年越しカウントダウンに参加しますか？
今年はこの「Noodlカウントダウンタイマ」を利用して年越するのはいかがでしょうか。

と、前置きはさておき、Noodlでカウントダウンタイマを作りました。
ただのカウントダウンタイマではつまらないため、パスワード認証で解除する機能も付けてみました。

#デモ
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ちらっ（パート２） <a href="https://t.co/yfAvETrwM6">pic.twitter.com/yfAvETrwM6</a></p>&mdash; まえぷー@アウトプット復活！！ (@kmaepu) <a href="https://twitter.com/kmaepu/status/1207298237578665984?ref_src=twsrc%5Etfw">December 18, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

　画面をタップするとカウントダウンが始まり、正しいパスワードを入力できれば停止します。
　背景を点滅させることでユーザが焦るように仕向けています。

#仕組み
###カウントダウンタイマ
　主に次の5つの処理を行っています。

- RootのGroupノードをタップすると無限タイマー（Periaod generation）が起動　
- 1秒間隔でPeriod generationコンポーネントからTriggerが発される
- javascriptノード”Counter”でダウンカウント
- javascriptノード”Format”で値が1桁になったら10の位に0を詰めたテキストデータにする
- String Formatノードで表示する文字形式にする

　カウントダウンタイマのフローはこのとおりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/4b41539a-afdf-74fd-2a9d-cc631a534fa9.png)

　javascriptノード”Counter”の中身は次のようになっています。ざっくりコードの説明をすると、Triggerが入るとダウンカウント可能か判定し、可能ならばダウンカウントします。ダウンカウントするとマイナスになる場合にキャリーを発生させています。

```javascript
define({
    inputs: {
        set_timer_H: "number",
        set_timer_L: "number",
        max_timer_H: "number",
        max_timer_L: "number",
        trigger:"number"
    },
    outputs: {
        s: "string",
        ms:"string",
        uf:"boolean"
    },
    destroy: function(inputs, outputs) {

    },
    setup: function(inputs, outputs) {
        outputs.ms = inputs.set_timer_L;
        outputs.s = inputs.set_timer_H;
        outputs.uf = false;     
        var carry_ms = false;
        var carry_s = false;
        
    },
    run: function(inputs, outputs, changedInputs) {
        if(outputs.uf === true){
            return 0;
        }
        if(inputs.trigger === true){
            if(outputs.ms === 0){
                carry_ms = true;
                outputs.ms = inputs.max_timer_L;
            }else{
                carry_ms = false;
                outputs.ms--;
            }
            if(carry_ms === true){
                if(outputs.s === 0){
                    carry_s = true;
                }else{
                    carry_s = false;
                    outputs.s--;
                }
            }
        }    
        if(carry_s === true && carry_ms === true){
            outputs.uf = true;       
        }
    }
});
```
　カウントする時間は次のようにプロパティで設定できます。
この例では1分に設定しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/a6972958-60d3-29c3-5c00-8cca1b355c1e.png)

　javascriptノード”Format”の中身は次のようになっています。
入力された値が10未満の場合、10の位に0を付け加えてテキストデータとして出力します。

```javascript
define({
    inputs: {
        num: "number"
    },
    outputs: {
        text: "string"
    },
    destroy: function(inputs, outputs) {

    },
    setup: function(inputs, outputs) {

    },
    run: function(inputs, outputs, changedInputs) {
        if(inputs.num < 10){
            outputs.text = "0" + inputs.num;
        }else{
            oututs.text = "" + inputs.num;
        }
    }
});
```

###パスワード認証
　主に次の4つの処理を行っています。

- Text Inputノードで文字列入力
- Imageノード”arrow.png”で右矢印を表示し、タップすると認証開始
- javascriptノードで入力された文字列と正解パスワードを比較
- 正解していたらstateプロパティにfalseを出力する

　フローはこのようになっています。javascriptノードのstateは画面の点滅状態とカウントダウンタイマの停止に利用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/02d8f1b1-b711-8dd8-3ce7-416c861adff4.png)

　Text Inputノードはその名の通り文字入力を受け付けるノードです。
このノードのプロパティにある**Type**をpasswordにすると、入力中の文字列を隠してくれます。
　今回は入力ミスを起こさせるために使っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/42342b2c-e7cd-2e2a-58c9-c09e92378e69.png)

　javascriptノードの中身は次のようになっています。パスワードの正解パターンをソースコードに埋め込んでいるので、解析されるとばれてしまいますね。

```javascript
define({
    inputs: {
        pass: "string",
        trig:"boolean",
    },
    outputs: {
        state: "boolean",
        text:"string",
    },
    destroy: function(inputs, outputs) {

    },
    setup: function(inputs, outputs) {

    },
    run: function(inputs, outputs, changedInputs) {
        if(inputs.trig === true){
            if(inputs.pass === "Noodl"){
                outputs.state = true;
            }  else{
                outputs.state = false;
            } 
        }else{
            outputs.state = false;
        } 
        outputs.text = inputs.pass;
    }
});
```

#おわりに
　Noodlでちょっとしたゲーム感覚なUIを作ってみました。
このUIを作るためにjavascriptのコーディングだけでなく、無限タイマーや文字列入力の使い方を学ぶことができたので良かったです。

　プログラミングって、いきなりコードを書くところから入ると何してるか理解しづらいですよね。Noodlのようにビジュアルプログラミングから入ると、結果を理解した上でコードを書くのでプログラミングに入門しやすいのではないでしょうか。