突然Go言語に興味が出てきたので学習しながらいろいろやってみます.
よってプロから見るとダメダメなコードを書いている可能性が大です.悪しからず.
そもそもGo言語とは
Googleが開発したコンパイルするタイプの言語(≠スクリプト言語)です.
文法はめっちゃシンプル.並列処理に強くて高速らしい.
ビルドして実行するときはコンソールで
go run hoge.go
と叩く.
文法
「パッケージ」というものを最初に宣言する.必ずmainパッケージがある必要がある.
プログラムはmainパッケージの中のmain関数から実行される.
変数
varで宣言できる.string, int, float64, bool, nilのデータ型がある.
宣言方法はいろいろ.そして1文字目に
1 文字目が小文字の場合はそのパッケージだけで見える変数(private)で,
大文字の場合は他のパッケージからも見える変数(public).
var hoge int var hoge2 = 2 // 型名は省略可能 hoge3 := 3 // varも省略可能 var a, b int // 同時に定義して a, b = 1, 100 // 同時に代入 var ( x = 123 y = "hogey" ) // 複数を同時に // 配列 var arr [5]int arr := [3]int{1, 3, 6}
「スライス」という便利機能があるらしい.
定数
constで定義する.
const { hoge = 1 hoge2 = 2 }
関数
func hogehoge()
で宣言.引数と戻り値の方は絶対指定しなければならない.
package main import "fmt" func hoge () { fmt.Println("Hello, world!") } func hoge2 (text string) { fmt.Println(text) } func hoge3 (i int) int { return i*i } // 複数の戻り値を与えられる func hoge4(a int, b int) (int, int) { return b, a }
繰り返し・条件分岐
繰り返しはfor文オンリー.while的に使うことも可能.
for i := 0; i < 5; i++ { if i == 0 { // hoge } else if i == 4 { // hogehoge break } } // while的 n := 0 for n < 5 { // hoge n++ }
GolangでOpenGL
さてGo言語で画面描画をしようとするとやっぱりOpenGL.
Go用のものは以下です.
github.com
Goではコマンドからサクッとパッケージをインストールできます.( 楽! )
go-glの最新版だといろいろ変わっているので,2,1にしました(甘え)
$ go get -u github.com/go-gl/gl/v2.1/gl $ go get -u github.com/go-gl/glfw/v3.2/glfw
今回はglfwもいっしょにインストール.
円を描画
package main import "github.com/go-gl/gl/v2.1/gl" import "github.com/go-gl/glfw/v3.2/glfw" import "log" import "math" import "runtime" func init() { runtime.LockOSThread() } func main() { windowWidth := 640 //!< 横幅 windowHeight := 640 //!< 縦幅 // glfwを初期化 if err := glfw.Init(); err != nil { log.Fatalln("[Error] Failed to initialize glfw:", err) } defer glfw.Terminate() // main関数が閉じられるときに呼び出される // Windowを作る glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 1) window, err := glfw.CreateWindow(windowWidth, windowHeight, "GL Test", nil, nil) if err != nil { panic(err) // 強制的に終了 } window.MakeContextCurrent() // GLの初期化 if err := gl.Init(); err != nil { panic(err) // 強制的に終了 } for !window.ShouldClose() { // ウィンドウを閉じるまで繰り返す gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) r := 0.5 //!< 半径 n := 100 //!< 円の分割数 // 円を描く gl.Begin(gl.POLYGON) gl.Color4f(0.2, 0.3, 0.7, 1.0) // 円の色(RGBA) // 円を描画 for i := 0; i < n; i++ { x := r * math.Cos(2.0 * 3.14 * (float64(i)/float64(n))) y := r * math.Sin(2.0 * 3.14 * (float64(i)/float64(n))) gl.Vertex3f(float32(x), float32(y), 0.0) // 頂点座標 } gl.End(); gl.Flush(); window.SwapBuffers() glfw.PollEvents() } }
実行結果:
やったね!描画できたよ!!
ライフゲームを作る
ライフゲーム (Conway’s Game of Life[1]) は1970年にイギリスの数学者ジョン・ホートン・コンウェイ (John Horton Conway) が考案した生命の誕生、進化、淘汰などのプロセスを簡易的なモデルで再現したシミュレーションゲームである。
ライフゲーム – Wikipedia
- 誕生 – 死んでいるセルに隣接する生きたセルがちょうど3つあれば、次の世代が誕生する。
- 生存 – 生きているセルに隣接する生きたセルが2つか3つならば、次の世代でも生存する。
- 過疎 – 生きているセルに隣接する生きたセルが1つ以下ならば、過疎により死滅する。
- 過密 – 生きているセルに隣接する生きたセルが4つ以上ならば、過密により死滅する。
package main import "github.com/go-gl/gl/v2.1/gl" import "github.com/go-gl/glfw/v3.2/glfw" import "log" //import "math" import "runtime" var windowWidth = 1305 //!< 横幅 var windowHeight = 1305 //!< 縦幅 var n = 32 //!< セルサイズ var cells [32][32]int //!< セルの配列 var prevCells [32][32]int //!< 前ステップのセルの配列 var count = 0 //!< フレームカウント func init() { runtime.LockOSThread() for i := 0; i < n; i++ { for j := 0; j < n; j++ { cells[i][j] = 0 prevCells[i][j] = 0 } } //penta(10,15) //penta(5,5) //glider(25,20) hansyoku(15,15) } func penta(x int, y int) { cells[x][y] = 1 cells[x+3][y] = 1 cells[x+5][y] = 1 cells[x+6][y] = 1 cells[x+8][y] = 1 cells[x+11][y] = 1 cells[x][y+1] = 1 cells[x+1][y+1] = 1 cells[x+2][y+1] = 1 cells[x+3][y+1] = 1 cells[x+5][y+1] = 1 cells[x+6][y+1] = 1 cells[x+8][y+1] = 1 cells[x+9][y+1] = 1 cells[x+10][y+1] = 1 cells[x+11][y+1] = 1 cells[x][y+2] = 1 cells[x+3][y+2] = 1 cells[x+5][y+2] = 1 cells[x+6][y+2] = 1 cells[x+8][y+2] = 1 cells[x+11][y+2] = 1 } func glider(x int, y int) { cells[x][y] = 1 cells[x][y+1] = 1 cells[x][y+2] = 1 cells[x+1][y] = 1 cells[x+2][y+1] = 1 } func hansyoku(x int, y int) { cells[x][y] = 1 cells[x+1][y] = 1 cells[x+2][y] = 1 cells[x+4][y] = 1 cells[x][y+1] = 1 cells[x+3][y+2] = 1 cells[x+4][y+2] = 1 cells[x+1][y+3] = 1 cells[x+2][y+3] = 1 cells[x+4][y+3] = 1 cells[x][y+4] = 1 cells[x+2][y+4] = 1 cells[x+4][y+4] = 1 } func display() { prevCells = cells for i := 0; i < n; i++ { for j := 0; j < n; j++ { // セルをカウント num := 0 if i-1>=0 && j-1>=0 {num += prevCells[i-1][j-1]} if j-1>=0 {num += prevCells[i][j-1]} if i+1<n && j-1>=0 {num += prevCells[i+1][j-1]} if i-1>=0 {num += prevCells[i-1][j]} if i+1<n {num += prevCells[i+1][j]} if i-1>=0 && j+1<n {num += prevCells[i-1][j+1]} if j+1<n {num += prevCells[i][j+1]} if i+1<n && j+1<n {num += prevCells[i+1][j+1]} // セルを設定 if num <=1 { cells[i][j] = 0 } else if num <= 2 { if prevCells[i][j] == 1 { cells[i][j] = 1 } else { cells[i][j] = 0 } } else if num == 3 { cells[i][j] = 1 } else { cells[i][j] = 0 } // 色を設定 if cells[i][j] == 1{ gl.Color4f(0.2, 0.3, 0.7, 1.0) } else { gl.Color4f(0.1, 0.1, 0.1, 1.0) } gl.PushMatrix() gl.Translatef(float32(i)*float32(windowWidth/n), float32(j)*float32(windowHeight/n), 0.0) rect(10.0) gl.PopMatrix() } } gl.Flush(); count = count + 1 } func rect(ext float32) { gl.Begin(gl.POLYGON) gl.Vertex3f(-float32(ext), float32(ext), 0.0) gl.Vertex3f(float32(ext), float32(ext), 0.0) gl.Vertex3f(float32(ext), -float32(ext), 0.0) gl.Vertex3f(-float32(ext), -float32(ext), 0.0) gl.End() } func main() { // glfwを初期化 if err := glfw.Init(); err != nil { log.Fatalln("[Error] Failed to initialize glfw:", err) } defer glfw.Terminate() // main関数が閉じられるときに呼び出される // Windowを作る glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 1) window, err := glfw.CreateWindow(windowWidth, windowHeight, "Life Game", nil, nil) if err != nil { panic(err) // 強制的に終了 } window.MakeContextCurrent() // GLの初期化 if err := gl.Init(); err != nil { panic(err) // 強制的に終了 } // 座標変換 (画面幅*画面幅の座標にする) gl.Scalef(2.0/float32(windowWidth), 2.0/float32(windowHeight), 1.0) gl.Translatef(-float32(windowWidth)/2.0 + 25.0, -float32(windowHeight)/2.0 + 25.0, 0.0) // タイマーのセッティング fps, currentTime, lastTime, elapsedTime := 4.0, 0.0, 0.0, 0.0 glfw.SetTime(0.0) // メインループ for !window.ShouldClose() { // ウィンドウを閉じるまで繰り返す // タイマー currentTime = glfw.GetTime() elapsedTime = currentTime - lastTime if(elapsedTime >= 1.0/fps){ gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) display() window.SwapBuffers() glfw.PollEvents() lastTime = glfw.GetTime() } } }