forked from zacharycarter/zengine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
As mentioned in a few commit comments and issue zacharycarter#21, the first round of the timer module looked a little wrong (e.g. it was giving us milliseconds for `deltaTime()` when it should have been giving us seconds instead). This commit fixes that and removes a little cruft. Under the hood all of the times are measured in hard integers, but the programmer is given a floating point interface to using the time. On top of that, the timer module now has a `Timer` object. The rationale for this is two fold: 1. This makes the `Timer` less tied into the engine internals (i.e. independant). 2. Users may need timers for other things (e.g. spell cooldowns, time trials in racing scenarios, making a day n' night cycle; the list goes on). Before we only had one global timer. Now we've got many that the user can use (and resuse). I've also added some documentation better explaining things. (I should maybe add some drawings too). closes zacharycarter#21
- Loading branch information
1 parent
ca3e1c0
commit 78b5d65
Showing
2 changed files
with
73 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,74 @@ | ||
import sdl2 | ||
|
||
var | ||
startTime, currentTime, previousTime, updateTime: float64 | ||
ticks: uint | ||
frequency: float64 | ||
|
||
# Returns total number of ticks the timer has endured | ||
proc totalTicks*() : uint {.inline.} = | ||
ticks | ||
|
||
# Returns the time elapsed between the current frame | ||
# and previous frame | ||
proc deltaTime*() : float64 {.inline.} = | ||
updateTime | ||
|
||
# Returns the time elapsed since application start | ||
proc timeElapsed*() : float64 {.inline.} = | ||
currentTime - startTime | ||
|
||
# Returns the current time | ||
proc time*() : float64 {.inline.} = | ||
float64(sdl2.getPerformanceCounter()*1000) / frequency | ||
|
||
# Ticks the timer | ||
proc tick*() {.inline.} = | ||
currentTime = time() | ||
updateTime = currentTime - previousTime | ||
previousTime = currentTime | ||
inc(ticks) | ||
|
||
# Initializes the timer | ||
proc init*() = | ||
frequency = float64 sdl2.getPerformanceFrequency() | ||
startTime = time() | ||
currentTime = startTime | ||
|
||
# The `Timer` object is what is used to measure time and differences in time. | ||
# This is necessary for things like Animation, frame independant movement, | ||
# lifetimes, cooldowns, and many more things. The general idea of this is that | ||
# you create a Timer, start it up, tick it forward and then grab the difference | ||
# in time from the previous tick to the next. | ||
# | ||
# Within your game (loop) there should be at least one timer. It should look | ||
# something like this: | ||
# | ||
# ``` | ||
# # Create and start the clock | ||
# var clock = Timer() | ||
# clock.start() | ||
# while running: | ||
# | ||
# # Update game & render logic | ||
# update(clock.deltaTime()) | ||
# render(clock.deltaTime()) | ||
# | ||
# # Tick forward | ||
# clock.tick() | ||
# ``` | ||
# | ||
# I'd recommend reading the documentation for the `start()`, `tick()`, and | ||
# `deltaTime()` procs to get a better idea how they work. | ||
type Timer* = object | ||
ticks: uint64 # How many times the timer has "ticked," | ||
timeSinceLastTick: float64 # Amount of time (in seconds) since the last tick | ||
startTime, currentTime, previousTime: uint64 # What actually measures the time under the hood | ||
|
||
|
||
# How many "time units," from SDL is one second (caching the function's return) | ||
let frequency: float64 = sdl2.getPerformanceFrequency().float64 | ||
|
||
|
||
# Starts the timer. You can call this multiple times to reset it. | ||
proc start*(self: var Timer) = | ||
self.startTime = sdl2.getPerformanceCounter() | ||
self.previousTime = self.startTime | ||
self.currentTime = self.startTime | ||
|
||
|
||
# Returns total number of ticks the Timer has endured. You will probably not | ||
# need to use this at all. | ||
proc totalTicks*(self: Timer) : uint64 {.inline.} = | ||
self.ticks | ||
|
||
|
||
# Returns the time elapsed between the current tick and the previous tick. This | ||
# value will not chance until you call `tick` again. Say if your game is | ||
# running at 100 logical updates per second, this would return a value around | ||
# `0.01`. If it was logically updating at 60 FPS, it would be more like | ||
# `0.016667`. | ||
# Return value is in seconds. | ||
proc deltaTime*(self: Timer) : float64 {.inline.} = | ||
self.timeSinceLastTick | ||
|
||
|
||
# Returns the time elapsed since `Timer.init()` has been called. Return value | ||
# is in seconds. | ||
proc timeElapsed*(self: Timer) : float64 {.inline.} = | ||
(self.currentTime - self.startTime).float64 / frequency | ||
|
||
|
||
# Ticks the timer forward. | ||
proc tick*(self: var Timer) {.inline.} = | ||
self.currentTime = sdl2.getPerformanceCounter() | ||
self.timeSinceLastTick = (self.currentTime - self.previousTime).float64 / frequency | ||
self.previousTime = self.currentTime | ||
self.ticks.inc() | ||
|