The script is in tools/ rather than thrown away, because two lanes are
writing Flan in the old spelling right now and their files need the same
pass at merge.
It works on forms, not on text: a keyword becomes a dot only where it sits
in a field-label position inside a brace, so an enum member in value
position, a map key inside an EDN string and a type-position {K V} are all
left alone. :keys keeps its colon -- it names no field.
120 lines
4.9 KiB
Plaintext
120 lines
4.9 KiB
Plaintext
;;;; raylib [core] example - delta time
|
|
;;;;
|
|
;;;; examples/core/core_delta_time.c. Needed get-mouse-wheel-move and get-fps,
|
|
;;;; both now bound — draw-fps was already there, but it puts the number on the
|
|
;;;; screen itself and this example wants to compare it against the target it
|
|
;;;; set, so it needs the number back.
|
|
;;;;
|
|
;;;; Three TextFormats in the C. Two of the three are a fixed number of
|
|
;;;; decimal places, which `f64->bytes` cannot do — it is "%g" — so they
|
|
;;;; still go through examples/digits.flan. The integer one does too, only
|
|
;;;; because its width is needed to put the next piece after it; the draw
|
|
;;;; itself is now (string (i64->bytes n)) and one draw-text.
|
|
;;;;
|
|
;;;; One faithfulness note that is a bug in the C and is kept anyway: it draws
|
|
;;;; `TextFormat("Frame time: %02.02f ms", GetFrameTime())` — GetFrameTime is
|
|
;;;; in SECONDS, so at 60 fps the C's own screen reads "0.02 ms" for what is
|
|
;;;; really 16.7 ms. Porting it as-is means the two programs show the same
|
|
;;;; thing, which is what a port is for; the milliseconds are drawn beside it
|
|
;;;; here rather than instead of it, so the file is not quietly asserting that
|
|
;;;; the original was right.
|
|
;;;;
|
|
;;;; The two circle positions are `defvar`s for the usual reason: they are
|
|
;;;; state between frames and a `let` inside the loop would reset them.
|
|
|
|
(import rl "vendor:raylib")
|
|
(import d "digits.flan")
|
|
|
|
(defconst screen-width 800)
|
|
(defconst screen-height 450)
|
|
|
|
(defconst speed f32 10.0)
|
|
(defconst circle-radius f32 32.0)
|
|
|
|
(defvar delta-circle rl/Vector2)
|
|
(defvar frame-circle rl/Vector2)
|
|
(defvar current-fps i32)
|
|
|
|
(defn main []
|
|
(rl/init-window screen-width screen-height
|
|
"raylib [core] example - delta time")
|
|
(defer (rl/close-window))
|
|
|
|
(set current-fps 60)
|
|
(set delta-circle (rl/Vector2 {.x 0.0 .y (/ (f32 screen-height) 3.0)}))
|
|
(set frame-circle (rl/Vector2 {.x 0.0
|
|
.y (* (f32 screen-height) (/ 2.0 3.0))}))
|
|
|
|
(rl/set-target-fps current-fps)
|
|
|
|
(until (rl/window-should-close?)
|
|
;; Update
|
|
(let [wheel (rl/get-mouse-wheel-move)]
|
|
(unless (= wheel 0.0)
|
|
(set current-fps (+ current-fps (i32 wheel)))
|
|
(when (< current-fps 0) (set current-fps 0))
|
|
(rl/set-target-fps current-fps)))
|
|
|
|
;; The whole point of the example: one circle is scaled by the frame time
|
|
;; and one is not, so lowering the target with the wheel makes the second
|
|
;; one crawl while the first keeps its speed.
|
|
(set (.x delta-circle)
|
|
(+ (.x delta-circle) (* (rl/get-frame-time) (* 6.0 speed))))
|
|
(set (.x frame-circle) (+ (.x frame-circle) (* 0.1 speed)))
|
|
|
|
(when (> (.x delta-circle) (f32 screen-width)) (set (.x delta-circle) 0.0))
|
|
(when (> (.x frame-circle) (f32 screen-width)) (set (.x frame-circle) 0.0))
|
|
|
|
(when (rl/key-pressed? :r)
|
|
(set (.x delta-circle) 0.0)
|
|
(set (.x frame-circle) 0.0))
|
|
|
|
;; Draw
|
|
(rl/begin-drawing)
|
|
(rl/clear-background rl/raywhite)
|
|
|
|
(rl/draw-circle-v delta-circle circle-radius rl/red)
|
|
(rl/draw-circle-v frame-circle circle-radius rl/blue)
|
|
|
|
;; "FPS: unlimited (%i)" when the target is 0, "FPS: %i (target: %i)"
|
|
;; otherwise — the C's own branch, reassembled out of literals and
|
|
;; draw-int. `x` walks along the line as each piece is drawn, which is what
|
|
;; the returned width from draw-int is for.
|
|
(if (<= current-fps 0)
|
|
(let [x 10]
|
|
(rl/draw-text "FPS: unlimited (" x 10 20 rl/darkgray)
|
|
(set x (+ x (rl/measure-text "FPS: unlimited (" 20)))
|
|
(set x (+ x (d/draw-int (rl/get-fps) x 10 20 rl/darkgray)))
|
|
(rl/draw-text ")" x 10 20 rl/darkgray))
|
|
(let [x 10]
|
|
(rl/draw-text "FPS: " x 10 20 rl/darkgray)
|
|
(set x (+ x (rl/measure-text "FPS: " 20)))
|
|
(set x (+ x (d/draw-int (rl/get-fps) x 10 20 rl/darkgray)))
|
|
(rl/draw-text " (target: " x 10 20 rl/darkgray)
|
|
(set x (+ x (rl/measure-text " (target: " 20)))
|
|
(set x (+ x (d/draw-int current-fps x 10 20 rl/darkgray)))
|
|
(rl/draw-text ")" x 10 20 rl/darkgray)))
|
|
|
|
;; The C's line, kept exactly — seconds, labelled ms.
|
|
(let [x 10]
|
|
(rl/draw-text "Frame time: " x 30 20 rl/darkgray)
|
|
(set x (+ x (rl/measure-text "Frame time: " 20)))
|
|
(set x (+ x (d/draw-f32 (rl/get-frame-time) 2 x 30 20 rl/darkgray)))
|
|
(rl/draw-text " ms" x 30 20 rl/darkgray))
|
|
;; And the same number in the unit the label claims, so the file does not
|
|
;; have to be read to notice.
|
|
(let [x 10]
|
|
(rl/draw-text "(really " x 50 20 rl/lightgray)
|
|
(set x (+ x (rl/measure-text "(really " 20)))
|
|
(set x (+ x (d/draw-f32 (* (rl/get-frame-time) 1000.0) 2 x 50 20
|
|
rl/lightgray)))
|
|
(rl/draw-text " ms)" x 50 20 rl/lightgray))
|
|
|
|
(rl/draw-text "Use the scroll wheel to change the fps limit, r to reset"
|
|
10 70 20 rl/darkgray)
|
|
|
|
(rl/draw-text "FUNC: x += GetFrameTime()*speed" 10 110 20 rl/red)
|
|
(rl/draw-text "FUNC: x += speed" 10 260 20 rl/blue)
|
|
|
|
(rl/end-drawing)))
|