From 3a8ca5ad73a69e5fddc5efc0f0a0b66c23ab8e40 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 17 Jul 2018 01:42:19 +0900 Subject: [PATCH] ui: Implement TPS/SetTPS Fixes #605 Fixes #321 --- examples/windowsize/main.go | 20 +++++++++++++++++++- graphicscontext.go | 8 +++++++- internal/clock/clock.go | 8 +++++--- run.go | 23 +++++++++++++++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/examples/windowsize/main.go b/examples/windowsize/main.go index 9a388b86c..b9f5cec45 100644 --- a/examples/windowsize/main.go +++ b/examples/windowsize/main.go @@ -87,6 +87,7 @@ func update(screen *ebiten.Image) error { runnableInBackground := ebiten.IsRunnableInBackground() cursorVisible := ebiten.IsCursorVisible() vsyncEnabled := ebiten.IsVsyncEnabled() + tps := ebiten.TPS() if inpututil.IsKeyJustPressed(ebiten.KeyUp) { screenHeight += d @@ -130,6 +131,20 @@ func update(screen *ebiten.Image) error { if inpututil.IsKeyJustPressed(ebiten.KeyV) { vsyncEnabled = !vsyncEnabled } + if inpututil.IsKeyJustPressed(ebiten.KeyT) { + switch tps { + case -1: + tps = 30 + case 30: + tps = 60 + case 60: + tps = 120 + case 120: + tps = -1 + default: + panic("not reached") + } + } ebiten.SetScreenSize(screenWidth, screenHeight) ebiten.SetScreenScale(screenScale) @@ -137,6 +152,7 @@ func update(screen *ebiten.Image) error { ebiten.SetRunnableInBackground(runnableInBackground) ebiten.SetCursorVisible(cursorVisible) ebiten.SetVsyncEnabled(vsyncEnabled) + ebiten.SetTPS(tps) if inpututil.IsKeyJustPressed(ebiten.KeyI) { ebiten.SetWindowIcon([]image.Image{createRandomIconImage()}) @@ -167,8 +183,10 @@ 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 +Press T key to switch TPS (ticks per second) Cursor: (%d, %d) -FPS: %0.2f`, x, y, ebiten.CurrentFPS()) +FPS: %0.2f +TPS: %d`, x, y, ebiten.CurrentFPS(), ebiten.TPS()) ebitenutil.DebugPrint(screen, msg) return nil } diff --git a/graphicscontext.go b/graphicscontext.go index 12c078573..0b2d2ff18 100644 --- a/graphicscontext.go +++ b/graphicscontext.go @@ -82,7 +82,13 @@ func (c *graphicsContext) initializeIfNeeded() error { } func (c *graphicsContext) Update(afterFrameUpdate func()) error { - updateCount := clock.Update(defaultTPS) + tps := int(TPS()) + count := clock.Update(tps) + + updateCount := 1 + if tps >= 0 { + updateCount = count + } if err := c.initializeIfNeeded(); err != nil { return err diff --git a/internal/clock/clock.go b/internal/clock/clock.go index eba0ec71e..9c86d34fb 100644 --- a/internal/clock/clock.go +++ b/internal/clock/clock.go @@ -110,8 +110,7 @@ func updateFPS(now int64) { // Update updates the inner clock state and returns an integer value // indicating how many game frames the game should update based on given tps. // tps represents TPS (ticks per second). -// If tps is 0, Update always returns 0. -// If tps is negative, Update panics. +// If tps <= 0, Update always returns 0. // // Update is expected to be called per frame. func Update(tps int) int { @@ -127,5 +126,8 @@ func Update(tps int) int { n := now() updateFPS(n) - return calcCountFromTPS(int64(tps), n) + if tps > 0 { + return calcCountFromTPS(int64(tps), n) + } + return 0 } diff --git a/run.go b/run.go index 290c02508..1220c42c2 100644 --- a/run.go +++ b/run.go @@ -49,8 +49,13 @@ func CurrentFPS() float64 { var ( isDrawingSkipped = int32(0) + currentTPS = int32(0) ) +func init() { + atomic.StoreInt32(¤tTPS, defaultTPS) +} + func setDrawingSkipped(skipped bool) { v := int32(0) if skipped { @@ -552,3 +557,21 @@ func IsVsyncEnabled() bool { func SetVsyncEnabled(enabled bool) { ui.SetVsyncEnabled(enabled) } + +// TPS returns the current TPS. +// +// TPS is concurrent-safe. +func TPS() int { + return int(atomic.LoadInt32(¤tTPS)) +} + +// SetTPS sets the TPS (ticks per frame), that represents how many updating function is called +// per second. +// The initial value is 60. +// +// If the given tps is negative, TPS is unfixed and the game is updated per frame. +// +// SetTPS is concurrent-safe. +func SetTPS(tps int) { + atomic.StoreInt32(¤tTPS, int32(tps)) +}