LoginSignup
82
41

More than 3 years have passed since last update.

GoでStar Wars

Last updated at Posted at 2019-02-01

こんにちわ
ゴリラです。

先日、Twitter上でこちらのツイートを見かけました。

さすがmattnさん。
ただちょっと残念なのが、これVimのプラグインなのでVimでしか使えないです。

ないものは作るしかない。
というわけでこれのGo版を作りました。
Goならクロスコンパイルができるので、どこの環境でもバイナリ一つで動くしいつでも見れて良いなと。

作ったもの

go-starwars.gif

リポジトリこちらです。

この画像は @po3rin さんが作ったこちらのツールを使わせていただきました。
めっちゃ良いので、ぜひ使ってみてください。

QiitaだとURLはそのままでは使用できないので、画像をコピーしてURLだけ変えて貼り付けてみてください。

<a href="https://github.com/skanehira/go-starwars"><img src="https://qiita-image-store.s3.amazonaws.com/0/66178/0ef750bc-03ed-1eb8-2b3b-cfdb9801f3b9.png" width="460px"></a>

使い方

READMEを読んでください。
Dockerがある方は

docker run --rm -it skanehira/go-starwars

で実行できます。

仕組み

テキストファイルを読み込んで出力しているだけです。

使用ライブラリ

  • packr
    テキストをバイナリに埋め込むことができます。
    よく記事で見かけるgo-bindataというのがありますが、
    こちらはもうメンテされていないので、新たなにpackrを使うことにしました。
    使い方はREADMEを見ていただければと思いますが、バイナリをビルドするときはpackr buildするだけです。
    シンプルでわかりやすいですね。
  • go-colorable
    画面クリアにエスケープシーケンスを使用していますが、Windowsの場合はそれを使用できないそうです。
    そこでmattnさんが作成されたライブラリを使用することで、windowsでも画面クリアできるようにしました。
    さすがmattnさん。

処理の流れ

sw1.txtの中身が単なるテキストで、それをfor分で読み取って出力しているだけです。
45や30というのは待ち時間になっていて、それを除いた13行の内容が1フレームになります。

45


  Original Work: Simon Jansen ( http://www.asciimation.co.nz/ )   
  Inspiration  : Martin W. Kirst
                 https://github.com/nitram509/ascii-telnet-server 
  Httpification: Martin Raison
                 https://twitter.com/braizh

  The hard work was done by Simon,                                
  I just wrote the http player                                  
  and placed it online using Simon's movie sources.               


30




                       WWW.ASCIIMATION.CO.NZ


                             presents





1行ずつ読み込んでいて時間の行はstringをintにパースして結合した文字を出力し、
指定された時間を待ってから画面クリア&値初期化をします。
それ以外は文字列を結合するだけです。
めっちゃシンプルです。

scanner := bufio.NewScanner(file)
for scanner.Scan() {
    if i%height == 0 {
        // get duration from text line
        duration, err = strconv.Atoi(scanner.Text())
        if err != nil {
            continue
        }

        // print buffered line
        fmt.Println(buffer)

        time.Sleep(time.Duration((*speed)*duration) * time.Millisecond)

        // clear terminal screen, init buffer and duration
        clear()
        buffer = ""
        duration = 0
    } else {
        // text line into buffer
        buffer += fmt.Sprintln(scanner.Text())
    }
    i++
}

画面クリア処理について 

func clear() {
    // https://www.grapecity.com/developer/support/powernews/column/clang/047/page02.htm
    fmt.Fprint(stdOut, "\x1b[2J")
    fmt.Fprint(stdOut, "\x1b[0;0H")
    stdOut.Flush()
}

エスケープシーケンスを使用すると画面をクリアできます。
\x1b[2Jは画面をクリアしますが、カーソルはそのままなので、カーソルの一を左上に戻さないと行けないです。
\x1b[0;0Hはカーソルを座標0,0に戻します。
これを合わせることで画面をクリアすることが実現できました。

最後

ネタですが、こういうの作るのって楽しいですよね。
エンジニアは勉強する必要はないと思っていて、大事なのは自分がワクワク楽しみつつ知見と経験を深めることを見つけることなので、
これからも楽しんでいきますっ

82
41
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
82
41