twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

clock.go (3217B)


      1 // Copyright 2017 The Ebiten Authors
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // Package clock manages game timers.
     16 package clock
     17 
     18 import (
     19 	"sync"
     20 	"time"
     21 )
     22 
     23 var (
     24 	lastNow int64
     25 
     26 	// lastSystemTime is the last system time in the previous Update.
     27 	// lastSystemTime indicates the logical time in the game, so this can be bigger than the curren time.
     28 	lastSystemTime int64
     29 
     30 	currentFPS  float64
     31 	currentTPS  float64
     32 	lastUpdated int64
     33 	fpsCount    = 0
     34 	tpsCount    = 0
     35 
     36 	m sync.Mutex
     37 )
     38 
     39 func init() {
     40 	n := now()
     41 	lastNow = n
     42 	lastSystemTime = n
     43 	lastUpdated = n
     44 }
     45 
     46 func CurrentFPS() float64 {
     47 	m.Lock()
     48 	v := currentFPS
     49 	m.Unlock()
     50 	return v
     51 }
     52 
     53 func CurrentTPS() float64 {
     54 	m.Lock()
     55 	v := currentTPS
     56 	m.Unlock()
     57 	return v
     58 }
     59 
     60 func calcCountFromTPS(tps int64, now int64) int {
     61 	if tps == 0 {
     62 		return 0
     63 	}
     64 	if tps < 0 {
     65 		panic("clock: tps must >= 0")
     66 	}
     67 
     68 	diff := now - lastSystemTime
     69 	if diff < 0 {
     70 		return 0
     71 	}
     72 
     73 	count := 0
     74 	syncWithSystemClock := false
     75 
     76 	if diff > int64(time.Second)*5/60 {
     77 		// The previous time is too old.
     78 		// Let's force to sync the game time with the system clock.
     79 		syncWithSystemClock = true
     80 	} else {
     81 		count = int(diff * tps / int64(time.Second))
     82 	}
     83 
     84 	// Stabilize FPS.
     85 	// Without this adjustment, count can be unstable like 0, 2, 0, 2, ...
     86 	if count == 0 && (int64(time.Second)/tps/2) < diff {
     87 		count = 1
     88 	}
     89 	if count == 2 && (int64(time.Second)/tps*3/2) > diff {
     90 		count = 1
     91 	}
     92 
     93 	if syncWithSystemClock {
     94 		lastSystemTime = now
     95 	} else {
     96 		lastSystemTime += int64(count) * int64(time.Second) / tps
     97 	}
     98 
     99 	return count
    100 }
    101 
    102 func updateFPSAndTPS(now int64, count int) {
    103 	fpsCount++
    104 	tpsCount += count
    105 	if now < lastUpdated {
    106 		panic("clock: lastUpdated must be older than now")
    107 	}
    108 	if time.Second > time.Duration(now-lastUpdated) {
    109 		return
    110 	}
    111 	currentFPS = float64(fpsCount) * float64(time.Second) / float64(now-lastUpdated)
    112 	currentTPS = float64(tpsCount) * float64(time.Second) / float64(now-lastUpdated)
    113 	lastUpdated = now
    114 	fpsCount = 0
    115 	tpsCount = 0
    116 }
    117 
    118 const UncappedTPS = -1
    119 
    120 // Update updates the inner clock state and returns an integer value
    121 // indicating how many times the game should update based on given tps.
    122 // tps represents TPS (ticks per second).
    123 // If tps is UncappedTPS, Update always returns 1.
    124 // If tps <= 0 and not UncappedTPS, Update always returns 0.
    125 //
    126 // Update is expected to be called per frame.
    127 func Update(tps int) int {
    128 	m.Lock()
    129 	defer m.Unlock()
    130 
    131 	n := now()
    132 	if lastNow > n {
    133 		// This ensures that now() must be monotonic (#875).
    134 		panic("clock: lastNow must be older than n")
    135 	}
    136 	lastNow = n
    137 
    138 	c := 0
    139 	if tps == UncappedTPS {
    140 		c = 1
    141 	} else if tps > 0 {
    142 		c = calcCountFromTPS(int64(tps), n)
    143 	}
    144 	updateFPSAndTPS(n, c)
    145 
    146 	return c
    147 }