-
Notifications
You must be signed in to change notification settings - Fork 0
/
gameloop.go
75 lines (61 loc) · 2.37 KB
/
gameloop.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Package gameloop provides functions for creating game loops.
package gameloop
// Config describes a configuration for a game loop.
type Config struct {
// TargetFPS is used to calculate the seconds per update (1 / TargetFPS).
TargetFPS uint16
// IdleThreshold prevents updating the game if the time
// elapsed since the previous frame exceeds this number (in seconds).
IdleThreshold float64
// CurrentTimeFunc is a callback that should return the current time in
// seconds. It is used by the game loop to calculate the time elapsed
// between frames.
CurrentTimeFunc func() float64
// ProcessInputFunc is a callback that is called within the game loop. It is
// called before the UpdateFunc. It should process input logic
// (ie. keyboard, mouse, gamepad, etc.) and return a flag to signal the
// game loop to quit.
//
// This function will not be called if the elapsed time since the previous
// frame has exceeded IdleThreshold (ie. if window is minimized, etc.).
ProcessInputFunc func() (quit bool)
// UpdateFunc is a callback that is called within the game loop. It is
// called after ProcessInputFunc and it should contain logic that updates
// the game's state. This function will be called based on a fixed interval
// of 1 / TargetFPS (ie. 1 sec / 60 FPS = 0.01667 secs) and it is passed as
// a parameter (dt).
//
// This function will not be called if the elapsed time since the previous
// frame has exceeded IdleThreshold (ie. if window is minimized, etc.).
UpdateFunc func(dt float64)
// RenderFunc is a callback that is called within the game loop. It is
// called after UpdateFunc and it should contain rendering logic.
//
// This function will not be called if the elapsed time since the previous
// frame has exceeded IdleThreshold (ie. if window is minimized, etc.).
RenderFunc func()
}
// Create will create a game loop based on a given configuration.
func Create(c Config) func() {
secsPerUpdate := 1 / float64(c.TargetFPS)
var current, elapsed float64
return func() {
previous := c.CurrentTimeFunc()
lag := 0.0
for quit := false; !quit; {
current = c.CurrentTimeFunc()
elapsed = current - previous
previous = current
if elapsed > c.IdleThreshold {
continue
}
lag += elapsed
quit = c.ProcessInputFunc()
for lag >= secsPerUpdate {
c.UpdateFunc(secsPerUpdate)
lag -= secsPerUpdate
}
c.RenderFunc()
}
}
}