diff --git a/audio/audio.go b/audio/audio.go index ad5d7b12b..d40e43ce1 100644 --- a/audio/audio.go +++ b/audio/audio.go @@ -39,7 +39,6 @@ import ( "github.com/hajimehoshi/oto" "github.com/hajimehoshi/ebiten/internal/clock" - "github.com/hajimehoshi/ebiten/internal/loop" ) type players struct { @@ -233,7 +232,7 @@ func (c *Context) ping() { } func (c *Context) loop() { - loop.RegisterPing(c.ping) + clock.RegisterPing(c.ping) // Initialize oto.Player lazily to enable calling NewContext in an 'init' function. // Accessing oto.Player functions requires the environment to be already initialized, @@ -263,7 +262,7 @@ func (c *Context) loop() { c.m.Unlock() c.frames++ clock.ProceedPrimaryTimer() - bytesPerFrame := c.sampleRate * bytesPerSample * channelNum / loop.FPS + bytesPerFrame := c.sampleRate * bytesPerSample * channelNum / clock.FPS l := (c.frames * int64(bytesPerFrame)) - c.writtenBytes l &= mask c.writtenBytes += l diff --git a/internal/clock/clock.go b/internal/clock/clock.go index a75889017..01b6e7c3a 100644 --- a/internal/clock/clock.go +++ b/internal/clock/clock.go @@ -20,14 +20,23 @@ import ( "github.com/hajimehoshi/ebiten/internal/sync" ) +const FPS = 60 + var ( m sync.Mutex primaryTime int64 lastPrimaryTime int64 frames int64 logicalTime int64 + ping func() ) +func RegisterPing(pingFunc func()) { + m.Lock() + ping = pingFunc + m.Unlock() +} + // ProceedPrimaryTimer increments the primary time by a frame. func ProceedPrimaryTimer() { m.Lock() @@ -35,13 +44,16 @@ func ProceedPrimaryTimer() { m.Unlock() } -// Frames returns an integer value indicating how many logical frames the game should update. -// -// Frames also updates the inner timer states. -func Frames(now int64, fps int) int { +// Update updates the inner clock state and returns an integer value +// indicating how many logical frames the game should update. +func Update(now int64) int { m.Lock() defer m.Unlock() + if ping != nil { + ping() + } + // Initialize logicalTime if needed. if logicalTime == 0 { logicalTime = now @@ -74,20 +86,20 @@ func Frames(now int64, fps int) int { // As the primary time can be updated discountinuously, // the system clock is still needed. - if t > 5*int64(time.Second)/int64(fps) { + if t > 5*int64(time.Second)/FPS { // The previous time is too old. // Let's force to sync the logical time with the OS clock. sync = true } else { - count = int(t * int64(fps) / int64(time.Second)) + count = int(t * FPS / int64(time.Second)) } } // Stabilize FPS. - if count == 0 && (int64(time.Second)/int64(fps)/2) < t { + if count == 0 && (int64(time.Second)/FPS/2) < t { count = 1 } - if count == 2 && (int64(time.Second)/int64(fps)*3/2) > t { + if count == 2 && (int64(time.Second)/FPS*3/2) > t { count = 1 } if count > 3 { @@ -98,7 +110,7 @@ func Frames(now int64, fps int) int { if sync { logicalTime = now } else { - logicalTime += int64(count) * int64(time.Second) / int64(fps) + logicalTime += int64(count) * int64(time.Second) / FPS } return count } diff --git a/internal/loop/run.go b/internal/loop/run.go index a37b031fc..d34fcd787 100644 --- a/internal/loop/run.go +++ b/internal/loop/run.go @@ -22,7 +22,7 @@ import ( "github.com/hajimehoshi/ebiten/internal/sync" ) -const FPS = 60 +const FPS = clock.FPS func CurrentFPS() float64 { if theRunContext == nil { @@ -76,17 +76,6 @@ func End() { theRunContext = nil } -func RegisterPing(ping func()) { - <-contextInitCh - theRunContext.registerPing(ping) -} - -func (c *runContext) registerPing(ping func()) { - c.m.Lock() - c.ping = ping - c.m.Unlock() -} - type Updater interface { Update(updateCount int) error } @@ -99,13 +88,7 @@ func Update(u Updater) error { func (c *runContext) update(u Updater) error { n := now() - c.m.Lock() - if c.ping != nil { - c.ping() - } - c.m.Unlock() - - count := clock.Frames(n, FPS) + count := clock.Update(n) if err := u.Update(count); err != nil { return err }