Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Go MobileでAndroidアプリ開発

23,022 views

Published on

Droid Kaigi 2016で発表したものです。

Published in: Technology

Go MobileでAndroidアプリ開発

  1. 1. Go Mobileで Androidアプリ開発 2016/02/18(木) @Droid Kaigi 2016 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. ハッシュタグ: #DroidKaigiC #gomobile
  2. 2. アジェンダ ■ 自己紹介 ■ Goについて ● Goの特徴 ■ Androidアプリ開発とGo ● Goで開発ツールを作ろう ● Android上で動くツールを作ろう ■ Go Mobile ● ネイティブアプリ ● SDKアプリ ■ まとめ 2
  3. 3. 自己紹介 KLab株式会社 KLabGames事業本部 エンジニア 上田拓也 twitter: @tenntenn ■ 好きな言語 Go, JavaScript, Lua ■ 業務 モバイルオンラインゲームの開発(クライアントサイド) 主にゲームエンジンを使ったゲーム開発 Androidのコードを直接書くことは多くない 3
  4. 4. Goについて ● Goの特徴 ○ 強力でシンプルな言語設計と文法 ○ 並行プログラミング ○ 周辺ツールの充実 ○ 豊富な標準ライブラリ ○ シングルバイナリ/クロスコンパイル 4
  5. 5. Goとは? Googleが開発しているプログラミング言語 ■ 特徴 ● 強力でシンプルな言語設計と文法 ● 並行プログラミング ● 豊富な標準ライブラリ群 ● 周辺ツールの充実 ● シングルバイナリ/クロスコンパイル Goについて/Goの特徴 5
  6. 6. 強力でシンプルな言語設計と文法 Goについて/Goの特徴 ■ スクリプト言語の書きやすさ ● 冗長な記述は必要ない ■ 型のある言語の厳密さ ● 曖昧な記述はできない 6 非常に書きやすい!
  7. 7. 並行プログラム ■ ゴールーチン ● 軽量なスレッドに近いもの ● goキーワードをつけて関数呼び出し ■ チャネル ● ゴールーチン間のデータのやり取り ● 安全にデータをやり取りできる Goについて/Goの特徴 7 チャネル ゴールーチン A ゴールーチン B データ データ go f()
  8. 8. 豊富な標準ライブラリ ■ 標準ライブラリ一覧  https://golang.org/pkg/ 基本的なライブラリは標 準で揃っている Goについて/Goの特徴 8 net/http HTTPサーバなど archive, compress zipやgzipなど crypto 暗号化 encoding JSON, XML, CSVなど html/template HTMLテンプレート os, path/filepath ファイル操作など
  9. 9. 周辺ツールの充実(go tool) ■ go toolとして標準/準標準として提供 Goについて/Goの特徴 9 go build ビルドを行うコマンド go test xxxx_test.goに書かれたテスト コードの実行 go doc / godoc ドキュメント生成 gofmt / goimports コードフォーマッター golint コードチェッカー、リンター gocode コード補完
  10. 10. シングルバイナリ/クロスコンパイル ■ 環境変数のGOOSとGOARCHを指定する 開発環境とは違うOSやアーキテクチャ向けに クロスコンパイルできる # Windows(32ビット)向けにコンパイル $ GOOS=windows GOARCH=386 go build # Linux(64ビット)向けにコンパイル $ GOOS=linux GOARCH=amd64 go build シングルバイナリになるので 動作環境を用意しなくてよい go buildはコンパイルするコマンド Goについて/Goの特徴 10
  11. 11. Goを勉強するには ■ golang.org ● 公式ドキュメント類が充実 ■ コミュニティ ● Gophers Slack #japan ● Google+ Golang JP ■ Qiita ● Goタグでまとまっている ● Go言語の初心者が見ると幸せになれる場所 ■ 書籍 ● The Go Programming Language ● Go in Action Goについて/Goの特徴 11
  12. 12. Androidアプリ開発でGoは使える? Goについて/Goの特徴 ■ 特徴 ● 強力でシンプルな言語設計と文法 ● 並行プログラミング ● 豊富な標準ライブラリ群 ● go tool ● シングルバイナリ/クロスコンパイル これらの特徴が どうAndroid開発で活かせるか? 12
  13. 13. Androidアプリ開発とGo ● Goで開発ツールを作ろう ● Android上で動くツールを作ろう 13
  14. 14. Goで開発ツールを作ろう その1 簡単に画像をアップロードできて、 アプリ上から確認できるツールを作って! 非エンジニア まだAPIサーバはできていない... 専用サーバをさくっと用意できないかな... とあるアプリ開発の序盤にて... Android開発とGo/Goで開発ツールを作ろう 14 エンジニア
  15. 15. Goで開発ツールの作り方 その1 ■ 簡易コンテンツ管理システム Android開発とGo/Goで開発ツールを作ろう 15 Android端末 確認アプリ 非エンジニアのPC Go製のサーバ ● net/httpでHTTPサーバ ● html/templateでWebアプリ ● osでファイル操作 ● archive/zipで圧縮 ● imageで画像処理 開発サーバ コンテンツのアップロード コンテンツのダウンロード 開発サーバにコンパイルして バイナリを置き実行するだけ
  16. 16. net/httpパッケージを使おう ■ 簡単にHTTPサーバを作れる(コード) func main() { http.HandleFunc("/hello", hello) http.ListenAndServe(":8080", nil) } func hello(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "hello, golang!") } HTTPハンドラ "/hello"のパスで ハンドラを設定 ポート8080で HTTPサーバを起動 Goについて/Goの特徴 $ curl http://localhost:8080/hello hello, golang! curlでアクセスしてみると 16
  17. 17. Goで開発ツールを作ろう その2 とあるアプリ開発の中盤にて... Android開発とGo/Goで開発ツールを作ろう 17 JSONをCSVに変換したい! Windowsで動くツールを作って! 開発環境はMacだから... D&DしたらJSONをCSVに変換するか... エンジニア 非エンジニア
  18. 18. Goで開発ツールの作り方 その2 ■ Windowsでも動く変換ツール Android開発とGo/Goで開発ツールを作ろう 18 Go製のツール ● クロスコンパイル ● encoding/json ● encoding/csv ● osでファイル操作 エンジニアの Mac Windows用の バイナリを渡す 非エンジニアの Windows ファイルをD&Dで変換クロスコンパイル
  19. 19. Goで開発ツールを作ろう ■ シングルバイナリ/クロスコンパイル ● Windows, Linux, Macなどで動く ● 動作環境を準備しなくていい ■ 豊富な標準ライブラリ ● HTTPサーバが簡単につくれる ● ファイル操作や各種エンコード ● 圧縮処理や画像処理 ■ 並行処理 ● リソースを効率的に使う 19 Android開発とGo/Goで開発ツールを作ろう
  20. 20. Androidアプリ開発とGo ● Goで開発ツールを作ろう ● Android上で動くツールを作ろう 20
  21. 21. Android上で動かそう ■ クロスコンパイルすれば、Androidで動く 21 Android端末 開発PC AndroidもLinuxなので Linux用にコンパイルする クロスコンパイル adb push adb shellで動かす Android開発とGo/Android上で動くツールを作ろう
  22. 22. Android上で動かそう ■ クロスコンパイルする ■ adb pushで端末に送る ■ adb shellで実行権限を与えて動かす $ GOOS=linux GOARCH=arm go build mytool.go $ adb push mytool /data/local/tmp $ adb shell $ chmod 755 /data/local/tmp/mytool $ /data/local/tmp/mytool 22 Android開発とGo/Android上で動くツールを作ろう
  23. 23. Android上で動くツール その1 アプリ上でダウンロードしたファイルが サイズが0になってることがある。 他に破損してるファイルがないか調べたい。 エンジニアA 特定の端末だけ発生する... 端末内に入ってファイル1つ1つ調べるか... エンジニアB Android開発とGo/Android上で動くツールを作ろう 23
  24. 24. サイズ0のファイルを探す 24 Android開発とGo/Android上で動くツールを作ろう Youtubeで見る コード 母艦のシェル adb shell 端末
  25. 25. Android上で動くツール その2 SNSの写真をダウンロードして リストで表示する部分のテストをしたい。 SNSへの接続部分はできてない。サイズ未定。 エンジニアA モック画像の配信サーバを用意する... 10x10.pngがきたら10x10の画像を返す... 端末からアクセスできるサーバがないから 端末でサーバを動かすか... エンジニアB 25 Android開発とGo/Android上で動くツールを作ろう
  26. 26. 画像配信のモックサーバ 26 Android開発とGo/Android上で動くツールを作ろう Youtubeで見る コード 母艦のシェル adb shell 端末
  27. 27. Android上で動かすツール ■ adb shell上で使えるコマンドを作る ● 動作環境を用意しないで済む ● Android上だけで完結 ● ファイル操作に関するパッケージが充実 ○ os, path/filepath など ■ 端末内サーバ ● ブラウザやアプリからアクセスできる ● モックサーバ ● プロキシサーバ ○ goproxyが便利 27 Android開発とGo/Android上で動くツールを作ろう
  28. 28. Android上で動かすツールの注意点 ■ ピュアGoでないとコンパイルが難しい ● cgoで書かれてると設定が必要 ○ cgoを使うとCで書かれたライブラリが使える ○ CCにNDKのCコンパイラを指定(後述) ■ OSに依存する処理には注意 ● OSに依存するライブラリ ● 環境によってサイズの異なる型の扱い ○ 環境によって32ビットだったりする ○ サイズ固定の型に書き変える ■ int32, int64, float32, float64など 28 Android開発とGo/Android上で動くツールを作ろう
  29. 29. Go Mobile ● cgoとGo Mobile ● SDKアプリ ● Nativeアプリ 29
  30. 30. cgo ■ Cで書かれたコードやライブラリが使える import "unsafe" /* #include <stdio.h> #include <stdlib.h> void hello(char *s) { printf("Hello, %sn", s); } */ import "C" func main() { str := C.CString("Droid Kaigi") C.hello(str) C.free(unsafe.Pointer(str)) } import "C"の上の コメント内にCのコードが書ける GoからCのコードを呼び出せる C上扱える値はGoのGCに回収されない Cの char * の変数を用意 30 Go Mobile/cgoとGo Mobile コード
  31. 31. Android向けにcgoを使ってビルド ■ cgoのコードもクロスコンパイルできる $ CGO_ENABLED=1 CC=arm-linux-androideabi-gcc GOOS=android GOARCH=arm GOARM=7 go buid -build-mode=pie hellocgo.go $ adb push hellocgo /data/local/tmp $ chmod 755 /data/local/tmp/hellocgo $ /data/local/tmp/hellocgo Hello, Droid Kaigi Go1.5までは -ldflags="-extldflags=-pie" cgoを含む場合はandroid クロスコンパイルでcgoを使う場合 31 Go Mobile/cgoとGo Mobile
  32. 32. build-mode ■ どうビルドするかを指定するオプション ● archive, c-archive ○ Cアーカイブ(.a)を作る ● shared, c-shared ○ 共有ライブラリ(.so)を作る ● exec ○ 実行可能ファイル ● pie ○ PIE形式の実行可能ファイル c-{archive, shared}は mainパッケージが対象 Android向けにも.soファイルが作れる 32 Go Mobile/cgoとGo Mobile
  33. 33. cgoとNDK 33 Go Mobile/cgoとGo Mobile Go cgo NDK ・クロスコンパイル ・共有ライブラリ ・Cのライブラリ ・JNI ・NativeActivity Go Mobile GoでAndroidアプリの開発
  34. 34. Go Mobileとは? ● Goでモバイルアプリを作るツール群 ○ iOS / Androidに対応 ○ golang.org/x/mobile ● 2通りのスタイル ○ SDKアプリ ⇒ Goで書いたライブラリを呼び出す ○ Nativeアプリ ⇒ Goだけで書く 参考:https://github.com/golang/go/wiki/Mobile 34 Go Mobile/cgoとGo Mobile
  35. 35. 35 https://github.com/golang/mobile
  36. 36. Go Mobileのインストール ■ 事前に必要なもの ● Goの開発環境(1.5以上) ● Androidの開発環境 ■ インストール $ go get golang.org/x/mobile/cmd/gomobile $ gomobile init -v # NDKなどをインストール 他に必要なものはこの2つのコマンドで揃う 36 Go Mobile/cgoとGo Mobile
  37. 37. Go Mobile ● cgoとGo Mobile ● SDKアプリ ● Nativeアプリ 37
  38. 38. Go aarファイル SDKアプリとNativeアプリ 38 Go Mobile/SDKアプリとNativeアプリ バインディングクラス(Java) 共有ライブラリ(.so) Java gomobile bind ■ SDKアプリ ■ Nativeアプリ apkファイル Go NativeActivity 共有ライブラリ(.so) gomobile build メイン ライブラリとして メイン
  39. 39. SDKアプリの例 ■ Ivy big number calculator(コード) ● APLっぽい言語の処理系のアプリ ● Rob Pikeが書いた実装をライブラリとして呼び出す ● Android版とiOS版でライブラリは同じ 39 Go Mobile/SDKアプリ Google Play App Store
  40. 40. gomobile bindの使い方 ■ aar(Androidアーカイブ)を生成 ● Goをビルドした共有ライブラリ(.so) ● バインディング(Java)をビルドした.jar ■ Android Studio(AS)のプラグインを使う ● gobindPlugin ● ASからgomobile bindを走らせる ● 生成したaarをリンク $ gomobile bind mypkg 40 Go Mobile/SDKアプリ
  41. 41. JavaからGoを呼び出す 41 Go Mobile/SDKアプリ Javaバインディング Javaのコード Cのコード Goのコード JNI cgo gomobile bindが 自動生成する
  42. 42. パッケージ GoとJavaのバインディング 42 Go Mobile/SDKアプリ シングルトン抽象クラス 構造体 クラス フィールド Getter/Setter メソッド 抽象メソッド パッケージ関数 staticメソッド JNIをつかった呼び出しは Seqクラスに隠蔽されている Go Java
  43. 43. gomobile bindで使えるGoの型 ■ 基本的な対応型 ● 符号付き整数と浮動小数点数 ● ブーリアン型と文字列型 ● バイトスライス([]byte) ■ 関数 ● 引数と戻り値が対応型の関数 ○ 戻り値は原則1つまで、error型は2つ目にできる ○ 2つ目のerror型はJavaのExceptionになる ■ 構造体 ● 公開された対応型のメソッドとフィールド ■ インタフェース ● 対応型のメソッド 今後増える予定 スライス =配列の参照型 Goは多値が返せる 43 Go Mobile/SDKアプリ
  44. 44. Go Mobile ● cgoとGo Mobile ● SDKアプリ ● Nativeアプリ 44
  45. 45. Go aarファイル SDKアプリとNativeアプリ 45 Go Mobile/Nativeアプリ バインディングクラス(Java) 共有ライブラリ(.so) Java gomobile bind ■ SDKアプリ ■ Nativeアプリ apkファイル Go GoNativeActivity 共有ライブラリ(.so) gomobile build メイン ライブラリとして メイン
  46. 46. Go Mobileでゲーム ■ Flappy Gopher ● GoCon キーノート ○ ソースコード ● Goだけで書かれている ● タッチイベント ● 画像の描画 ● 解説記事 ○ KLabGames Tech Blog 46 Go Mobile/Nativeアプリ $ go get github.com/adg/game $ cd $GOPATH/src/github.com/adg/game $ gomobile build
  47. 47. gomobile buildの使い方 ■ apkを生成 ● Goをビルドした.so ● GoNativeActivityをビルドしたdex ■ インストールまで行う ● 内部adb installを使う ● Androidのみ対応 $ gomobile build mypkg $ gomobile install mypkg 47 Go Mobile/Nativeアプリ goコマンドでビルドするとPCでも動く
  48. 48. Nativeアプリの機能 ■ 描画 ● OpenGL ES 2(gl, exp/gl/glutil) ● 2Dシーングラフ(exp/sprite) ■ イベント ● タッチイベント(event/touch) ● ライフサイクル(event/lifecycle) ■ センサー(exp/sensor) ● 加速度、ジャイロ、磁気センサ ■ 音(exp/audio) 48 Go Mobile/Nativeアプリ パッケージ名
  49. 49. Nativeアプリの基本 49 Go Mobile/Nativeアプリ イベントループ 描画イベント タッチイベント ライフサイクルイベント ■ ループしながらイベントを受信して処理 イベントの種類ごとに 分岐して処理 Androidの onStartなど
  50. 50. Nativieアプリの描画 ■ OpenGL ES 2 ● gl, exp/gl/glutil ● 自前でShaderなどを書く ■ スプライトエンジン ● exp/sprite ● 2Dシーングラフ ● OpenGLの関数を余り触らなくて良い ● お手軽に2Dゲームを作れる (OpenGLをゴリゴリ書くよりかは) 50 Go Mobile/Nativeアプリ
  51. 51. スプライトエンジン 51 Go Mobile/Nativeアプリ scene gopher スプライトエンジン ground1 ・・・ ノード テクスチャ サブテクスチャ ゲーム画面 描画 シーングラフ
  52. 52. スプライトエンジンを使った描画 52 Go Mobile/Nativeアプリ ・テスクチャのロード ・シーングラフの構築 描画イベント ライフサイクルイベント (画面表示開始) ・ノードの再配置 ・サブテクスチャの張替え 繰り返す 初期化処理 アフィン変換行列を セットして、座標、 角度、縮尺を設定
  53. 53. Nativeアプリの現状の問題点 ■ Google Playで公開できない ● resディレクトリが取り込めない ○ アイコンが変えれない ● 署名なしでビルドが出来ない ■ テキスト入力 ● テキスト入力が出来ない ● テキストの描画は頑張ればできる ■ プラットホームのAPIが呼べない ● Go側にインタフェースがない 53 Go Mobile/Nativeアプリ
  54. 54. ちょっと残念な解決策 ■ resディレクトリが取り込めない ● 後からapkに入れ込む ■ 署名なしでビルドが出来ない ● 一旦消して、別のkeystoreで署名する ■プラットホームのAPIが呼べない ● 内部で使ってるcgoの領域で定義された JavaVMオブジェクトを使う(サンプル) ● apkの中の.soを持ってきて、Android Studio のプロジェクトに読み込ませる せっかくapkまで作ってくれるのに! 54 Go Mobile/Nativeアプリ
  55. 55. Google Playで公開できました http://github.com/tenntenn/gofun 55 Go Mobile/Nativeアプリ
  56. 56. GoからToastが呼び出せました 56 Go Mobile/Nativeアプリ
  57. 57. Nativeアプリへの願望 ■ apkまで自動で行わない ● .soとjarの入ったaarを作る ○ gomobile bindと同じような方法 ○ Android Studioに読み込むプラグインを用意 ■ Javaを呼び出すインタフェースを公開する ● 実は存在してるけど内部パッケージ ● gomobile bindのバインディングに近い 57 Go Mobile/Nativeアプリ
  58. 58. しかしながら... ■ iOSのことも考える必要がある ● 同じフローでいけるのか? ● Obj-C/swiftのコードを呼べるのか? ■ GoやGo Mobileのコンセプトに沿うのか ● プラットフォームごとに違う方法は取れない ● ツール(gomobileコマンド)で面倒な処理をすべて行え るか? 58 Go Mobile/Nativeアプリ
  59. 59. まとめ ■ GoはAndroid開発に使える? ● さくっと開発ツールを作る ● Android上で直接動くツール ■ Go Mobile ● まだ実験段階のプロジェクト ● C/C++で書かれていた部分が置き換わっ ていってほしい ○ それでもcgoでCを書く必要あり 59
  60. 60. おまけ ■ shiny ● GUIライブラリ ● Go Mobileに似ている ● まだ始まったばかり ■ 2つのレイヤーからなる ● 基礎的な機能(ドライバ)を提供 ⇒ OpenGLやX11などの実装を提供 ● ピュアGoで書かれたウィジェット ⇒ 特定のドライバ実装に依存しない サンプルをMacで動かしたところ 60
  61. 61. 61
  62. 62. 62 以下、補足スライド
  63. 63. 63 SDKアプリの詳細
  64. 64. gomobile bindで生成されるバインディング ■ Goのコード(参考) ■ 生成されるJavaのコード package mypkg type Counter struct{Value int} func (c *Counter) Inc(){c.Value++} func New() *Counter{return &Counter{5}} public abstract class Mypkg { private Mypkg() {} public static final class Counter { public void Inc(); public long GetValue(); public void SetValue(long value); } public static Counter New(); } Java Go 自動生成
  65. 65. JavaからGoのコードを呼び出す ■ バインディングオブジェクト経由で呼び出す ● パッケージは抽象クラス ○ パッケージレベルの関数はパッケージクラスのメソッ ドになる ● 構造体は内部クラス ○ メソッドは内部クラスのメソッドになる ○ フィールドはGetter/Setter付きのフィールド Counter c = Mypkg.New(); c.Inc(); String s = String.format("%d", c.GetValue()); Log.d("Mypkg", s); // 1 Java
  66. 66. GoからJavaを呼び出す 66 Go Mobile/SDKアプリ Javaバインディング Javaのコード Cのコード Goのコード インタフェースを実装 インタフェースを 引数に関数呼び出し Javaバインディング Javaのコード Cのコード インタフェースの メソッドを呼び出し インタフェースの スタブは自動生成 Javaで実装したものをGoで呼び出せる
  67. 67. GoからJavaのコードを呼び出す ■ Go側でインタフェースとそれを使う関数を用意 ■ Java側でインタフェースを実装する public class SysPrint extends Myfmt.Printer.Stub { public void Print(String s) { System.out.println(s); } } Java package myfmt type Printer interface {Print(s string)} func PrintHello(p Printer) { p.Print("Hello, World!") } Go スタブクラスが 自動生成される
  68. 68. GoからJavaのコードを呼び出す ■ gomobile bindで生成されるバインディング public abstract class Myfmt { private Myfmt() {} public interface Printer { public void Print(String s); public static abstract class Stub implements Printer { ・・・ } ・・・ } public static void PrintHello(Printer p) { ・・・ } } Java GoのPrintHelloを 呼び出すメソッド Printerを実装
  69. 69. GoからJavaのコードを呼び出す Myfmt.Printer printer = new SysPrint(); Myfmt.PrintHello(printer); Java ■ Java側からPinterを使用する関数を呼び出す ■ 手順まとめ ● Goでインタフェースとインタフェースを引数に取 る関数を用意 ● gomobile bindでスタブを作る ● Java側でスタブを継承して実装する ● Java側からインタフェースを引数に取るGoの関 数を呼ぶ
  70. 70. SDKアプリでアプリ内サーバ 70 Go Mobile/SDKアプリ Androidアプリ Javaのコード Go製アプリ内サーバ HTTPリクエスト アプリ内サーバへHTTPリクエストを投げ るという選択肢も APIサーバ DBサーバ HTTPリクエスト
  71. 71. 71 Nativeアプリの詳細
  72. 72. app.Main ■ イベントループを行う関数 func main() { app.Main(func(a app.App) { // イベントループを書く }) }
  73. 73. イベントループ ■ app.App.Events()からイベントを取得 // Events() <-chan interface{} for e := range a.Events() { switch e := a.Filter(e).(type) { case lifecycle.Event: // ... case paint.Event: // ... } }
  74. 74. テクスチャのロード ■ アセットのオープン a, err := asset.Open("gopher.png") ■ 画像のデコード img, err := image.Decode(a) ■ テクスチャのロード t, err := eng.LoadTexture(img) assetsディレクトリ以下 のファイルを見に行く
  75. 75. シーングラフの構築 ■ ノードの作成と登録 ■ 子ノードの追加 scene := &sprite.Node{} eng.Register(scene) n := &sprite.Node{} eng.Register(n) scene.AppendChild(n)
  76. 76. サブテクスチャの作成と設定 ■ サブテクスチャの作成 st := sprite.Subtex { T:t, // テクスチャ R:iamge.Rect(0, 0, 100, 200) } ■ サブテクスチャの設定 eng.SetSubTex(n, st) テクスチャ上の該当の領 域を指定する
  77. 77. アフィン変換行列の設定 ■ アフィン変換行列の設定 ルートノードは、サイズ:1pt x 1pt、 座標:(0,0)、角度:0に対して変換行列を掛け合わせる // Scale(2,2)して、(5,5)だけ並行移動 eng.SetTransform(root, f32.Affine{ {2, 0, 5}, {0, 2, 5}, }) 1pt = 1/72 inch
  78. 78. アフィン変換行列の計算 ■ 親ノードから子ノードへ 親ノードの変換結果に子ノードの変換行列を 掛けわせて子ノードの描画位置を決める 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)
  79. 79. ノードの配置 ■ Node.Arranger.Arrange ● 毎フレーム呼ばれる ● ノードの位置を変更したりする type Arranger interface{ Arrange(e Engine, n *Node, t clock.Time) }

×