Go言語でゲーム開発


Go言語はよくサーバー開発で使われていますが、ゲーム制作でもGoが使えますよ！

## engi

今回紹介するライブラリーは「engi」です。

https://github.com/ajhager/engi

2Dゲームエンジンです。ちょっとXNA的な感じ。"SUPER ALPHA"なので、APIがよく変わりますが、とりあえず、engiのロゴを表示するdemos/hello.goを見てみましょう。

### engiの使い方

#### インポート

まずインポートします。ライブラリーではなく実行できるプログラムなので`package main`になります。

```go
package main

import (
	"github.com/ajhager/engi"
)
```

engiが使っているウインドを表示してくれる`azul3d.org/native/glfw.v4`というライブラリーは`go get`すると、自動的にGLFWをインストールするから、`go get`だけで大丈夫です。

#### ゲームオブジェクトを定義

engiは`engi.Game`という形に対して`Update()`や`Render()`を呼んでくれるので、`*engi.Game`を組み込めばいいです。

```go
type Game struct {
	*engi.Game
	bot   engi.Drawable
	batch *engi.Batch
	font  *engi.Font
}
```

`bot`はengiのロゴのスプライトです。`batch`はスプライトをrenderする際に使うSpriteBatch的な物です。`font`はテキストを表示するためのテクスチャーなどが入っている物です。

#### スプライトなどを読み込む

Gameの`Preload()`が一番最初に呼ばれるメッソドです。定義するとスプライトとかを読み込めます。

```go
func (game *Game) Preload() {
	engi.Files.Add("bot", "data/icon.png")
	engi.Files.Add("font", "data/font.png")
	game.batch = engi.NewBatch(engi.Width(), engi.Height())
}
```

#### スプライトなどを用意する

`Preload()`が終わってウインドが作られたら、`Setup()`が呼ばれます。ここで`Preload()`で読み込まれたファイルを使います。

```go
func (game *Game) Setup() {
	engi.SetBg(0x2d3739) // 背景の色
	game.bot = engi.Files.Image("bot")
	game.font = engi.NewGridFont(engi.Files.Image("font"), 20, 20)
}
```

#### 表示する

いよいよ`Draw()`です。engiが勝手に呼んでくれるので表示ループとか書かなくてもOKです。

```go
func (game *Game) Render() {
	game.batch.Begin()
	game.font.Print(game.batch, "ENGI", 475, 200, 0xffffff) // "ENGI"を表示
	game.batch.Draw(game.bot, 512, 320, 0.5, 0.5, 10, 10, 0, 0xffffff, 1) // ロゴを表示
	game.batch.End()
}
```

#### 最後にmain()

`package main`にするならmain関数が必要です。`engi.Open()`を使います。

```go
func main() {
    //      タイトル, height, width, fullscreen, Gameオブジェクト
	engi.Open("Hello", 1024, 640, false, &Game{})
}
```

#### こうなります…

![Screen Shot 2014-12-22 at 4.20.57 PM.png](https://qiita-image-store.s3.amazonaws.com/0/52098/8ea14e2f-29c1-6b2b-dca1-cda664f9796d.png "Screen Shot 2014-12-22 at 4.20.57 PM.png")

### 双方向にしよう

キーボードでロゴを動かせるようにしましょう。Gameのロゴのx, y変数を追加します。そしてこれから使うkeyMapを定義。

```go
type Game struct {
	*engi.Game
	bot   engi.Drawable
	batch *engi.Batch
	font  *engi.Font

	botX, botY float32
	keyMap     map[engi.Key]bool
}
```
`Preload()`にkeyMapのmakeとデフォルト配置を入れます。

```go
func (game *Game) Preload() {
	...
	game.keyMap = make(map[engi.Key]bool)
	game.botX, game.botY = 512, 320
}
```

`Render()`をbotX, botYを見るようにします。

```go
func (game *Game) Render() {
	...
	game.batch.Draw(game.bot, game.botX, game.botY, 0.5, 0.5, 10, 10, 0, 0xffffff, 1)
	...
}
```


Gameの`Key()`メッソドを定義すれば、キーボードイベントを対応できます。

```go
func (game *Game) Key(key engi.Key, modifier engi.Modifier, action engi.Action) {
	switch action {
	case engi.PRESS:
		game.keyMap[key] = true
	case engi.RELEASE:
		game.keyMap[key] = false
	}
}
```

そして`Update()`メッソドで、keyMapに応じてロゴの配置を変えます。

```go
func (game *Game) Update(dt float32) {
	// dt = 時間差 (0.01635106とか）
	var dx, dy float32
	if game.keyMap[engi.ArrowUp] { // trueなら押されている
		dy = -500
	}
	if game.keyMap[engi.ArrowDown] {
		dy = 500
	}
	if game.keyMap[engi.ArrowLeft] {
		dx = -500
	}
	if game.keyMap[engi.ArrowRight] {
		dx = 500
	}
	dx, dy = dx*dt, dy*dt // 適当に時間差に応じて動かす
	game.botX += dx
	game.botY += dy
}
```

よし。これでアローキーを使って動かせます！

## 最後に

Go言語のゲームの世界はこれから広がります！ぜひGo言語でゲームを作りましょう。engiはgopherjs対応しているので、javascriptにもコンパイルできますよ！