The trio the author decided on 2026-09-20 is now all built: def is CL's defparameter — its initialiser runs on every daemon re-run, unguarded, so an edited initialiser repaints the same storage on C-c C-c plus re-run — defonce (Clojure's name for CL's defvar, per the author) initialises once behind the .init~once. flag, and defconst stays the image. One parse arm reads both forms; the difference is Ast.reinit, carried to Tast.global's grerun. Emit.startup_plan gives a def no guard flag, and Check.check_global lifts every def initialiser — zero and literal included — into global/<n>, so the host's startup reaches it through the function cell and a re-evaluated def swaps it (Session's def_inits; Emit.redefinition declares the cell for a non-sibling target). The old defvar spelling is refused with the rename and both compiling spellings, and every program, test, doc and editor list is swept — except sand.flan, the author's live WIP, whose seven defvar lines are flagged in FIX.org and keep its three dependent tests red on this branch.
75 lines
3.1 KiB
Plaintext
75 lines
3.1 KiB
Plaintext
;;;; raylib [text] example - text writing anim
|
|
;;;;
|
|
;;;; examples/text/text_writing_anim.c. Sixty lines of C whose whole substance
|
|
;;;; is one call this package cannot bind:
|
|
;;;;
|
|
;;;; DrawText(TextSubtext(message, 0, framesCounter/10), ...)
|
|
;;;;
|
|
;;;; TextSubtext is in raylib.h and is not in the bindings, on the rule
|
|
;;;; raylib.flan states for the whole Text* family: it answers a `char *` into
|
|
;;;; a rotating static buffer, and declare-c refuses a returned pointer to
|
|
;;;; memory the caller does not own. There is no missing line to add — the
|
|
;;;; binding would be wrong at any signature.
|
|
;;;;
|
|
;;;; And it does not matter, because Flan has the operation as a primitive.
|
|
;;;; `(slice a lo hi)` takes a view of an array, `(string b)` reinterprets the
|
|
;;;; bytes as a string at no cost, and `(string (slice message 0 n))` is
|
|
;;;; TextSubtext with the static buffer removed — no copy, no shared state, no
|
|
;;;; rotation to run out of. Porting the example is therefore how the gap gets
|
|
;;;; *closed* rather than reported: the C's workaround for not having slices
|
|
;;;; is the thing Flan did not need.
|
|
;;;;
|
|
;;;; The one place they differ, and it is why the clamp below is here rather
|
|
;;;; than in the C: TextSubtext clips its length to the string, so the C can
|
|
;;;; pass a counter that runs past the end for ever and see nothing happen.
|
|
;;;; `slice` does not clip — an out-of-range bound is an error, and a bound
|
|
;;;; computed at run time is checked at run time — so the length has to be
|
|
;;;; brought inside the string before the call. That is a better failure than
|
|
;;;; the C's, and it costs one `min`.
|
|
;;;;
|
|
;;;; The message is a `[u8]` and not a `string` because `slice` takes an array
|
|
;;;; or a slice; `(bytes-view "…")` is the bridge in the other direction from
|
|
;;;; `(string …)` and costs nothing either. The embedded newline is written as
|
|
;;;; an escape, and raylib's draw-text breaks the line on it.
|
|
|
|
(import rl "vendor:raylib")
|
|
|
|
(defconst screen-width 800)
|
|
(defconst screen-height 450)
|
|
|
|
(defconst message
|
|
"This sample illustrates a text writing\nanimation effect! Check it out! ;)")
|
|
|
|
(defonce frames-counter i32)
|
|
|
|
(defn main [] ()
|
|
(rl/init-window screen-width screen-height
|
|
"raylib [text] example - text writing anim")
|
|
(defer (rl/close-window))
|
|
|
|
(set frames-counter 0)
|
|
|
|
(rl/set-target-fps 60)
|
|
|
|
(until (rl/window-should-close?)
|
|
;; Update. Holding space runs the counter eight times faster; enter starts
|
|
;; it over.
|
|
(if (rl/key-down? :key-space)
|
|
(set frames-counter (+ frames-counter 8))
|
|
(set frames-counter (+ frames-counter 1)))
|
|
|
|
(when (rl/key-pressed? :key-enter) (set frames-counter 0))
|
|
|
|
;; Draw
|
|
(rl/with-drawing
|
|
(rl/clear-background rl/raywhite)
|
|
|
|
;; One character every ten frames. The clamp is the whole difference from
|
|
;; the C — see the header comment.
|
|
(let [b (bytes-view message)
|
|
n (min (i32 (len b)) (/ frames-counter 10))]
|
|
(rl/draw-text (string (slice b 0 n)) 210 160 20 rl/maroon))
|
|
|
|
(rl/draw-text "PRESS [ENTER] to RESTART!" 240 260 20 rl/lightgray)
|
|
(rl/draw-text "HOLD [SPACE] to SPEED UP!" 239 300 20 rl/lightgray))))
|