github.com/c-darwin/mobile@v0.0.0-20160313183840-ff625c46f7c9/example/audio/main.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build darwin linux
     6  
     7  // An app that makes a sound as the gopher hits the walls of the screen.
     8  //
     9  // Note: This demo is an early preview of Go 1.5. In order to build this
    10  // program as an Android APK using the gomobile tool.
    11  //
    12  // See http://godoc.org/github.com/c-darwin/mobile/cmd/gomobile to install gomobile.
    13  //
    14  // Get the audio example and use gomobile to build or install it on your device.
    15  //
    16  //   $ go get -d github.com/c-darwin/mobile/example/audio
    17  //   $ gomobile build github.com/c-darwin/mobile/example/audio # will build an APK
    18  //
    19  //   # plug your Android device to your computer or start an Android emulator.
    20  //   # if you have adb installed on your machine, use gomobile install to
    21  //   # build and deploy the APK to an Android target.
    22  //   $ gomobile install github.com/c-darwin/mobile/example/audio
    23  //
    24  // Additionally, you can run the sample on your desktop environment
    25  // by using the go tool.
    26  //
    27  //   $ go install github.com/c-darwin/mobile/example/audio && audio
    28  //
    29  // On Linux, you need to install OpenAL developer library by
    30  // running the command below.
    31  //
    32  //   $ apt-get install libopenal-dev
    33  package main
    34  
    35  import (
    36  	"image"
    37  	"log"
    38  	"time"
    39  
    40  	_ "image/jpeg"
    41  
    42  	"github.com/c-darwin/mobile/app"
    43  	"github.com/c-darwin/mobile/asset"
    44  	"github.com/c-darwin/mobile/event/lifecycle"
    45  	"github.com/c-darwin/mobile/event/paint"
    46  	"github.com/c-darwin/mobile/event/size"
    47  	"github.com/c-darwin/mobile/exp/app/debug"
    48  	"github.com/c-darwin/mobile/exp/audio"
    49  	"github.com/c-darwin/mobile/exp/f32"
    50  	"github.com/c-darwin/mobile/exp/sprite"
    51  	"github.com/c-darwin/mobile/exp/sprite/clock"
    52  	"github.com/c-darwin/mobile/exp/sprite/glsprite"
    53  	"github.com/c-darwin/mobile/gl"
    54  )
    55  
    56  const (
    57  	width  = 72
    58  	height = 60
    59  )
    60  
    61  var (
    62  	startTime = time.Now()
    63  
    64  	eng   = glsprite.Engine()
    65  	scene *sprite.Node
    66  
    67  	player *audio.Player
    68  
    69  	sz size.Event
    70  )
    71  
    72  func main() {
    73  	app.Main(func(a app.App) {
    74  		for e := range a.Events() {
    75  			switch e := app.Filter(e).(type) {
    76  			case lifecycle.Event:
    77  				switch e.Crosses(lifecycle.StageVisible) {
    78  				case lifecycle.CrossOn:
    79  					onStart()
    80  				case lifecycle.CrossOff:
    81  					onStop()
    82  				}
    83  			case size.Event:
    84  				sz = e
    85  			case paint.Event:
    86  				onPaint()
    87  				a.EndPaint(e)
    88  			}
    89  		}
    90  	})
    91  }
    92  
    93  func onStart() {
    94  	rc, err := asset.Open("boing.wav")
    95  	if err != nil {
    96  		log.Fatal(err)
    97  	}
    98  	player, err = audio.NewPlayer(rc, 0, 0)
    99  	if err != nil {
   100  		log.Fatal(err)
   101  	}
   102  }
   103  
   104  func onStop() {
   105  	player.Close()
   106  }
   107  
   108  func onPaint() {
   109  	if scene == nil {
   110  		loadScene()
   111  	}
   112  	gl.ClearColor(1, 1, 1, 1)
   113  	gl.Clear(gl.COLOR_BUFFER_BIT)
   114  	now := clock.Time(time.Since(startTime) * 60 / time.Second)
   115  	eng.Render(scene, now, sz)
   116  	debug.DrawFPS(sz)
   117  }
   118  
   119  func newNode() *sprite.Node {
   120  	n := &sprite.Node{}
   121  	eng.Register(n)
   122  	scene.AppendChild(n)
   123  	return n
   124  }
   125  
   126  func loadScene() {
   127  	gopher := loadGopher()
   128  	scene = &sprite.Node{}
   129  	eng.Register(scene)
   130  	eng.SetTransform(scene, f32.Affine{
   131  		{1, 0, 0},
   132  		{0, 1, 0},
   133  	})
   134  
   135  	var x, y float32
   136  	dx, dy := float32(1), float32(1)
   137  
   138  	n := newNode()
   139  	// TODO: Shouldn't arranger pass the size.Event?
   140  	n.Arranger = arrangerFunc(func(eng sprite.Engine, n *sprite.Node, t clock.Time) {
   141  		eng.SetSubTex(n, gopher)
   142  
   143  		if x < 0 {
   144  			dx = 1
   145  			boing()
   146  		}
   147  		if y < 0 {
   148  			dy = 1
   149  			boing()
   150  		}
   151  		if x+width > float32(sz.WidthPt) {
   152  			dx = -1
   153  			boing()
   154  		}
   155  		if y+height > float32(sz.HeightPt) {
   156  			dy = -1
   157  			boing()
   158  		}
   159  
   160  		x += dx
   161  		y += dy
   162  
   163  		eng.SetTransform(n, f32.Affine{
   164  			{width, 0, x},
   165  			{0, height, y},
   166  		})
   167  	})
   168  }
   169  
   170  func boing() {
   171  	player.Seek(0)
   172  	player.Play()
   173  }
   174  
   175  func loadGopher() sprite.SubTex {
   176  	a, err := asset.Open("gopher.jpeg")
   177  	if err != nil {
   178  		log.Fatal(err)
   179  	}
   180  	defer a.Close()
   181  
   182  	img, _, err := image.Decode(a)
   183  	if err != nil {
   184  		log.Fatal(err)
   185  	}
   186  	t, err := eng.LoadTexture(img)
   187  	if err != nil {
   188  		log.Fatal(err)
   189  	}
   190  	return sprite.SubTex{t, image.Rect(0, 0, 360, 300)}
   191  }
   192  
   193  type arrangerFunc func(e sprite.Engine, n *sprite.Node, t clock.Time)
   194  
   195  func (a arrangerFunc) Arrange(e sprite.Engine, n *sprite.Node, t clock.Time) { a(e, n, t) }