mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
Add IsVsyncEnabled / SetVsyncEnabled
This enables the game to work more efficiently (but consume much more CPU). Fixes #405.
This commit is contained in:
parent
aed0bf4a37
commit
e25c237a01
@ -86,6 +86,7 @@ func update(screen *ebiten.Image) error {
|
||||
fullscreen := ebiten.IsFullscreen()
|
||||
runnableInBackground := ebiten.IsRunnableInBackground()
|
||||
cursorVisible := ebiten.IsCursorVisible()
|
||||
vsyncEnabled := ebiten.IsVsyncEnabled()
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
|
||||
screenHeight += d
|
||||
@ -126,11 +127,16 @@ func update(screen *ebiten.Image) error {
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyC) {
|
||||
cursorVisible = !cursorVisible
|
||||
}
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyV) {
|
||||
vsyncEnabled = !vsyncEnabled
|
||||
}
|
||||
|
||||
ebiten.SetScreenSize(screenWidth, screenHeight)
|
||||
ebiten.SetScreenScale(screenScale)
|
||||
ebiten.SetFullscreen(fullscreen)
|
||||
ebiten.SetRunnableInBackground(runnableInBackground)
|
||||
ebiten.SetCursorVisible(cursorVisible)
|
||||
ebiten.SetVsyncEnabled(vsyncEnabled)
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyI) {
|
||||
ebiten.SetWindowIcon([]image.Image{createRandomIconImage()})
|
||||
@ -159,6 +165,7 @@ Press F key to switch the fullscreen state
|
||||
Press B key to switch the run-in-background state
|
||||
Press C key to switch the cursor visibility
|
||||
Press I key to change the window icon
|
||||
Press V key to switch vsync
|
||||
Press Q key to quit
|
||||
Cursor: (%d, %d)
|
||||
FPS: %0.2f`, x, y, ebiten.CurrentFPS())
|
||||
|
@ -49,6 +49,7 @@ type userInterface struct {
|
||||
origPosX int
|
||||
origPosY int
|
||||
runnableInBackground bool
|
||||
vsync bool
|
||||
|
||||
initFullscreen bool
|
||||
initCursorVisible bool
|
||||
@ -66,6 +67,7 @@ var (
|
||||
origPosY: -1,
|
||||
initCursorVisible: true,
|
||||
initWindowDecorated: true,
|
||||
vsync: true,
|
||||
}
|
||||
)
|
||||
|
||||
@ -241,7 +243,7 @@ func SetScreenSize(width, height int) bool {
|
||||
}
|
||||
r := false
|
||||
_ = u.runOnMainThread(func() error {
|
||||
r = u.setScreenSize(width, height, u.scale, u.fullscreen())
|
||||
r = u.setScreenSize(width, height, u.scale, u.fullscreen(), u.vsync)
|
||||
return nil
|
||||
})
|
||||
return r
|
||||
@ -254,7 +256,7 @@ func SetScreenScale(scale float64) bool {
|
||||
}
|
||||
r := false
|
||||
_ = u.runOnMainThread(func() error {
|
||||
r = u.setScreenSize(u.width, u.height, scale, u.fullscreen())
|
||||
r = u.setScreenSize(u.width, u.height, scale, u.fullscreen(), u.vsync)
|
||||
return nil
|
||||
})
|
||||
return r
|
||||
@ -302,7 +304,7 @@ func SetFullscreen(fullscreen bool) {
|
||||
}
|
||||
_ = u.runOnMainThread(func() error {
|
||||
u := currentUI
|
||||
u.setScreenSize(u.width, u.height, u.scale, fullscreen)
|
||||
u.setScreenSize(u.width, u.height, u.scale, fullscreen, u.vsync)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@ -315,6 +317,32 @@ func IsRunnableInBackground() bool {
|
||||
return currentUI.isRunnableInBackground()
|
||||
}
|
||||
|
||||
func SetVsyncEnabled(enabled bool) {
|
||||
u := currentUI
|
||||
if !u.isRunning() {
|
||||
_ = u.runOnMainThread(func() error {
|
||||
u.vsync = enabled
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
_ = u.runOnMainThread(func() error {
|
||||
u := currentUI
|
||||
u.setScreenSize(u.width, u.height, u.scale, u.fullscreen(), enabled)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func IsVsyncEnabled() bool {
|
||||
r := false
|
||||
u := currentUI
|
||||
_ = u.runOnMainThread(func() error {
|
||||
r = currentUI.vsync
|
||||
return nil
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
func SetWindowTitle(title string) {
|
||||
if !currentUI.isRunning() {
|
||||
return
|
||||
@ -459,7 +487,7 @@ func Run(width, height int, scale float64, title string, g GraphicsContext, main
|
||||
|
||||
// The game is in window mode (not fullscreen mode) at the first state.
|
||||
// Don't refer u.initFullscreen here to avoid some GLFW problems.
|
||||
u.setScreenSize(width, height, scale, false)
|
||||
u.setScreenSize(width, height, scale, false, u.vsync)
|
||||
u.title = title
|
||||
u.window.SetTitle(title)
|
||||
u.window.Show()
|
||||
@ -542,7 +570,7 @@ func (u *userInterface) update(g GraphicsContext) error {
|
||||
_ = u.runOnMainThread(func() error {
|
||||
if u.isInitFullscreen() {
|
||||
u := currentUI
|
||||
u.setScreenSize(u.width, u.height, u.scale, true)
|
||||
u.setScreenSize(u.width, u.height, u.scale, true, u.vsync)
|
||||
u.setInitFullscreen(false)
|
||||
}
|
||||
return nil
|
||||
@ -603,8 +631,8 @@ func (u *userInterface) swapBuffers() {
|
||||
}
|
||||
|
||||
// setScreenSize must be called from the main thread.
|
||||
func (u *userInterface) setScreenSize(width, height int, scale float64, fullscreen bool) bool {
|
||||
if u.width == width && u.height == height && u.scale == scale && u.fullscreen() == fullscreen {
|
||||
func (u *userInterface) setScreenSize(width, height int, scale float64, fullscreen bool, vsync bool) bool {
|
||||
if u.width == width && u.height == height && u.scale == scale && u.fullscreen() == fullscreen && u.vsync == vsync {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -622,6 +650,7 @@ func (u *userInterface) setScreenSize(width, height int, scale float64, fullscre
|
||||
u.height = height
|
||||
u.scale = scale
|
||||
u.fullscreenScale = 0
|
||||
u.vsync = vsync
|
||||
|
||||
// To make sure the current existing framebuffers are rendered,
|
||||
// swap buffers here before SetSize is called.
|
||||
@ -665,6 +694,7 @@ func (u *userInterface) setScreenSize(width, height int, scale float64, fullscre
|
||||
// Window title might be lost on macOS after coming back from fullscreen.
|
||||
u.window.SetTitle(u.title)
|
||||
}
|
||||
|
||||
// SwapInterval is affected by the current monitor of the window.
|
||||
// This needs to be called at least after SetMonitor.
|
||||
// Without SwapInterval after SetMonitor, vsynch doesn't work (#375).
|
||||
@ -672,7 +702,11 @@ func (u *userInterface) setScreenSize(width, height int, scale float64, fullscre
|
||||
// TODO: (#405) If triple buffering is needed, SwapInterval(0) should be called,
|
||||
// but is this correct? If glfw.SwapInterval(0) and the driver doesn't support triple
|
||||
// buffering, what will happen?
|
||||
glfw.SwapInterval(1)
|
||||
if u.vsync {
|
||||
glfw.SwapInterval(1)
|
||||
} else {
|
||||
glfw.SwapInterval(0)
|
||||
}
|
||||
|
||||
u.toChangeSize = true
|
||||
return true
|
||||
|
@ -36,6 +36,7 @@ type userInterface struct {
|
||||
scale float64
|
||||
fullscreen bool
|
||||
runnableInBackground bool
|
||||
vsync bool
|
||||
|
||||
sizeChanged bool
|
||||
windowFocus bool
|
||||
@ -46,12 +47,14 @@ var currentUI = &userInterface{
|
||||
sizeChanged: true,
|
||||
windowFocus: true,
|
||||
pageVisible: true,
|
||||
vsync: true,
|
||||
}
|
||||
|
||||
var (
|
||||
window = js.Global().Get("window")
|
||||
document = js.Global().Get("document")
|
||||
requestAnimationFrame = window.Get("requestAnimationFrame")
|
||||
setTimeoutForLoop = js.Global().Call("eval", "((f) => { setTimeout(f, 0); })")
|
||||
)
|
||||
|
||||
func MonitorSize() (int, int) {
|
||||
@ -86,6 +89,14 @@ func IsRunnableInBackground() bool {
|
||||
return currentUI.runnableInBackground
|
||||
}
|
||||
|
||||
func SetVsyncEnabled(enabled bool) {
|
||||
currentUI.vsync = enabled
|
||||
}
|
||||
|
||||
func IsVsyncEnabled() bool {
|
||||
return currentUI.vsync
|
||||
}
|
||||
|
||||
func ScreenPadding() (x0, y0, x1, y1 float64) {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
@ -215,7 +226,11 @@ func (u *userInterface) loop(g GraphicsContext) error {
|
||||
close(ch)
|
||||
return
|
||||
}
|
||||
requestAnimationFrame.Invoke(cf)
|
||||
if u.vsync {
|
||||
requestAnimationFrame.Invoke(cf)
|
||||
} else {
|
||||
setTimeoutForLoop.Invoke(cf)
|
||||
}
|
||||
}
|
||||
cf = js.NewCallback(f)
|
||||
// Call f asyncly to be async since ch is used in f.
|
||||
|
@ -394,6 +394,14 @@ func SetWindowDecorated(decorated bool) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
func IsVsyncEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func SetVsyncEnabled(enabled bool) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
func UpdateTouches(touches []*input.Touch) {
|
||||
input.Get().UpdateTouches(touches)
|
||||
}
|
||||
|
25
run.go
25
run.go
@ -520,3 +520,28 @@ func SetWindowIcon(iconImages []image.Image) {
|
||||
func DeviceScaleFactor() float64 {
|
||||
return devicescale.DeviceScale()
|
||||
}
|
||||
|
||||
// IsVsyncEnabled returns a boolean value indicating whether
|
||||
// the game uses the display's vsync.
|
||||
//
|
||||
// IsVsyncEnabled is concurrent-safe.
|
||||
func IsVsyncEnabled() bool {
|
||||
return ui.IsVsyncEnabled()
|
||||
}
|
||||
|
||||
// SetVsyncEnabled sets a boolean value indicating whether
|
||||
// the game uses the display's vsync.
|
||||
//
|
||||
// If the given value is true, the game tries to sync the display's refresh rate.
|
||||
// If false, the game ignores the display's refresh rate.
|
||||
// The initial value is true.
|
||||
// By disabling vsync, the game works more efficiently but consumes more CPU.
|
||||
//
|
||||
// Note that the state doesn't affect how many the run funciton is updated per second.
|
||||
//
|
||||
// SetVsyncEnabled doesn't work on mobiles so far.
|
||||
//
|
||||
// SetVsyncEnabled is concurrent-safe.
|
||||
func SetVsyncEnabled(enabled bool) {
|
||||
ui.SetVsyncEnabled(enabled)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user