(´･ω･`)ショボーンが降ってくるコマンドをGo言語で作ってみました⊂二二二（　＾ω＾）二⊃ 

(´･ω･`)ショボーンが降ってくるコマンドをGo言語で作ってみました。スクリーンショットはこちら。

```bash
shobon
```

![Screenshot from 2017-09-17 23-45-33.png](https://qiita-image-store.s3.amazonaws.com/0/140543/8c1669db-396b-8666-76e9-5f3b55abe424.png)

アスキーアートで拡大されたしょぼんくんが画面を上から下へと降りてきます。スクショだけではわかりませんが、ただ降りるだけです。`--reverse`オプションを指定すればゆっくりと上がっていきます。

これをベースになんかいろいろオプションを作ったので紹介していきます。ソースコードは[github.com/aimof/shobon](https://github.com/aimof/shobon)こちら。`go install`でインストールできるよ！

ちなみに__技術的に高度なことは一切やっていません__。エスケープシーケンスくらいです。

## 基本コマンド`shobon`

上のスクショのようにしょぼんくんがゆっくり降りてきます。この部分のコードは以下。

```go
func printDefaultShobon(height, width int) {
	var x int = 0
	if width > kaomoji.SHOBON_WIDTH {
		x = (width - kaomoji.SHOBON_WIDTH) / 2
	}
	if height < 8 {
		printShobon(x, 0, 8)
	} else {
		for i := 0; i < height-kaomoji.SHOBON_HEIGHT-1; i++ {
			if *reverseOption {
				printShobon(x, height-kaomoji.SHOBON_HEIGHT-i-2, height)
			} else {
				printShobon(x, i, height)
			}
			time.Sleep(150 * time.Millisecond)
		}
	}
}

func printShobon(x, y, height int) {
	var indent string = strings.Repeat(" ", x)
	fmt.Print("\x1b[1J")
	fmt.Print("\x1b[1;1H")
	fmt.Print(strings.Repeat("\n", y))

	fmt.Print(indent + kaomoji.SHOBON0 + "\n")
	fmt.Print(indent + kaomoji.SHOBON1 + "\n")
	fmt.Print(indent + kaomoji.SHOBON2 + "\n")
	fmt.Print(indent + kaomoji.SHOBON3 + "\n")
	fmt.Print(indent + kaomoji.SHOBON4 + "\n")
	fmt.Print(indent + kaomoji.SHOBON5 + "\n")
	fmt.Print(indent + kaomoji.SHOBON6 + "\n")
	fmt.Print(indent + kaomoji.SHOBON7 + "\n")
	fmt.Print(strings.Repeat("\n", height-y-kaomoji.SHOBON_HEIGHT-1))
}
```

最初のうちはこんなノリだったのですが楽しくなってきたので、ちょっとふざけたオプションを用意しました。

## しょぼんくんがたくさん降ってくるオプション`shobon --many`

![Screenshot from 2017-09-17 23-45-42.png](https://qiita-image-store.s3.amazonaws.com/0/140543/43beffc9-042c-21fa-31e1-475dee4e2f89.png)


![Screenshot from 2017-09-17 23-45-47.png](https://qiita-image-store.s3.amazonaws.com/0/140543/eff2431d-e39f-9738-0338-3d525a98f1fb.png)

一行に一人しょぼんくんが降りてきます。

これだけではなんかしょうもないのでしょぼんくんがうじゃうじゃおりてくる`shobon --too-many`オプションを用意しました。

![Screenshot from 2017-09-17 23-47-35.png](https://qiita-image-store.s3.amazonaws.com/0/140543/5b1552e2-afa5-0db1-50cb-6cab73e7114d.png)

実装はだいぶ汚いです。気になったらリポジトリで確認してみてください。ちなみにこちらにも`--reverse`オプションを用意しました。

![Screenshot from 2017-09-18 00-10-49.png](https://qiita-image-store.s3.amazonaws.com/0/140543/cc5e685a-bc56-6694-8807-7a131eb916e4.png)

登っていきます。

## しょぼんくんがジャンプするコマンド`shobon --jump`

静止画では通常コマンドと同じなので写真は省略。

```go
func printJumpingShobon(height, width int) {
	if height < 2*kaomoji.SHOBON_HEIGHT {
		fmt.Println("sorry, your terminal is too small to jump.")
		return
	}
	var x int = 0
	if width > kaomoji.SHOBON_WIDTH {
		x = (width - kaomoji.SHOBON_WIDTH) / 2
	}
	if height < 8 {
		printShobon(x, 0, 8)
	} else {
		for jump := 0; jump < 10; jump++ {
			highest := float64(height - kaomoji.SHOBON_HEIGHT)
			for i := height - kaomoji.SHOBON_HEIGHT - 1; i >= 0; i-- {
				var shobonHeight float64 = float64(height - kaomoji.SHOBON_HEIGHT - i)
				printShobon(x, i, height)
				time.Sleep(time.Duration(math.Pow((shobonHeight-highest/2)/(highest/2), 2) * float64(40*time.Millisecond)))
			}
			for i := 0; i < height-kaomoji.SHOBON_HEIGHT-1; i++ {
				var shobonHeight float64 = float64(height - kaomoji.SHOBON_HEIGHT - i)
				printShobon(x, i, height)
				time.Sleep(time.Duration(math.Pow((shobonHeight-highest/2)/(highest/2), 2) * float64(40*time.Millisecond)))
			}
		}
	}
}
```

しょぼんくんがそれっぽくジャンプします。ジャンプしているっぽく関数を選ぶのが大変でした。durationを正規化した二次関数の二乗で表現したのですが、こんなんでよいのかな？ もっといい関数があるかもしれないけど物理わからない……

## ⊂二二二（　＾ω＾）二⊃ `shobon --booon`

最後にブーンが降ってくるコマンドを用意しました。

![Screenshot from 2017-09-17 23-46-50.png](https://qiita-image-store.s3.amazonaws.com/0/140543/e583300d-c297-cd32-6ea8-41940ef8f2eb.png)

普通に打つとブーンが画面真ん中を飛びます。左から右に。

当然こちらにも`--many`オプションがあり、

![Screenshot from 2017-09-17 23-47-16.png](https://qiita-image-store.s3.amazonaws.com/0/140543/08cb1ecb-47c6-a89c-6631-a908332319d6.png)

ちょっと増えます。

これだけで物足りなかったら、もちろん`--too-many`コマンドもあります。

![Screenshot from 2017-09-17 23-47-54.png](https://qiita-image-store.s3.amazonaws.com/0/140543/7468fb88-df40-81b5-6e36-0c13a6a71016.png)

いっぱい飛びます。

## まとめ

一発ネタコマンド楽しい！

## 使った技術

エスケープシーケンス

```go
fmt.Print("\x1b[2J")   // 画面全クリア
fmt.Print("\x1b[1;1H") // 左上（1,1）に移動
```