-
Notifications
You must be signed in to change notification settings - Fork 2
/
clock.lisp
58 lines (51 loc) · 1.94 KB
/
clock.lisp
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
(in-package :uid)
(defclass clock ()
((last-time :accessor last-time :initform nil)
(time-delta :accessor time-delta :initform 0)
(times :accessor times)
(next-target-time :accessor next-target-time :initform 0)
(fps-limit :accessor fps-limit :initform nil :initarg :fps-limit)
(cumulative-time :initform 0.0 :accessor cumulative-time)))
(defmethod initialize-instance :after ((clock clock) &key (max-times-stored 10))
(setf (times clock) (make-queue max-times-stored)))
(defgeneric max-times-stored (clock)
(:method ((clock clock))
(queue-length (times clock))))
(defgeneric (setf max-times-stored) (new-value clock)
(:method (new-value (clock clock))
(setf (times clock) (make-queue new-value))))
(defgeneric tick (clock)
(:method :before ((clock clock))
(when (fps-limit clock)
(limit-fps clock)))
(:method ((clock clock))
(with-accessors ((times times) (last-time last-time)
(cumulative-time cumulative-time)
(dt time-delta))
clock
(let ((now (uid:now)))
(when last-time
(let ((time-delta (- now last-time)))
(setf dt time-delta)
(unless (zerop time-delta)
(when (= (queue-count times) (max-times-stored clock))
(decf cumulative-time (dequeue times)))
(enqueue time-delta times)
(incf cumulative-time time-delta))))
(setf last-time now)))))
(defgeneric limit-fps (clock)
(:method ((clock clock))
(when (fps-limit clock)
(let* ((now (now))
(sleep-time (* 2 (- (next-target-time clock) now))))
(setf (next-target-time clock)
(+ (/ (fps-limit clock))
now))
(when (plusp sleep-time)
(sleep (float sleep-time)))))))
(defgeneric fps (clock)
(:method ((clock clock))
(if (zerop (cumulative-time clock))
0
(/ (queue-count (times clock))
(cumulative-time clock)))))