saino.me

都内でひっそりと生きる IT エンジニアの個人ブログです

Go 言語の練習を兼ねて SDL2 でライフゲームを作ってみました。

作ろうと思った動機

www.saino.me

上記エントリで CHIP-8 のエミュレータを作ろうと思っていて、ディスプレイを擬似的に用意しようと思ったときに「GUI でドットを表現する」ということを基礎として学びたかったというのが1つ。

また、Go のチュートリアルは一通りやってみましたが、やはり何か「やってる感」があるプログラムを採用したかったためです。

SDL2 自体も色々とできて、なかなか面白そうだったので、グラフィック周りのハンドリングも学べるということで、一石二鳥ということでやってみました。

たぶん普通は CUI プログラムを書いて、画面を逐一クリアしてターミナルに逐一表示するほうが簡単だと思いますが、そこはロマンということで ...

作ったもののデモ

こちらは初期位置をランダムに配置したバージョンです。マスをクリックすることで、強制的にマスを「生きている状態」にすることができます。

f:id:kaishuu0123:20200213113332g:plain
ランダムバージョン

また配置をソースコードで記述してあげることで、こういった規則的なアニメーションができます。プログラムでこういった記述ができるなんて、かっこいいです( *ˊᵕˋ ) ⁾⁾

f:id:kaishuu0123:20200213113637g:plain
Cross バージョン

ソースコード

github.com

作り切るまでの過程

せっかく作ったので、足跡を残すために「どのように順を追って勉強をしたか」という点を残しておこうと思います。

1. Go について学ぶ

こちらは、有名すぎる「A Tour of Go」を一通りなぞりました。

go-tour-jp.appspot.com

2. Go の開発環境について学ぶ

私が Go を始めたころは Go Modules というものがなかった頃の話なので、アップデートがてら、Go Modules を使った開発環境を調べました。下記サイトでは goenv を利用していますが、私は brew で Go 1.12.5 を導入しました。

rightcode.co.jp

3. グラフィックライブラリの選定

ここは散々迷いました。もともとグラフィックライブラリには精通していないので、「OpenGL というものがあったり、Windows では DirectX ってのがあるな ...」程度にしか理解していません。

なので、記事先頭で引用した記事内で SDL2 を利用しているということを脳死で採用し、 SDL2 を使うことにしました。GLUT や GLFW などもありますが、Go の binding では pixel というものもあるようです。

github.com

なかなか奥が深いです。ライブラリの棲み分けのブロック図とかないのかな、これ。

というわけで SDL2 を採用することを決めたので、Go の SDL2 binding である下記のveandco/go-sdl2 というライブラリを利用することにしました。

github.com

4. SDL2 の使い方を学ぶ

SDL2 を使うことにしたので、早速「ウインドウの表示」と「ピクセル単位での描画」を学んでいきます。

ここでは、「SDL には Window, Renderer, Texture」というものがあるんだな、というざっくりとした理解をして、「Texture に特定のデータの配列を渡して、Texture のデータを Renderer にコピーすればそれっぽいものを描画するんだな」ということを理解しておきます。

上記のソースでは sdl2canvas という自分が定義したパッケージに pixels という配列を持たせて、そこに R8G8B8A8 形式でデータを持たせて、それを Texture に渡すことでピクセル単位の描画を行っています。

github.com

5. ライフゲームのルールを把握して実装する

SDL2 とはまったく関係なく、ライフゲームのルールを作り込んでいきます。

github.com

ライフゲームでは、フィールドがあり、ステップを進めるたびに特定のルールで次々とフィールド上で生死を繰り返していきます。

ここでは、「現在のフィールド(Current)」と「現在のフィールドを元に生死判定を行ったあとのフィールド(Next)」の2つのフィールドを持っておきます。生死判定が終わったあとに「現在のフィールド」にコピーします。

ちなみに生死判定はいろいろなルールがあるそうですね。

ja.wikipedia.org

ちなみに正式名称は「Conway's Game of Life」と言うそうで、ボードゲームと名前がかぶるから「Conway's」という名前が先頭についているようです。

ja.wikipedia.org

6. ライフゲームのフィールドを SDL2 で作ったウインドウに反映する

私が書いたコードの該当箇所はこちら

ライフゲームが持っている配列から、SDL2 Texture に反映する pixels という配列に反映します。

ここでは、ウインドウの横幅 -> 縦幅の順で for 文を回し、特定の範囲ごとに色を塗り分けています。

これで完成です⸜( ´ ꒳ ` )⸝

まとめ

SDL2 を使ってウィンドウを表示して、ドット絵っぽいような画面を描画して、そこにライフゲームのロジックを組み込むということができました。

これで、何らかのエミュレータを描くこともできるようになったかなと思います。

CHIP-8 エミュレータ書くぞー

ライフゲームに関する蛇足

ライフゲーム自体も奥が深く、専用の wiki があり、パターンファイルというものまで決まっているそうです。

www.conwaylife.com

RTE というファイルフォーマットがあり、このファイルにはルールやドットパターンなどが記述されています。このファイルを読み込んで、描画することで特定のアニメーションを再生できる、という仕組みですね。

ここまで対応できると、すでに先人が見つけたパターンを試すことができるので、これはこれでまた1つ面白いトピックだと思います。(今回は RTE ファイルの読み込みまではやっていません)