ui: Add IsRunnableInBackground / SetRunnableInBackground (#272)

This commit is contained in:
Hajime Hoshi 2017-08-02 23:37:50 +09:00
parent bb5036b3e1
commit f0d47312c4
6 changed files with 105 additions and 25 deletions

View File

@ -58,7 +58,7 @@ type Input struct {
}
func (i *Input) update() {
for _, key := range []ebiten.Key{ebiten.KeyP, ebiten.KeyS, ebiten.KeyX, ebiten.KeyZ} {
for _, key := range []ebiten.Key{ebiten.KeyP, ebiten.KeyS, ebiten.KeyX, ebiten.KeyZ, ebiten.KeyB} {
if !ebiten.IsKeyPressed(key) {
i.keyStates[key] = 0
} else {
@ -170,6 +170,10 @@ func (p *Player) update() error {
p.updatePlayPause()
p.updateSE()
p.updateVolume()
if p.input.isKeyTriggered(ebiten.KeyB) {
b := ebiten.IsRunnableInBackground()
ebiten.SetRunnableInBackground(!b)
}
if err := p.audioContext.Update(); err != nil {
return err
}
@ -262,6 +266,7 @@ func (p *Player) draw(screen *ebiten.Image) {
Press S to toggle Play/Pause
Press P to play SE
Press Z or X to change volume of the music
Press B to switch the run-in-background state
%s`, ebiten.CurrentFPS(), currentTimeStr)
ebitenutil.DebugPrint(screen, msg)
}

View File

@ -21,6 +21,7 @@ import (
"image/color"
_ "image/jpeg"
"log"
"math"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
@ -41,7 +42,9 @@ var (
ebiten.KeyRight: 0,
ebiten.KeyS: 0,
ebiten.KeyF: 0,
ebiten.KeyB: 0,
}
count = 0
)
func update(screen *ebiten.Image) error {
@ -56,6 +59,7 @@ func update(screen *ebiten.Image) error {
d := int(32 / screenScale)
screenWidth, screenHeight := screen.Size()
fullscreen := ebiten.IsFullscreen()
runnableInBackground := ebiten.IsRunnableInBackground()
if keyStates[ebiten.KeyUp] == 1 {
screenHeight += d
@ -88,9 +92,15 @@ func update(screen *ebiten.Image) error {
if keyStates[ebiten.KeyF] == 1 {
fullscreen = !fullscreen
}
if keyStates[ebiten.KeyB] == 1 {
runnableInBackground = !runnableInBackground
}
ebiten.SetScreenSize(screenWidth, screenHeight)
ebiten.SetScreenScale(screenScale)
ebiten.SetFullscreen(fullscreen)
ebiten.SetRunnableInBackground(runnableInBackground)
count++
if ebiten.IsRunningSlowly() {
return nil
@ -101,12 +111,16 @@ func update(screen *ebiten.Image) error {
w2, h2 := screen.Size()
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(-w+w2)/2, float64(-h+h2)/2)
dx := math.Cos(2*math.Pi*float64(count)/360) * 10
dy := math.Sin(2*math.Pi*float64(count)/360) * 10
op.GeoM.Translate(dx, dy)
screen.DrawImage(gophersImage, op)
x, y := ebiten.CursorPosition()
msg := fmt.Sprintf(`Press arrow keys to change the window size
Press S key to change the window scale
Press F key to change the fullscreen state
Press B key to change the run-in-background state
Cursor: (%d, %d)
FPS: %0.2f`, x, y, ebiten.CurrentFPS())
ebitenutil.DebugPrint(screen, msg)

View File

@ -30,22 +30,23 @@ import (
)
type userInterface struct {
title string
window *glfw.Window
width int
height int
scale float64
deviceScale float64
glfwScale float64
fullscreen bool
fullscreenScale float64
funcs chan func()
running bool
sizeChanged bool
origPosX int
origPosY int
initFullscreen bool
m sync.Mutex
title string
window *glfw.Window
width int
height int
scale float64
deviceScale float64
glfwScale float64
fullscreen bool
fullscreenScale float64
funcs chan func()
running bool
sizeChanged bool
origPosX int
origPosY int
initFullscreen bool
runnableInBackground bool
m sync.Mutex
}
var (
@ -133,6 +134,19 @@ func (u *userInterface) setInitFullscreen(initFullscreen bool) {
u.m.Unlock()
}
func (u *userInterface) isRunnableInBackground() bool {
u.m.Lock()
v := u.runnableInBackground
u.m.Unlock()
return v
}
func (u *userInterface) setRunnableInBackground(runnableInBackground bool) {
u.m.Lock()
u.runnableInBackground = runnableInBackground
u.m.Unlock()
}
func (u *userInterface) runOnMainThread(f func() error) error {
if u.funcs == nil {
// already closed
@ -213,6 +227,14 @@ func SetFullscreen(fullscreen bool) {
})
}
func SetRunnableInBackground(runnableInBackground bool) {
currentUI.setRunnableInBackground(runnableInBackground)
}
func IsRunnableInBackground() bool {
return currentUI.isRunnableInBackground()
}
func ScreenOffset() (float64, float64) {
u := currentUI
if !u.isRunning() {
@ -372,7 +394,7 @@ func (u *userInterface) update(g GraphicsContext) error {
_ = u.runOnMainThread(func() error {
u.pollEvents()
for u.window.GetAttrib(glfw.Focused) == 0 {
for !u.isRunnableInBackground() && u.window.GetAttrib(glfw.Focused) == 0 {
// Wait for an arbitrary period to avoid busy loop.
time.Sleep(time.Second / 60)
u.pollEvents()

View File

@ -27,10 +27,11 @@ import (
var canvas *js.Object
type userInterface struct {
width int
height int
scale float64
fullscreen bool
width int
height int
scale float64
fullscreen bool
runnableInBackground bool
deviceScale float64
sizeChanged bool
@ -67,6 +68,14 @@ func IsFullscreen() bool {
return currentUI.fullscreen
}
func SetRunnableInBackground(runnableInBackground bool) {
currentUI.runnableInBackground = runnableInBackground
}
func IsRunnableInBackground() bool {
return currentUI.runnableInBackground
}
func ScreenOffset() (float64, float64) {
return 0, 0
}
@ -104,7 +113,7 @@ func (u *userInterface) actualScreenScale() float64 {
}
func (u *userInterface) update(g GraphicsContext) error {
if !u.windowFocus {
if !u.runnableInBackground && !u.windowFocus {
return nil
}
if opengl.GetContext().IsContextLost() {

View File

@ -118,12 +118,20 @@ func SetCursorVisibility(visibility bool) {
// Do nothing
}
func SetFullscreen(fullscreen bool) bool {
func SetFullscreen(fullscreen bool) {
// Do nothing
}
func IsFullscreen() bool {
// Do nothing
return false
}
func IsFullscreen() bool {
func SetRunnableInBackground(runnableInBackground bool) {
// Do nothing
}
func IsRunnableInBackground() bool {
// Do nothing
return false
}

22
run.go
View File

@ -178,3 +178,25 @@ func IsFullscreen() bool {
func SetFullscreen(fullscreen bool) {
ui.SetFullscreen(fullscreen)
}
// IsRunnableInBackground returns a boolean value indicating whether the game runs even in background.
//
// This function is concurrent-safe.
func IsRunnableInBackground() bool {
return ui.IsRunnableInBackground()
}
// SetRunnableInBackground sets the state if the game runs even in background.
//
// If the given value is true, the game runs in background e.g. when losing focus.
// The initial state is false.
//
// Known issue: On browsers, even if the state is on, the game doesn't run in background tabs.
// This is because browsers throttles background tabs not to often update.
//
// SetRunnableInBackground doesn't work on mobiles so far.
//
// This function is concurrent-safe.
func SetRunnableInBackground(runnableInBackground bool) {
ui.SetRunnableInBackground(runnableInBackground)
}