| // Copyright 2014 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // An app that demonstrates the sprite package. |
| // |
| // Note: This demo is an early preview of Go 1.5. In order to build this |
| // program as an Android APK using the gomobile tool. |
| // |
| // See http://godoc.org/golang.org/x/mobile/cmd/gomobile to install gomobile. |
| // |
| // Get the sprite example and use gomobile to build or install it on your device. |
| // |
| // $ go get -d golang.org/x/mobile/example/sprite |
| // $ gomobile build golang.org/x/mobile/example/sprite # will build an APK |
| // |
| // # plug your Android device to your computer or start an Android emulator. |
| // # if you have adb installed on your machine, use gomobile install to |
| // # build and deploy the APK to an Android target. |
| // $ gomobile install golang.org/x/mobile/example/sprite |
| // |
| // Switch to your device or emulator to start the Basic application from |
| // the launcher. |
| // You can also run the application on your desktop by running the command |
| // below. (Note: It currently doesn't work on Windows.) |
| // $ go install golang.org/x/mobile/example/sprite && sprite |
| package main |
| |
| import ( |
| "image" |
| "log" |
| "math" |
| "time" |
| |
| _ "image/jpeg" |
| |
| "golang.org/x/mobile/app" |
| "golang.org/x/mobile/app/debug" |
| "golang.org/x/mobile/event" |
| "golang.org/x/mobile/f32" |
| "golang.org/x/mobile/gl" |
| "golang.org/x/mobile/sprite" |
| "golang.org/x/mobile/sprite/clock" |
| "golang.org/x/mobile/sprite/glsprite" |
| ) |
| |
| var ( |
| start = time.Now() |
| lastClock = clock.Time(-1) |
| |
| eng = glsprite.Engine() |
| scene *sprite.Node |
| ) |
| |
| func main() { |
| app.Run(app.Callbacks{ |
| Draw: draw, |
| Touch: touch, |
| }) |
| } |
| |
| func draw() { |
| if scene == nil { |
| loadScene() |
| } |
| |
| now := clock.Time(time.Since(start) * 60 / time.Second) |
| if now == lastClock { |
| // TODO: figure out how to limit draw callbacks to 60Hz instead of |
| // burning the CPU as fast as possible. |
| // TODO: (relatedly??) sync to vblank? |
| return |
| } |
| lastClock = now |
| |
| gl.ClearColor(1, 1, 1, 1) |
| gl.Clear(gl.COLOR_BUFFER_BIT) |
| eng.Render(scene, now) |
| debug.DrawFPS() |
| } |
| |
| func touch(t event.Touch) { |
| } |
| |
| func newNode() *sprite.Node { |
| n := &sprite.Node{} |
| eng.Register(n) |
| scene.AppendChild(n) |
| return n |
| } |
| |
| func loadScene() { |
| texs := loadTextures() |
| scene = &sprite.Node{} |
| eng.Register(scene) |
| eng.SetTransform(scene, f32.Affine{ |
| {1, 0, 0}, |
| {0, 1, 0}, |
| }) |
| |
| var n *sprite.Node |
| |
| n = newNode() |
| eng.SetSubTex(n, texs[texBooks]) |
| eng.SetTransform(n, f32.Affine{ |
| {36, 0, 0}, |
| {0, 36, 0}, |
| }) |
| |
| n = newNode() |
| eng.SetSubTex(n, texs[texFire]) |
| eng.SetTransform(n, f32.Affine{ |
| {72, 0, 144}, |
| {0, 72, 144}, |
| }) |
| |
| n = newNode() |
| n.Arranger = arrangerFunc(func(eng sprite.Engine, n *sprite.Node, t clock.Time) { |
| // TODO: use a tweening library instead of manually arranging. |
| t0 := uint32(t) % 120 |
| if t0 < 60 { |
| eng.SetSubTex(n, texs[texGopherR]) |
| } else { |
| eng.SetSubTex(n, texs[texGopherL]) |
| } |
| |
| u := float32(t0) / 120 |
| u = (1 - f32.Cos(u*2*math.Pi)) / 2 |
| |
| tx := 18 + u*48 |
| ty := 36 + u*108 |
| sx := 36 + u*36 |
| sy := 36 + u*36 |
| eng.SetTransform(n, f32.Affine{ |
| {sx, 0, tx}, |
| {0, sy, ty}, |
| }) |
| }) |
| } |
| |
| const ( |
| texBooks = iota |
| texFire |
| texGopherR |
| texGopherL |
| ) |
| |
| func loadTextures() []sprite.SubTex { |
| a, err := app.Open("waza-gophers.jpeg") |
| if err != nil { |
| log.Fatal(err) |
| } |
| defer a.Close() |
| |
| img, _, err := image.Decode(a) |
| if err != nil { |
| log.Fatal(err) |
| } |
| t, err := eng.LoadTexture(img) |
| if err != nil { |
| log.Fatal(err) |
| } |
| |
| return []sprite.SubTex{ |
| texBooks: sprite.SubTex{t, image.Rect(4, 71, 132, 182)}, |
| texFire: sprite.SubTex{t, image.Rect(330, 56, 440, 155)}, |
| texGopherR: sprite.SubTex{t, image.Rect(152, 10, 152+140, 10+90)}, |
| texGopherL: sprite.SubTex{t, image.Rect(162, 120, 162+140, 120+90)}, |
| } |
| } |
| |
| type arrangerFunc func(e sprite.Engine, n *sprite.Node, t clock.Time) |
| |
| func (a arrangerFunc) Arrange(e sprite.Engine, n *sprite.Node, t clock.Time) { a(e, n, t) } |