blob: 6a29388ae93bf0a6bdc8c10dfa6e4c4d796dea93 [file] [log] [blame]
// 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.
// +build darwin linux
// 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"
_ "image/gif"
"golang.org/x/mobile/app"
"golang.org/x/mobile/asset"
"golang.org/x/mobile/event/paint"
"golang.org/x/mobile/event/size"
"golang.org/x/mobile/exp/app/debug"
"golang.org/x/mobile/exp/f32"
"golang.org/x/mobile/exp/sprite"
"golang.org/x/mobile/exp/sprite/clock"
"golang.org/x/mobile/exp/sprite/glsprite"
"golang.org/x/mobile/gl"
//"golang.org/x/mobile/event/mouse"
"golang.org/x/mobile/event/touch"
//gc "github.com/rthornton128/goncurses"
)
var (
startTime = time.Now()
eng = glsprite.Engine()
scene *sprite.Node
sprites []*sprite.Node
spritesXY [][]float32
initialSpritesXY [][]float32
curSpriteIndex = -1
lastMouseXY = []float32{-1,-1}
numCards = 4
numDropTargets = 3
numDecks = 2
cardWidth = float32(175)
cardHeight = float32(245)
dropWidth = float32(768/2)
dropHeight = float32(620/2)
paddingSize = float32(cardWidth/5)
middleSize = float32(cardHeight)
windowSize = []float32{-1,-1}
)
func main() {
app.Main(func(a app.App) {
var sz size.Event
for e := range a.Events() {
switch e := app.Filter(e).(type) {
case size.Event:
sz = e
windowSize[0] = float32(sz.WidthPx)
windowSize[1] = float32(sz.HeightPx)
case touch.Event:
onTouch(e)
case paint.Event:
onPaint(sz)
a.EndPaint(e)
}
}
})
}
func onTouch(t touch.Event) {
switch t.Type.String() {
case "begin":
//i > numDropTargets excludes drop targets, draw, and discard so they can't move
for i := len(sprites)-1; i >= numDropTargets+2; i-- {
if t.X >= spritesXY[i][0] &&
t.Y >= spritesXY[i][1] &&
t.X <= spritesXY[i][2]+spritesXY[i][0] &&
t.Y <= spritesXY[i][3]+spritesXY[i][1] {
curSpriteIndex = i
lastMouseXY[0] = t.X
lastMouseXY[1] = t.Y
return
}
}
//checking if draw or discard is clicked
for i := 1; i >= 0; i-- {
if t.X >= spritesXY[i][0] &&
t.Y >= spritesXY[i][1] &&
t.X <= spritesXY[i][2]+spritesXY[i][0] &&
t.Y <= spritesXY[i][3]+spritesXY[i][1] {
if i == 0 {
//draw is clicked
numCards++
loadScene()
} else {
//discard is clicked
if numCards > 0 {
numCards--
loadScene()
}
}
}
}
case "move":
if curSpriteIndex > -1 {
eng.SetTransform(sprites[curSpriteIndex], f32.Affine{
{spritesXY[curSpriteIndex][2], 0, spritesXY[curSpriteIndex][0]+t.X-lastMouseXY[0]},
{0, spritesXY[curSpriteIndex][3], spritesXY[curSpriteIndex][1]+t.Y-lastMouseXY[1]},
})
spritesXY[curSpriteIndex][0] = spritesXY[curSpriteIndex][0]+t.X-lastMouseXY[0]
spritesXY[curSpriteIndex][1] = spritesXY[curSpriteIndex][1]+t.Y-lastMouseXY[1]
lastMouseXY[0] = t.X
lastMouseXY[1] = t.Y
}
case "end":
onTarget := false
for i := 2; i < numDropTargets+2; i++ {
if curSpriteIndex > -1 &&
spritesXY[curSpriteIndex][0] + spritesXY[curSpriteIndex][2]/2 >= spritesXY[i][0] &&
spritesXY[curSpriteIndex][1] + spritesXY[curSpriteIndex][3]/2 >= spritesXY[i][1] &&
spritesXY[curSpriteIndex][0] + spritesXY[curSpriteIndex][2]/2 <= spritesXY[i][2]+spritesXY[i][0] &&
spritesXY[curSpriteIndex][1] + spritesXY[curSpriteIndex][3]/2 <= spritesXY[i][3]+spritesXY[i][1] {
eng.SetTransform(sprites[curSpriteIndex], f32.Affine{
{spritesXY[curSpriteIndex][2], 0, spritesXY[i][0]+spritesXY[i][2]/2-spritesXY[curSpriteIndex][2]/2},
{0, spritesXY[curSpriteIndex][3], spritesXY[i][1]+spritesXY[i][3]/2-spritesXY[curSpriteIndex][3]/2},
})
spritesXY[curSpriteIndex][0] = spritesXY[i][0]+spritesXY[i][2]/2-spritesXY[curSpriteIndex][2]/2
spritesXY[curSpriteIndex][1] = spritesXY[i][1]+spritesXY[i][3]/2-spritesXY[curSpriteIndex][3]/2
onTarget = true
}
}
if onTarget == false && curSpriteIndex > -1 {
eng.SetTransform(sprites[curSpriteIndex], f32.Affine{
{initialSpritesXY[curSpriteIndex][2], 0, initialSpritesXY[curSpriteIndex][0]},
{0, initialSpritesXY[curSpriteIndex][3], initialSpritesXY[curSpriteIndex][1]},
})
spritesXY[curSpriteIndex][0] = initialSpritesXY[curSpriteIndex][0]
spritesXY[curSpriteIndex][1] = initialSpritesXY[curSpriteIndex][1]
}
curSpriteIndex = -1
}
}
func onPaint(sz size.Event) {
if scene == nil {
loadScene()
}
gl.ClearColor(1, 1, 1, 1)
gl.Clear(gl.COLOR_BUFFER_BIT)
now := clock.Time(time.Since(startTime) * 60 / time.Second)
eng.Render(scene, now, sz)
debug.DrawFPS(sz)
}
func newNode() *sprite.Node {
n := &sprite.Node{}
eng.Register(n)
scene.AppendChild(n)
return n
}
func addSprite(x float32, y float32, xSize float32, ySize float32, spriteTex sprite.SubTex) {
n := newNode()
eng.SetSubTex(n, spriteTex)
eng.SetTransform(n, f32.Affine{
{xSize, 0, x},
{0, ySize, y},
})
sprites = append(sprites, n)
spritesXY = append(spritesXY, []float32{x,y,xSize,ySize})
initialSpritesXY = append(initialSpritesXY, []float32{x,y,xSize,ySize})
}
func loadScene() {
sprites = make([]*sprite.Node, 0)
spritesXY = make([][]float32, 0)
initialSpritesXY = make([][]float32, 0)
texs := loadTextures()
scene = &sprite.Node{}
eng.Register(scene)
eng.SetTransform(scene, f32.Affine{
{1, 0, 0},
{0, 1, 0},
})
dropXScaler := (float32(numDropTargets)*dropWidth+float32(numDropTargets+1)*paddingSize)/windowSize[0]
cardXScaler := (float32(numCards)*cardWidth+(float32(numCards)+1)*paddingSize)/windowSize[0]
deckXScaler := (float32(numDecks+2)*cardWidth+(float32(numDecks+2)+1)*paddingSize)/windowSize[0]
yScaler := (dropHeight+cardHeight+middleSize+4*paddingSize)/windowSize[1]
cardTexs := []sprite.SubTex{texs[card1], texs[card2], texs[card3], texs[card4]}
for yScaler > cardXScaler {
cardXScaler += (cardWidth+paddingSize)/windowSize[0]
}
//deck and discard must be added first
addSprite((2*paddingSize+cardWidth)/deckXScaler, (2*paddingSize+cardHeight)/yScaler,
cardWidth/deckXScaler, cardHeight/yScaler, texs[draw])
addSprite((3*paddingSize+2*cardWidth)/deckXScaler, (2*paddingSize+cardHeight)/yScaler,
cardWidth/deckXScaler, cardHeight/yScaler, texs[discard])
//all drop targets must be added before all cards
for i := 0; i < numDropTargets; i++ {
addSprite((float32(i+1)*paddingSize+float32(i)*dropWidth)/dropXScaler, (cardHeight+middleSize+3*paddingSize)/yScaler,
dropWidth/dropXScaler, dropHeight/yScaler, texs[dropTarget])
}
for i := 0; i < numCards; i++ {
addSprite((float32(i+1)*paddingSize+float32(i)*cardWidth)/cardXScaler, paddingSize/yScaler,
cardWidth/cardXScaler, cardHeight/cardXScaler, cardTexs[i%len(cardTexs)])
}
}
const (
card1 = iota
card2
card3
card4
dropTarget
draw
discard
)
func loadTextures() []sprite.SubTex {
a, err := asset.Open("cards.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)
}
a2, err := asset.Open("dropTarget.jpeg")
if err != nil {
log.Fatal(err)
}
defer a2.Close()
img2, _, err := image.Decode(a2)
if err != nil {
log.Fatal(err)
}
t2, err := eng.LoadTexture(img2)
if err != nil {
log.Fatal(err)
}
a3, err := asset.Open("deck.jpeg")
if err != nil {
log.Fatal(err)
}
defer a3.Close()
img3, _, err := image.Decode(a3)
if err != nil {
log.Fatal(err)
}
t3, err := eng.LoadTexture(img3)
if err != nil {
log.Fatal(err)
}
return []sprite.SubTex{
card1: sprite.SubTex{t, image.Rect(15, 15, 190, 260)},
card2: sprite.SubTex{t, image.Rect(195, 60, 370, 305)},
card3: sprite.SubTex{t, image.Rect(375, 107, 550, 350)},
card4: sprite.SubTex{t, image.Rect(555, 135, 730, 377)},
dropTarget: sprite.SubTex{t2, image.Rect(0,0,766,620)},
draw: sprite.SubTex{t3, image.Rect(0,0,1506/2,1052)},
discard: sprite.SubTex{t3, image.Rect(1506/2,0,1506,1052)},
}
}