Goだけで
モバイルアプリを
作ろう
2015/10/11(日)
@Goオールスターズ!
The Go gopher was designed by Renee French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0
Attributions license.
アジェンダ
● 自己紹介
● Go Mobileとは?
● どうやって作るのか?
● イベント
● spriteパッケージ
● その他できること
● Google Playに公開するまでの道のり
自己紹介
KLab株式会社
KLabGames事業本部 エンジニア
上田拓也
twitter: @tenntenn
■ 好きな言語
Go, JavaScript, Lua
■ 業務
モバイルオンラインゲームの開発(クライアントサイド)
Go Mobileとは?
https://github.com/golang/mobile
Goとクロスコンパイル
■ $GOOSと$GOARCHを指定する
$ GOOS=linux GOARCH=arm go build main.go
■ Android上で実行
$ adb push main /data/local/tmp
$ adb shell
$ run-as pkgname
$ cat /data/local/tmp/main > main
$ chmod 766 main
findやgrepが使えない時に便利
Go Mobileとは
● Goでモバイルアプリを作るツール群
○ iOS / Androidに対応
○ golang.org/x/mobile
● 2通りのスタイル
○ Goだけで書く
⇒ OpenGL を使う
○ 一部だけ書く
⇒ Java, Obj-c/Swiftから
参考:https://github.com/golang/go/wiki/Mobile
Goだけでモバイルアプリを作ってみた
http://github.com/tenntenn/gofun
どうやって作るの?
gomobileコマンド
■ gomobile init
● ツールチェインのインストールや初期化を行う
● 最初の1回だけ実行すればよい
■ gomobile build
● ビルドを行う
● apk(Android)やapp(iOS)の生成を行う
■ gomobile install
● gomobile build後にadb installまで行う
● Android限定
PCで動かす場合は
go buildで行う
Go Mobileのパッケージ
■ glパッケージ
● golang.org/x/mobile/gl
● OpenGL ES で頑張る
■ eventパッケージ
● golang.org/x/mobile/event/touch
● golang.org/x/mobile/event/paint
● golang.org/x/mobile/event/lifecycle など
■ spriteパッケージ
● golang.org/x/mobile/exp/sprite
● 2次元のシーングラフ
イベントループとspriteパッケージ
参考:サンプルコード
イベントループとspriteパッケージ
参考:サンプルコード
app.Main
■ イベントループを行う関数
func main() {
app.Main(func(a app.App) {
// イベントループを書く
})
}
イベントループ
■ app.App.Events()からイベントを取得
// Events() <-chan interface{}
for e := range a.Events() {
switch e := a.Filter(e).(type) {
case lifecycle.Event:
// ...
case paint.Event:
// ...
}
}
spriteパッケージ
■ sprite.Engine
● 描画エンジンを表すインタフェース
● 具体的な実装は別のパッケージに任せる
sprite/glsprite, sprite/portable
■ sprite.Node
● シーングラフのノードを表す構造体
■ sprite.Texture
● テクスチャを表すインタフェース
■ sprite.SubTex
● テクスチャの一部を表す構造体
● ノードに設定される
テクスチャ
サブテクスチャ
イベントループとspriteパッケージ
参考:サンプルコード
テクスチャのロード
■ アセットのオープン
a, err := asset.Open("gopher.png")
■ 画像のデコード
img, err := image.Decode(a)
■ テクスチャのロード
t, err := eng.LoadTexture(img)
assetsディレクトリ以下の
ファイルを見に行く
イベントループとspriteパッケージ
参考:サンプルコード
シーングラフの構築
■ ノードの作成と登録
■ 子ノードの追加
scene := &sprite.Node{}
eng.Register(scene)
n := &sprite.Node{}
eng.Register(n)
scene.AppendChild(n)
サブテクスチャの作成と設定
■ サブテクスチャの作成
st := sprite.Subtex {
T:t, // テクスチャ
R:iamge.Rect(0, 0, 100, 200)
}
■ サブテクスチャの設定
eng.SetSubTex(n, st)
テクスチャ上の該当の領域
を指定する
アフィン変換行列の設定
■ アフィン変換行列の設定
ルートノードは、サイズ:1pt x 1pt、
座標:(0,0)、角度:0に対して変換行列を掛け合わせる
eng.SetTransform(root, f32.Affine{
{2, 0, 5},
{0, 2, 5},
})
1pt = 1/72 inch
アフィン変換行列の計算
■ 親ノードから子ノードへ
親ノードの変換結果に子ノードの変換行列を
掛けわせて子ノードの描画位置を決める
root
n
eng.SetTransform(root, f32.Affine{
{2, 0, 5},
{0, 2, 5},
})
eng.SetTransform(n, f32.Affine{
{100, 0, 10},
{0, 100, 10},
})
2x2, (5, 5)
200x200, (25, 25)
イベントループとspriteパッケージ
参考:サンプルコード
ノードの配置
■ Node.Arranger.Arrange
● 毎フレーム呼ばれる
● ノードの位置を変更したりする
type Arranger interface{
Arrange(e Engine, n *Node, t clock.Time)
}
シーングラフの描画
■ Engine.Render
シーングラフを描画する
現在の時刻と、画面サイズ(size.Event)が必要
// 60FPS
now := clock.Time(
time.Since(st)*60/time.Second)
// szはsize.Event
eng.Render(root, now, sz)
実行例
その他できること
■ touch.Event
● タッチイベント
■ sensor.Event
● センサーイベント
■ Goの標準パッケージ
● ほとんどのパッケージは使える
● net/httpでWebサーバを立てる
○ Androidはandroid.permission.INTERNETがいる
○ 参考:サンプルコード
Google Play に公開するまでの道のり
● Goでモバイルアプリを書く
● apkを作る
○ gomobile build pkg_name
● アイコンを作る
○ apkにresがない
● apkにresを突っ込む
○ apk-toolで一度展開して突っ込む
● 署名+zipaligne
詳しくはブログに書いています
http://klabgames.tech.blog.jp.klab.com/
結構変わってる!
■テクスチャ開放ができる
● sprite.Engine.Release
● glutil.Images.Release
■ テクスチャロード
● 1回目のペイントイベントでなくてよい
● lifecycle.EventのStageVisible(CrossOn)で
よい
Goだけでモバイルアプリを作ろう

Goだけでモバイルアプリを作ろう