mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 11:48:55 +01:00
faaf391619
Syncing was already incomplete (e.g. decoding takes more than one frame and delays can happen in this case). Giving up syncing audio timer and game timer should not affect the game experience so much. Instead, clock implementation will be much simpler.
123 lines
2.4 KiB
Go
123 lines
2.4 KiB
Go
// Copyright 2017 The Ebiten Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package clock manages game timers.
|
|
package clock
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const FPS = 60
|
|
|
|
var (
|
|
frames int64
|
|
|
|
// lastSystemTime is the last system time in the previous Update.
|
|
lastSystemTime int64
|
|
|
|
currentFPS float64
|
|
lastFPSUpdated int64
|
|
framesForFPS int64
|
|
|
|
started bool
|
|
onStart func()
|
|
|
|
m sync.Mutex
|
|
)
|
|
|
|
func CurrentFPS() float64 {
|
|
m.Lock()
|
|
v := currentFPS
|
|
m.Unlock()
|
|
return v
|
|
}
|
|
|
|
func OnStart(f func()) {
|
|
m.Lock()
|
|
onStart = f
|
|
m.Unlock()
|
|
}
|
|
|
|
func updateFPS(now int64) {
|
|
if lastFPSUpdated == 0 {
|
|
lastFPSUpdated = now
|
|
}
|
|
framesForFPS++
|
|
if time.Second > time.Duration(now-lastFPSUpdated) {
|
|
return
|
|
}
|
|
currentFPS = float64(framesForFPS) * float64(time.Second) / float64(now-lastFPSUpdated)
|
|
lastFPSUpdated = now
|
|
framesForFPS = 0
|
|
}
|
|
|
|
// Update updates the inner clock state and returns an integer value
|
|
// indicating how many game frames the game should update.
|
|
func Update() int {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
if !started {
|
|
if onStart != nil {
|
|
onStart()
|
|
}
|
|
started = true
|
|
}
|
|
|
|
n := now()
|
|
|
|
// Initialize lastSystemTime if needed.
|
|
if lastSystemTime == 0 {
|
|
lastSystemTime = n
|
|
}
|
|
|
|
diff := n - lastSystemTime
|
|
if diff < 0 {
|
|
return 0
|
|
}
|
|
|
|
count := 0
|
|
syncWithSystemClock := false
|
|
|
|
if diff > 5*int64(time.Second)/FPS {
|
|
// The previous time is too old.
|
|
// Let's force to sync the game time with the system clock.
|
|
syncWithSystemClock = true
|
|
} else {
|
|
count = int(diff * FPS / int64(time.Second))
|
|
}
|
|
|
|
// Stabilize FPS.
|
|
// Without this adjustment, count can be unstable like 0, 2, 0, 2, ...
|
|
if count == 0 && (int64(time.Second)/FPS/2) < diff {
|
|
count = 1
|
|
}
|
|
if count == 2 && (int64(time.Second)/FPS*3/2) > diff {
|
|
count = 1
|
|
}
|
|
|
|
frames += int64(count)
|
|
if syncWithSystemClock {
|
|
lastSystemTime = n
|
|
} else {
|
|
lastSystemTime += int64(count) * int64(time.Second) / FPS
|
|
}
|
|
|
|
updateFPS(n)
|
|
|
|
return count
|
|
}
|