Merge branch 'worktree-agent-a788866b56165817f' into dev-loop
This commit is contained in:
commit
91ec235395
59
BUILT.md
59
BUILT.md
@ -5292,3 +5292,62 @@ route neither covers, and says so rather than claiming to be a design.
|
||||
|
||||
`test/programs/generics.flan` runs one written body at two key types; `test/programs/generic-map-reject.flan` is
|
||||
the other half, a call site at `f64` refused against the clause.
|
||||
|
||||
## The begin/end pairs are macros now, and the pair is all they can promise
|
||||
|
||||
`vendor/raylib/modes.flan` — a second file in the raylib package with no `declare-c` in it, split out on
|
||||
`vector.flan`'s reasoning exactly: `raylib.flan` is the package's statement about C and the file the header check
|
||||
reads signatures out of, and nothing here can be made wrong by raylib changing because nothing here names C.
|
||||
|
||||
Five macros, one per pair the package binds: `with-drawing`, `with-mode-2d`, `with-mode-3d`, `with-texture-mode`,
|
||||
`with-scissor-mode`. Each expands to `(do (begin-… args) body… (end-…))` — the calls the author used to type, in the
|
||||
order they used to type them, with the argument evaluated once where it always was. No `let` and no `gensym`
|
||||
anywhere: nothing binds a name, so there is no name a caller's could collide with, and introducing one in a
|
||||
deliberately non-hygienic macro that does not need it is a step backwards. NEXT.md called these "three-line macros
|
||||
once the expander lands" when it rejected `unwind-protect`, and they are.
|
||||
|
||||
They arrive qualified, the rule every declaration in a package follows: the importer writes `(rl/with-drawing …)`
|
||||
and a bare `(with-drawing …)` is an unknown name. The expansions name `begin-drawing` and friends unqualified and
|
||||
the expander qualifies them on the way out — `test/programs/pkgs/mac/mac.flan` is that rule's worked example, and
|
||||
these are its first non-test use.
|
||||
|
||||
**What the macro removes is not what a reader assumes it removes.** It removes *the `End*` is missing, or is the
|
||||
wrong one, or drifted away from its `Begin*` during an edit* — which is the whole of the class that actually bites,
|
||||
and `EndMode2D` closing a `BeginMode3D` type-checks fine and corrupts the matrix stack. It does **not** remove a
|
||||
body that leaves through the unwind path: a `return`, or an `invoke-restart` reaching an enclosing `restart-case`,
|
||||
skips the rest of the `do` and the `End*` with it, exactly as it skipped a hand-written one.
|
||||
|
||||
`defer` is the obvious fix and is not available. It is a compile-time construct — the forms are copied into the
|
||||
function's exit paths — so it is refused inside a loop body, and a begin/end pair lives inside the game loop
|
||||
essentially always. The refusal was checked rather than assumed:
|
||||
|
||||
```
|
||||
defer is not allowed inside a loop body — a defer is copied into every exit path of the function, so it
|
||||
always registers and always runs at function exit.
|
||||
```
|
||||
|
||||
Were it permitted there it would be wrong in the worse direction: one `EndDrawing` at function exit for N
|
||||
`BeginDrawing`s, which is the silent-wrongness class the refusal exists for. A macro expanding to a `defer` would
|
||||
therefore compile at a function body's top level and be refused in the one place anybody writes it. So the
|
||||
discipline `sand.flan` already wrote down stays the discipline — **keep the restart boundary outside the pair**, so
|
||||
choosing `continue` for a frame abandons the update and still reaches the drawing. spec-conditions §5 is the rule
|
||||
behind that: a transfer runs the intervening frames' `defer`s and moves control, and there are none here to run.
|
||||
`sand.flan`'s comment says so at the loop, and the macro's header says so at the definition.
|
||||
|
||||
**35 call sites converted** across `examples/` and `sand.flan`: 26 `with-drawing`, 5 `with-texture-mode`, 3
|
||||
`with-mode-3d`, 1 `with-mode-2d`. Every begin/end pair in the corpus except one — `examples/core-scissor-test.flan`
|
||||
turns its scissor on and off from a flag, so its `Begin` and its `End` sit in two separate `when`s with the drawing
|
||||
between them and there is no body to wrap. That site is left hand-written, and it is the honest illustration of the
|
||||
macro's limit rather than an oversight: a conditional pair is a shape a bracketing macro cannot express without
|
||||
duplicating the body.
|
||||
|
||||
`sand.flan` converted its draw pair and stays at parity — `lisp/sand.lisp` writes `rl:with-drawing` there, which is
|
||||
what makes it a port of the reference version rather than an addition to it. Its header note "no user-written
|
||||
macros" now reads "no macros of its own", because `rl/with-drawing` is the binding package's, as in the Lisp.
|
||||
|
||||
`with-scissor-mode` is the one no example exercises, so `test/programs/rl-with.flan` does: all five expanded in a
|
||||
`frame` function deliberately **unreachable from `main`**, which is what lets the case run with no libraylib at all
|
||||
— `reach.ml` answers the link from the checked program, and `check` still walks every line. Nothing there draws,
|
||||
because nothing headless can. `rl-with-reject.flan` is the arity half: a macro cannot signal while it expands, so
|
||||
the prelude's idiom is to answer a symbol that is not a name and reads as the sentence the caller needs
|
||||
(`with-mode-2d-takes-a-camera-and-a-body`), with the expander's note beneath it naming the macro at the call site.
|
||||
|
||||
@ -99,44 +99,39 @@
|
||||
(set (.rotation camera) 0.0))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
;; Everything between these two is in world space and goes through the
|
||||
;; camera. The ground and the crosshair lines are drawn far outside the
|
||||
;; window on purpose: at zoom 0.1 they still have to reach the edges.
|
||||
(rl/begin-mode-2d camera)
|
||||
;; Everything inside with-mode-2d is in world space and goes through
|
||||
;; the camera. The ground and the crosshair lines are drawn far outside
|
||||
;; the window on purpose: at zoom 0.1 they still have to reach the edges.
|
||||
(rl/with-mode-2d camera
|
||||
(rl/draw-rectangle -6000 320 13000 8000 rl/darkgray)
|
||||
|
||||
(rl/draw-rectangle -6000 320 13000 8000 rl/darkgray)
|
||||
(dotimes [i max-buildings]
|
||||
(rl/draw-rectangle-rec (at buildings i) (at build-colors i)))
|
||||
|
||||
(dotimes [i max-buildings]
|
||||
(rl/draw-rectangle-rec (at buildings i) (at build-colors i)))
|
||||
(rl/draw-rectangle-rec player rl/red)
|
||||
|
||||
(rl/draw-rectangle-rec player rl/red)
|
||||
(rl/draw-line (i32 (.x (.target camera))) (* screen-height -10)
|
||||
(i32 (.x (.target camera))) (* screen-height 10) rl/green)
|
||||
(rl/draw-line (* screen-width -10) (i32 (.y (.target camera)))
|
||||
(* screen-width 10) (i32 (.y (.target camera))) rl/green))
|
||||
|
||||
(rl/draw-line (i32 (.x (.target camera))) (* screen-height -10)
|
||||
(i32 (.x (.target camera))) (* screen-height 10) rl/green)
|
||||
(rl/draw-line (* screen-width -10) (i32 (.y (.target camera)))
|
||||
(* screen-width 10) (i32 (.y (.target camera))) rl/green)
|
||||
;; And everything after it is in screen space again — the frame drawn
|
||||
;; around the window is how the example shows the difference.
|
||||
(rl/draw-text "SCREEN AREA" 640 10 20 rl/red)
|
||||
|
||||
(rl/end-mode-2d)
|
||||
(rl/draw-rectangle 0 0 screen-width 5 rl/red)
|
||||
(rl/draw-rectangle 0 5 5 (- screen-height 10) rl/red)
|
||||
(rl/draw-rectangle (- screen-width 5) 5 5 (- screen-height 10) rl/red)
|
||||
(rl/draw-rectangle 0 (- screen-height 5) screen-width 5 rl/red)
|
||||
|
||||
;; And everything after it is in screen space again — the frame drawn
|
||||
;; around the window is how the example shows the difference.
|
||||
(rl/draw-text "SCREEN AREA" 640 10 20 rl/red)
|
||||
(rl/draw-rectangle 10 10 250 113 (rl/fade rl/skyblue 0.5))
|
||||
(rl/draw-rectangle-lines 10 10 250 113 rl/blue)
|
||||
|
||||
(rl/draw-rectangle 0 0 screen-width 5 rl/red)
|
||||
(rl/draw-rectangle 0 5 5 (- screen-height 10) rl/red)
|
||||
(rl/draw-rectangle (- screen-width 5) 5 5 (- screen-height 10) rl/red)
|
||||
(rl/draw-rectangle 0 (- screen-height 5) screen-width 5 rl/red)
|
||||
|
||||
(rl/draw-rectangle 10 10 250 113 (rl/fade rl/skyblue 0.5))
|
||||
(rl/draw-rectangle-lines 10 10 250 113 rl/blue)
|
||||
|
||||
(rl/draw-text "Free 2d camera controls:" 20 20 10 rl/black)
|
||||
(rl/draw-text "- Right/Left to move Offset" 40 40 10 rl/darkgray)
|
||||
(rl/draw-text "- Mouse Wheel to Zoom in-out" 40 60 10 rl/darkgray)
|
||||
(rl/draw-text "- A / S to Rotate" 40 80 10 rl/darkgray)
|
||||
(rl/draw-text "- R to reset Zoom and Rotation" 40 100 10 rl/darkgray)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-text "Free 2d camera controls:" 20 20 10 rl/black)
|
||||
(rl/draw-text "- Right/Left to move Offset" 40 40 10 rl/darkgray)
|
||||
(rl/draw-text "- Mouse Wheel to Zoom in-out" 40 60 10 rl/darkgray)
|
||||
(rl/draw-text "- A / S to Rotate" 40 80 10 rl/darkgray)
|
||||
(rl/draw-text "- R to reset Zoom and Rotation" 40 100 10 rl/darkgray))))
|
||||
|
||||
@ -113,46 +113,41 @@
|
||||
(set (.hit collision) false)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/begin-mode-3d camera)
|
||||
(rl/with-mode-3d camera
|
||||
(if (.hit collision)
|
||||
(do
|
||||
(rl/draw-cube cube-position (.x cube-size) (.y cube-size) (.z cube-size)
|
||||
rl/red)
|
||||
(rl/draw-cube-wires cube-position (.x cube-size) (.y cube-size)
|
||||
(.z cube-size) rl/maroon)
|
||||
;; A slightly larger wireframe around the selection, which is the
|
||||
;; whole visual feedback of the example.
|
||||
(rl/draw-cube-wires cube-position (+ (.x cube-size) 0.2)
|
||||
(+ (.y cube-size) 0.2) (+ (.z cube-size) 0.2)
|
||||
rl/green))
|
||||
(do
|
||||
(rl/draw-cube cube-position (.x cube-size) (.y cube-size) (.z cube-size)
|
||||
rl/gray)
|
||||
(rl/draw-cube-wires cube-position (.x cube-size) (.y cube-size)
|
||||
(.z cube-size) rl/darkgray)))
|
||||
|
||||
(if (.hit collision)
|
||||
(do
|
||||
(rl/draw-cube cube-position (.x cube-size) (.y cube-size) (.z cube-size)
|
||||
rl/red)
|
||||
(rl/draw-cube-wires cube-position (.x cube-size) (.y cube-size)
|
||||
(.z cube-size) rl/maroon)
|
||||
;; A slightly larger wireframe around the selection, which is the
|
||||
;; whole visual feedback of the example.
|
||||
(rl/draw-cube-wires cube-position (+ (.x cube-size) 0.2)
|
||||
(+ (.y cube-size) 0.2) (+ (.z cube-size) 0.2)
|
||||
rl/green))
|
||||
(do
|
||||
(rl/draw-cube cube-position (.x cube-size) (.y cube-size) (.z cube-size)
|
||||
rl/gray)
|
||||
(rl/draw-cube-wires cube-position (.x cube-size) (.y cube-size)
|
||||
(.z cube-size) rl/darkgray)))
|
||||
;; raylib draws the ray a thousand units long, so it reads as a line
|
||||
;; crossing the scene rather than as a segment with an end.
|
||||
(rl/draw-ray ray rl/maroon)
|
||||
(rl/draw-grid 10 1.0))
|
||||
|
||||
;; raylib draws the ray a thousand units long, so it reads as a line
|
||||
;; crossing the scene rather than as a segment with an end.
|
||||
(rl/draw-ray ray rl/maroon)
|
||||
(rl/draw-grid 10 1.0)
|
||||
(rl/draw-text "Try clicking on the box with your mouse!" 240 10 20
|
||||
rl/darkgray)
|
||||
|
||||
(rl/end-mode-3d)
|
||||
(when (.hit collision)
|
||||
(rl/draw-text "BOX SELECTED"
|
||||
(/ (- screen-width (rl/measure-text "BOX SELECTED" 30)) 2)
|
||||
(i32 (* (f32 screen-height) 0.1)) 30 rl/green))
|
||||
|
||||
(rl/draw-text "Try clicking on the box with your mouse!" 240 10 20
|
||||
rl/darkgray)
|
||||
(rl/draw-text "Right click mouse to toggle camera controls" 10 430 10
|
||||
rl/gray)
|
||||
|
||||
(when (.hit collision)
|
||||
(rl/draw-text "BOX SELECTED"
|
||||
(/ (- screen-width (rl/measure-text "BOX SELECTED" 30)) 2)
|
||||
(i32 (* (f32 screen-height) 0.1)) 30 rl/green))
|
||||
|
||||
(rl/draw-text "Right click mouse to toggle camera controls" 10 430 10
|
||||
rl/gray)
|
||||
|
||||
(rl/draw-fps 10 10)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-fps 10 10))))
|
||||
|
||||
@ -25,8 +25,7 @@
|
||||
(rl/set-target-fps 60)
|
||||
|
||||
(until (rl/window-should-close?)
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-text "Congrats! You created your first window!" 190 200 20
|
||||
rl/lightgray)
|
||||
(rl/end-drawing)))
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-text "Congrats! You created your first window!" 190 200 20
|
||||
rl/lightgray))))
|
||||
|
||||
@ -70,50 +70,48 @@
|
||||
(set (.x frame-circle) 0.0))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-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)
|
||||
(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)
|
||||
;; "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 "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))
|
||||
(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 "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)))
|
||||
(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))
|
||||
|
||||
;; 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 "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)))
|
||||
(rl/draw-text "FUNC: x += GetFrameTime()*speed" 10 110 20 rl/red)
|
||||
(rl/draw-text "FUNC: x += speed" 10 260 20 rl/blue))))
|
||||
|
||||
@ -183,98 +183,96 @@
|
||||
.width 75.0 .height 24.0})]
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(if (rl/gamepad-available? gamepad)
|
||||
(do
|
||||
;; The C draws `TextFormat("GP%d: %s", gamepad, GetGamepadName(...))`.
|
||||
;; The name is unbindable — see the header — so this is the index and
|
||||
;; the word the C would have followed it with.
|
||||
(rl/draw-text "GP" 10 10 10 rl/black)
|
||||
(let [x (+ 10 (rl/measure-text "GP" 10))]
|
||||
(rl/draw-text ": CONNECTED (name unbindable)"
|
||||
(+ x (d/draw-int gamepad x 10 10 rl/black))
|
||||
10 10 rl/black))
|
||||
(if (rl/gamepad-available? gamepad)
|
||||
(do
|
||||
;; The C draws `TextFormat("GP%d: %s", gamepad, GetGamepadName(...))`.
|
||||
;; The name is unbindable — see the header — so this is the index and
|
||||
;; the word the C would have followed it with.
|
||||
(rl/draw-text "GP" 10 10 10 rl/black)
|
||||
(let [x (+ 10 (rl/measure-text "GP" 10))]
|
||||
(rl/draw-text ": CONNECTED (name unbindable)"
|
||||
(+ x (d/draw-int gamepad x 10 10 rl/black))
|
||||
10 10 rl/black))
|
||||
|
||||
(let [lx (deadzone (rl/get-gamepad-axis-movement gamepad :left-x)
|
||||
stick-deadzone)
|
||||
ly (deadzone (rl/get-gamepad-axis-movement gamepad :left-y)
|
||||
stick-deadzone)
|
||||
rx (deadzone (rl/get-gamepad-axis-movement gamepad :right-x)
|
||||
stick-deadzone)
|
||||
ry (deadzone (rl/get-gamepad-axis-movement gamepad :right-y)
|
||||
stick-deadzone)
|
||||
lt (trigger-deadzoned
|
||||
(rl/get-gamepad-axis-movement gamepad :left-trigger))
|
||||
rt (trigger-deadzoned
|
||||
(rl/get-gamepad-axis-movement gamepad :right-trigger))]
|
||||
(let [lx (deadzone (rl/get-gamepad-axis-movement gamepad :left-x)
|
||||
stick-deadzone)
|
||||
ly (deadzone (rl/get-gamepad-axis-movement gamepad :left-y)
|
||||
stick-deadzone)
|
||||
rx (deadzone (rl/get-gamepad-axis-movement gamepad :right-x)
|
||||
stick-deadzone)
|
||||
ry (deadzone (rl/get-gamepad-axis-movement gamepad :right-y)
|
||||
stick-deadzone)
|
||||
lt (trigger-deadzoned
|
||||
(rl/get-gamepad-axis-movement gamepad :left-trigger))
|
||||
rt (trigger-deadzoned
|
||||
(rl/get-gamepad-axis-movement gamepad :right-trigger))]
|
||||
|
||||
(draw-pad-background)
|
||||
(draw-pad-buttons)
|
||||
(draw-pad-background)
|
||||
(draw-pad-buttons)
|
||||
|
||||
(draw-stick 345 260 lx ly
|
||||
(rl/gamepad-button-down? gamepad :left-thumb))
|
||||
(draw-stick 465 260 rx ry
|
||||
(rl/gamepad-button-down? gamepad :right-thumb))
|
||||
(draw-stick 345 260 lx ly
|
||||
(rl/gamepad-button-down? gamepad :left-thumb))
|
||||
(draw-stick 465 260 rx ry
|
||||
(rl/gamepad-button-down? gamepad :right-thumb))
|
||||
|
||||
;; The triggers as bars filling upward from a grey track. The +1
|
||||
;; and the halving turn raylib's [-1, 1] into [0, 1].
|
||||
(rl/draw-rectangle 151 110 15 70 rl/gray)
|
||||
(rl/draw-rectangle 644 110 15 70 rl/gray)
|
||||
(rl/draw-rectangle 151 110 15 (i32 (* (/ (+ 1.0 lt) 2.0) 70.0))
|
||||
rl/red)
|
||||
(rl/draw-rectangle 644 110 15 (i32 (* (/ (+ 1.0 rt) 2.0) 70.0))
|
||||
rl/red))
|
||||
;; The triggers as bars filling upward from a grey track. The +1
|
||||
;; and the halving turn raylib's [-1, 1] into [0, 1].
|
||||
(rl/draw-rectangle 151 110 15 70 rl/gray)
|
||||
(rl/draw-rectangle 644 110 15 70 rl/gray)
|
||||
(rl/draw-rectangle 151 110 15 (i32 (* (/ (+ 1.0 lt) 2.0) 70.0))
|
||||
rl/red)
|
||||
(rl/draw-rectangle 644 110 15 (i32 (* (/ (+ 1.0 rt) 2.0) 70.0))
|
||||
rl/red))
|
||||
|
||||
(rl/draw-text "DETECTED AXIS [" 10 50 10 rl/maroon)
|
||||
(let [x (+ 10 (rl/measure-text "DETECTED AXIS [" 10))]
|
||||
(rl/draw-text "]:" (+ x (d/draw-int axis-count x 50 10 rl/maroon))
|
||||
50 10 rl/maroon))
|
||||
(rl/draw-text "DETECTED AXIS [" 10 50 10 rl/maroon)
|
||||
(let [x (+ 10 (rl/measure-text "DETECTED AXIS [" 10))]
|
||||
(rl/draw-text "]:" (+ x (d/draw-int axis-count x 50 10 rl/maroon))
|
||||
50 10 rl/maroon))
|
||||
|
||||
(dotimes [i axis-count]
|
||||
(rl/draw-text "AXIS " 20 (+ 70 (* 20 i)) 10 rl/darkgray)
|
||||
(let [x (+ 20 (rl/measure-text "AXIS " 10))
|
||||
y (+ 70 (* 20 i))]
|
||||
(set x (+ x (d/draw-int i x y 10 rl/darkgray)))
|
||||
(rl/draw-text ": " x y 10 rl/darkgray)
|
||||
(set x (+ x (rl/measure-text ": " 10)))
|
||||
;; The raw reading, not the deadzoned one — the C shows the raw
|
||||
;; value here too, which is what makes the deadzone visible as a
|
||||
;; difference between this row and the stick.
|
||||
(d/draw-f32 (axis-at gamepad i) 2 x y 10
|
||||
rl/darkgray)))
|
||||
(dotimes [i axis-count]
|
||||
(rl/draw-text "AXIS " 20 (+ 70 (* 20 i)) 10 rl/darkgray)
|
||||
(let [x (+ 20 (rl/measure-text "AXIS " 10))
|
||||
y (+ 70 (* 20 i))]
|
||||
(set x (+ x (d/draw-int i x y 10 rl/darkgray)))
|
||||
(rl/draw-text ": " x y 10 rl/darkgray)
|
||||
(set x (+ x (rl/measure-text ": " 10)))
|
||||
;; The raw reading, not the deadzoned one — the C shows the raw
|
||||
;; value here too, which is what makes the deadzone visible as a
|
||||
;; difference between this row and the stick.
|
||||
(d/draw-f32 (axis-at gamepad i) 2 x y 10
|
||||
rl/darkgray)))
|
||||
|
||||
;; Drawn and inert. See the header: SetGamepadVibration is a stub in
|
||||
;; this raylib and is not bound.
|
||||
(rl/draw-rectangle-rec vibrate-rect rl/skyblue)
|
||||
(rl/draw-text "VIBRATE" (+ (i32 (.x vibrate-rect)) 14)
|
||||
(+ (i32 (.y vibrate-rect)) 1) 10 rl/darkgray)
|
||||
(rl/draw-text "(not bound: raylib stub)" 95
|
||||
(+ (i32 (.y vibrate-rect)) 7) 10 rl/gray)
|
||||
;; Drawn and inert. See the header: SetGamepadVibration is a stub in
|
||||
;; this raylib and is not bound.
|
||||
(rl/draw-rectangle-rec vibrate-rect rl/skyblue)
|
||||
(rl/draw-text "VIBRATE" (+ (i32 (.x vibrate-rect)) 14)
|
||||
(+ (i32 (.y vibrate-rect)) 1) 10 rl/darkgray)
|
||||
(rl/draw-text "(not bound: raylib stub)" 95
|
||||
(+ (i32 (.y vibrate-rect)) 7) 10 rl/gray)
|
||||
|
||||
;; -1 when nothing is pressed, which is why the binding answers an
|
||||
;; i32 and not a GamepadButton.
|
||||
;; draw-int answers the width it drew, so a branch that ends in one
|
||||
;; has type i32 while its sibling has type () and the `if` will not
|
||||
;; typecheck — "expected i32, found ()". Both arms end in a
|
||||
;; draw-text here, which is the tidy way out; where that is awkward a
|
||||
;; trailing `(do)` is the other.
|
||||
(let [b (rl/get-gamepad-button-pressed)]
|
||||
(if (>= b 0)
|
||||
(do (rl/draw-text "DETECTED BUTTON: " 10 430 10 rl/red)
|
||||
(d/draw-int b (+ 10 (rl/measure-text "DETECTED BUTTON: " 10))
|
||||
430 10 rl/red)
|
||||
(do))
|
||||
(rl/draw-text "DETECTED BUTTON: NONE" 10 430 10 rl/gray))))
|
||||
;; -1 when nothing is pressed, which is why the binding answers an
|
||||
;; i32 and not a GamepadButton.
|
||||
;; draw-int answers the width it drew, so a branch that ends in one
|
||||
;; has type i32 while its sibling has type () and the `if` will not
|
||||
;; typecheck — "expected i32, found ()". Both arms end in a
|
||||
;; draw-text here, which is the tidy way out; where that is awkward a
|
||||
;; trailing `(do)` is the other.
|
||||
(let [b (rl/get-gamepad-button-pressed)]
|
||||
(if (>= b 0)
|
||||
(do (rl/draw-text "DETECTED BUTTON: " 10 430 10 rl/red)
|
||||
(d/draw-int b (+ 10 (rl/measure-text "DETECTED BUTTON: " 10))
|
||||
430 10 rl/red)
|
||||
(do))
|
||||
(rl/draw-text "DETECTED BUTTON: NONE" 10 430 10 rl/gray))))
|
||||
|
||||
(do
|
||||
(rl/draw-text "GP" 10 10 10 rl/gray)
|
||||
(let [x (+ 10 (rl/measure-text "GP" 10))]
|
||||
(rl/draw-text ": NOT DETECTED"
|
||||
(+ x (d/draw-int gamepad x 10 10 rl/gray))
|
||||
10 10 rl/gray))
|
||||
(rl/draw-text "left/right arrows select another pad" 10 30 10
|
||||
rl/lightgray)))
|
||||
|
||||
(rl/end-drawing))))
|
||||
(do
|
||||
(rl/draw-text "GP" 10 10 10 rl/gray)
|
||||
(let [x (+ 10 (rl/measure-text "GP" 10))]
|
||||
(rl/draw-text ": NOT DETECTED"
|
||||
(+ x (d/draw-int gamepad x 10 10 rl/gray))
|
||||
10 10 rl/gray))
|
||||
(rl/draw-text "left/right arrows select another pad" 10 30 10
|
||||
rl/lightgray)))))))
|
||||
|
||||
@ -328,37 +328,35 @@
|
||||
(set (at touch-positions i) (rl/get-touch-position i)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/draw-text "*" 165 12 10 rl/black)
|
||||
(rl/draw-text "Example optimized for Web/HTML5\non Smartphones with Touch Screen."
|
||||
175 12 10 rl/black)
|
||||
(rl/draw-text "*" 165 42 10 rl/black)
|
||||
(rl/draw-text "While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation."
|
||||
175 42 10 rl/black)
|
||||
(rl/draw-text "*" 165 12 10 rl/black)
|
||||
(rl/draw-text "Example optimized for Web/HTML5\non Smartphones with Touch Screen."
|
||||
175 12 10 rl/black)
|
||||
(rl/draw-text "*" 165 42 10 rl/black)
|
||||
(rl/draw-text "While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation."
|
||||
175 42 10 rl/black)
|
||||
|
||||
(draw-last-gesture touch-count)
|
||||
(draw-log)
|
||||
(draw-protractor)
|
||||
(draw-last-gesture touch-count)
|
||||
(draw-log)
|
||||
(draw-protractor)
|
||||
|
||||
;; The pointer itself: every live touch, or the mouse when there is no
|
||||
;; touchscreen. The halo is the gesture colour faded, which is what
|
||||
;; `fade` was bound for.
|
||||
(unless (= g :none)
|
||||
(if (> touch-count 0)
|
||||
(do
|
||||
(dotimes [i touch-count]
|
||||
(let [p (at touch-positions i)]
|
||||
(rl/draw-circle-v p 50.0 (rl/fade gesture-color 0.5))
|
||||
(rl/draw-circle-v p 5.0 gesture-color)))
|
||||
;; Two fingers: the line between them, thinner while pinching
|
||||
;; out, which is the C's only use of the raw 512.
|
||||
(when (= touch-count 2)
|
||||
(rl/draw-line-ex (at touch-positions 0) (at touch-positions 1)
|
||||
(if (= g :pinch-out) 8.0 12.0) gesture-color)))
|
||||
(let [m (rl/get-mouse-position)]
|
||||
(rl/draw-circle-v m 35.0 (rl/fade gesture-color 0.5))
|
||||
(rl/draw-circle-v m 5.0 gesture-color))))
|
||||
|
||||
(rl/end-drawing)))))
|
||||
;; The pointer itself: every live touch, or the mouse when there is no
|
||||
;; touchscreen. The halo is the gesture colour faded, which is what
|
||||
;; `fade` was bound for.
|
||||
(unless (= g :none)
|
||||
(if (> touch-count 0)
|
||||
(do
|
||||
(dotimes [i touch-count]
|
||||
(let [p (at touch-positions i)]
|
||||
(rl/draw-circle-v p 50.0 (rl/fade gesture-color 0.5))
|
||||
(rl/draw-circle-v p 5.0 gesture-color)))
|
||||
;; Two fingers: the line between them, thinner while pinching
|
||||
;; out, which is the C's only use of the raw 512.
|
||||
(when (= touch-count 2)
|
||||
(rl/draw-line-ex (at touch-positions 0) (at touch-positions 1)
|
||||
(if (= g :pinch-out) 8.0 12.0) gesture-color)))
|
||||
(let [m (rl/get-mouse-position)]
|
||||
(rl/draw-circle-v m 35.0 (rl/fade gesture-color 0.5))
|
||||
(rl/draw-circle-v m 5.0 gesture-color)))))))))
|
||||
|
||||
@ -80,31 +80,29 @@
|
||||
(set gestures-count 0)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/draw-rectangle-rec touch-area rl/gray)
|
||||
(rl/draw-rectangle 225 15 (- screen-width 240) (- screen-height 30)
|
||||
rl/raywhite)
|
||||
(rl/draw-rectangle-rec touch-area rl/gray)
|
||||
(rl/draw-rectangle 225 15 (- screen-width 240) (- screen-height 30)
|
||||
rl/raywhite)
|
||||
|
||||
(rl/draw-text "GESTURES TEST AREA" (- screen-width 270)
|
||||
(- screen-height 40) 20 (rl/fade rl/gray 0.5))
|
||||
(rl/draw-text "GESTURES TEST AREA" (- screen-width 270)
|
||||
(- screen-height 40) 20 (rl/fade rl/gray 0.5))
|
||||
|
||||
(dotimes [i gestures-count]
|
||||
(if (= 0 (% i 2))
|
||||
(rl/draw-rectangle 10 (+ 30 (* 20 i)) 200 20
|
||||
(rl/fade rl/lightgray 0.5))
|
||||
(rl/draw-rectangle 10 (+ 30 (* 20 i)) 200 20
|
||||
(rl/fade rl/lightgray 0.3)))
|
||||
;; The newest entry in maroon and the rest in dark grey, as the C
|
||||
;; has it.
|
||||
(rl/draw-text (at gesture-log i) 35 (+ 36 (* 20 i)) 10
|
||||
(if (< i (- gestures-count 1)) rl/darkgray rl/maroon)))
|
||||
(dotimes [i gestures-count]
|
||||
(if (= 0 (% i 2))
|
||||
(rl/draw-rectangle 10 (+ 30 (* 20 i)) 200 20
|
||||
(rl/fade rl/lightgray 0.5))
|
||||
(rl/draw-rectangle 10 (+ 30 (* 20 i)) 200 20
|
||||
(rl/fade rl/lightgray 0.3)))
|
||||
;; The newest entry in maroon and the rest in dark grey, as the C
|
||||
;; has it.
|
||||
(rl/draw-text (at gesture-log i) 35 (+ 36 (* 20 i)) 10
|
||||
(if (< i (- gestures-count 1)) rl/darkgray rl/maroon)))
|
||||
|
||||
(rl/draw-rectangle-lines 10 29 200 (- screen-height 50) rl/gray)
|
||||
(rl/draw-text "DETECTED GESTURES" 50 15 10 rl/gray)
|
||||
(rl/draw-rectangle-lines 10 29 200 (- screen-height 50) rl/gray)
|
||||
(rl/draw-text "DETECTED GESTURES" 50 15 10 rl/gray)
|
||||
|
||||
(unless (= current-gesture :none)
|
||||
(rl/draw-circle-v touch 30.0 rl/maroon))
|
||||
|
||||
(rl/end-drawing)))))
|
||||
(unless (= current-gesture :none)
|
||||
(rl/draw-circle-v touch 30.0 rl/maroon)))))))
|
||||
|
||||
@ -40,8 +40,7 @@
|
||||
(when (rl/key-down? :down) (set (.y ball) (+ (.y ball) 2.0)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-text "move the ball with arrow keys" 10 10 20 rl/darkgray)
|
||||
(rl/draw-circle-v ball 50.0 rl/maroon)
|
||||
(rl/end-drawing)))
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-text "move the ball with arrow keys" 10 10 20 rl/darkgray)
|
||||
(rl/draw-circle-v ball 50.0 rl/maroon))))
|
||||
|
||||
@ -42,14 +42,13 @@
|
||||
(set box-y (- box-y (i32 (* (rl/get-mouse-wheel-move) (f32 scroll-speed)))))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-rectangle (- (/ screen-width 2) 40) box-y 80 80 rl/maroon)
|
||||
(rl/draw-text "Use mouse wheel to move the cube up and down!" 10 10 20
|
||||
rl/gray)
|
||||
;; The two halves of the C's one TextFormat call: the literal, measured,
|
||||
;; and then the number starting where it ended.
|
||||
(rl/draw-text "Box position Y: " 10 40 20 rl/lightgray)
|
||||
(d/draw-int-padded box-y 3 (+ 10 (rl/measure-text "Box position Y: " 20))
|
||||
40 20 rl/lightgray)
|
||||
(rl/end-drawing)))
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-rectangle (- (/ screen-width 2) 40) box-y 80 80 rl/maroon)
|
||||
(rl/draw-text "Use mouse wheel to move the cube up and down!" 10 10 20
|
||||
rl/gray)
|
||||
;; The two halves of the C's one TextFormat call: the literal, measured,
|
||||
;; and then the number starting where it ended.
|
||||
(rl/draw-text "Box position Y: " 10 40 20 rl/lightgray)
|
||||
(d/draw-int-padded box-y 3 (+ 10 (rl/measure-text "Box position Y: " 20))
|
||||
40 20 rl/lightgray))))
|
||||
|
||||
@ -49,13 +49,12 @@
|
||||
:else ball-color))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-circle-v ball 40.0 ball-color)
|
||||
(rl/draw-text "move ball with mouse and click mouse button to change color"
|
||||
10 10 20 rl/darkgray)
|
||||
(rl/draw-text "Press 'H' to toggle cursor visibility" 10 30 20 rl/darkgray)
|
||||
(if (rl/cursor-hidden?)
|
||||
(rl/draw-text "CURSOR HIDDEN" 20 60 20 rl/red)
|
||||
(rl/draw-text "CURSOR VISIBLE" 20 60 20 rl/lime))
|
||||
(rl/end-drawing))))
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/draw-circle-v ball 40.0 ball-color)
|
||||
(rl/draw-text "move ball with mouse and click mouse button to change color"
|
||||
10 10 20 rl/darkgray)
|
||||
(rl/draw-text "Press 'H' to toggle cursor visibility" 10 30 20 rl/darkgray)
|
||||
(if (rl/cursor-hidden?)
|
||||
(rl/draw-text "CURSOR HIDDEN" 20 60 20 rl/red)
|
||||
(rl/draw-text "CURSOR VISIBLE" 20 60 20 rl/lime))))))
|
||||
|
||||
@ -45,26 +45,24 @@
|
||||
(set (at touch-positions i) (rl/get-touch-position i)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(dotimes [i count]
|
||||
(let [p (at touch-positions i)]
|
||||
;; raylib reports (0,0) for a slot that is not being touched, so the
|
||||
;; C filters on it and so does this. It means a real touch in the
|
||||
;; very top-left corner is dropped; that is raylib's ambiguity, not
|
||||
;; something the port introduced.
|
||||
(when (and (> (.x p) 0.0) (> (.y p) 0.0))
|
||||
(rl/draw-circle-v p 34.0 rl/orange)
|
||||
;; The C's TextFormat("%d", i). This used to need examples/digits.flan
|
||||
;; and a table of one-character strings; (string b) makes the
|
||||
;; number a string with no instructions, so it is one draw-text and
|
||||
;; this file imports nothing but raylib.
|
||||
(rl/draw-text (string (i64->bytes (i64 i)))
|
||||
(- (i32 (.x p)) 10) (- (i32 (.y p)) 70) 40
|
||||
rl/black))))
|
||||
(dotimes [i count]
|
||||
(let [p (at touch-positions i)]
|
||||
;; raylib reports (0,0) for a slot that is not being touched, so the
|
||||
;; C filters on it and so does this. It means a real touch in the
|
||||
;; very top-left corner is dropped; that is raylib's ambiguity, not
|
||||
;; something the port introduced.
|
||||
(when (and (> (.x p) 0.0) (> (.y p) 0.0))
|
||||
(rl/draw-circle-v p 34.0 rl/orange)
|
||||
;; The C's TextFormat("%d", i). This used to need examples/digits.flan
|
||||
;; and a table of one-character strings; (string b) makes the
|
||||
;; number a string with no instructions, so it is one draw-text and
|
||||
;; this file imports nothing but raylib.
|
||||
(rl/draw-text (string (i64->bytes (i64 i)))
|
||||
(- (i32 (.x p)) 10) (- (i32 (.y p)) 70) 40
|
||||
rl/black))))
|
||||
|
||||
(rl/draw-text "touch the screen at multiple locations to get multiple balls"
|
||||
10 10 20 rl/darkgray)
|
||||
|
||||
(rl/end-drawing))))
|
||||
(rl/draw-text "touch the screen at multiple locations to get multiple balls"
|
||||
10 10 20 rl/darkgray)))))
|
||||
|
||||
@ -172,24 +172,22 @@
|
||||
(move-player pressed (rl/get-frame-time))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/draw-circle-v player 50.0 rl/maroon)
|
||||
(rl/draw-circle-v player 50.0 rl/maroon)
|
||||
|
||||
(dotimes [i button-max]
|
||||
(rl/draw-circle-v (at button-positions i) button-radius
|
||||
(if (= i pressed) rl/darkgray rl/black))
|
||||
(let [t (at arrow-tris i)]
|
||||
(rl/draw-triangle (at t 0) (at t 1) (at t 2)
|
||||
(at label-colors i))))
|
||||
(dotimes [i button-max]
|
||||
(rl/draw-circle-v (at button-positions i) button-radius
|
||||
(if (= i pressed) rl/darkgray rl/black))
|
||||
(let [t (at arrow-tris i)]
|
||||
(rl/draw-triangle (at t 0) (at t 1) (at t 2)
|
||||
(at label-colors i))))
|
||||
|
||||
(rl/draw-text "move the player with D-Pad buttons" 10 10 20 rl/darkgray)
|
||||
;; Not in the C: which button the search picked, as a number, so the
|
||||
;; headless case and the window agree about the same thing.
|
||||
(rl/draw-text "button: " 10 34 20 rl/lightgray)
|
||||
(rl/draw-text (string (i64->bytes (i64 pressed)))
|
||||
(+ 10 (rl/measure-text "button: " 20)) 34 20
|
||||
rl/lightgray)
|
||||
|
||||
(rl/end-drawing))))
|
||||
(rl/draw-text "move the player with D-Pad buttons" 10 10 20 rl/darkgray)
|
||||
;; Not in the C: which button the search picked, as a number, so the
|
||||
;; headless case and the window agree about the same thing.
|
||||
(rl/draw-text "button: " 10 34 20 rl/lightgray)
|
||||
(rl/draw-text (string (i64->bytes (i64 pressed)))
|
||||
(+ 10 (rl/measure-text "button: " 20)) 34 20
|
||||
rl/lightgray)))))
|
||||
|
||||
@ -51,22 +51,20 @@
|
||||
(set (.y scissor) (- (f32 (rl/get-mouse-y)) (/ (.height scissor) 2.0)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(when scissor-mode
|
||||
(rl/begin-scissor-mode (i32 (.x scissor)) (i32 (.y scissor))
|
||||
(i32 (.width scissor)) (i32 (.height scissor))))
|
||||
(when scissor-mode
|
||||
(rl/begin-scissor-mode (i32 (.x scissor)) (i32 (.y scissor))
|
||||
(i32 (.width scissor)) (i32 (.height scissor))))
|
||||
|
||||
;; A full-screen rectangle and a line of text. Only the part inside the
|
||||
;; scissor rectangle reaches the framebuffer, which is the whole example.
|
||||
(rl/draw-rectangle 0 0 (rl/get-screen-width) (rl/get-screen-height) rl/red)
|
||||
(rl/draw-text "Move the mouse around to reveal this text!" 190 200 20
|
||||
rl/lightgray)
|
||||
;; A full-screen rectangle and a line of text. Only the part inside the
|
||||
;; scissor rectangle reaches the framebuffer, which is the whole example.
|
||||
(rl/draw-rectangle 0 0 (rl/get-screen-width) (rl/get-screen-height) rl/red)
|
||||
(rl/draw-text "Move the mouse around to reveal this text!" 190 200 20
|
||||
rl/lightgray)
|
||||
|
||||
(when scissor-mode (rl/end-scissor-mode))
|
||||
(when scissor-mode (rl/end-scissor-mode))
|
||||
|
||||
(rl/draw-rectangle-lines-ex scissor 1.0 rl/black)
|
||||
(rl/draw-text "Press S to toggle scissor test" 10 10 20 rl/black)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-rectangle-lines-ex scissor 1.0 rl/black)
|
||||
(rl/draw-text "Press S to toggle scissor test" 10 10 20 rl/black))))
|
||||
|
||||
@ -127,53 +127,51 @@
|
||||
(set (.y ball-speed) (* (.y ball-speed) -1.0)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/with-drawing
|
||||
|
||||
;; A transparent framebuffer wants a transparent clear; anything else
|
||||
;; paints over the desktop the flag exists to show.
|
||||
(if (rl/window-state? rl/flag-window-transparent)
|
||||
(rl/clear-background rl/blank)
|
||||
(rl/clear-background rl/raywhite))
|
||||
;; A transparent framebuffer wants a transparent clear; anything else
|
||||
;; paints over the desktop the flag exists to show.
|
||||
(if (rl/window-state? rl/flag-window-transparent)
|
||||
(rl/clear-background rl/blank)
|
||||
(rl/clear-background rl/raywhite))
|
||||
|
||||
(rl/draw-circle-v ball-pos ball-radius rl/maroon)
|
||||
(rl/draw-rectangle-lines-ex
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (rl/get-screen-width))
|
||||
.height (f32 (rl/get-screen-height))})
|
||||
4.0 rl/raywhite)
|
||||
(rl/draw-circle-v ball-pos ball-radius rl/maroon)
|
||||
(rl/draw-rectangle-lines-ex
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (rl/get-screen-width))
|
||||
.height (f32 (rl/get-screen-height))})
|
||||
4.0 rl/raywhite)
|
||||
|
||||
(rl/draw-circle-v (rl/get-mouse-position) 10.0 rl/darkblue)
|
||||
(rl/draw-circle-v (rl/get-mouse-position) 10.0 rl/darkblue)
|
||||
|
||||
(rl/draw-fps 10 10)
|
||||
(rl/draw-fps 10 10)
|
||||
|
||||
;; The C's TextFormat("Screen Size: [%i, %i]", ...), reassembled out of
|
||||
;; literals and examples/digits.flan the way the other ports do it: `x`
|
||||
;; walks along the line, and draw-int hands back the width it drew.
|
||||
(let [x 10]
|
||||
(rl/draw-text "Screen Size: [" x 40 10 rl/green)
|
||||
(set x (+ x (rl/measure-text "Screen Size: [" 10)))
|
||||
(set x (+ x (d/draw-int (rl/get-screen-width) x 40 10 rl/green)))
|
||||
(rl/draw-text ", " x 40 10 rl/green)
|
||||
(set x (+ x (rl/measure-text ", " 10)))
|
||||
(set x (+ x (d/draw-int (rl/get-screen-height) x 40 10 rl/green)))
|
||||
(rl/draw-text "]" x 40 10 rl/green))
|
||||
(rl/draw-text "Following flags can be set after window creation:"
|
||||
10 60 10 rl/gray)
|
||||
(draw-flag "[F] FLAG_FULLSCREEN_MODE:" rl/flag-fullscreen-mode 80)
|
||||
(draw-flag "[R] FLAG_WINDOW_RESIZABLE:" rl/flag-window-resizable 100)
|
||||
(draw-flag "[D] FLAG_WINDOW_UNDECORATED:" rl/flag-window-undecorated 120)
|
||||
(draw-flag "[H] FLAG_WINDOW_HIDDEN:" rl/flag-window-hidden 140)
|
||||
(draw-flag "[N] FLAG_WINDOW_MINIMIZED:" rl/flag-window-minimized 160)
|
||||
(draw-flag "[M] FLAG_WINDOW_MAXIMIZED:" rl/flag-window-maximized 180)
|
||||
(draw-flag "[U] FLAG_WINDOW_UNFOCUSED:" rl/flag-window-unfocused 200)
|
||||
(draw-flag "[T] FLAG_WINDOW_TOPMOST:" rl/flag-window-topmost 220)
|
||||
(draw-flag "[A] FLAG_WINDOW_ALWAYS_RUN:" rl/flag-window-always-run 240)
|
||||
(draw-flag "[V] FLAG_VSYNC_HINT:" rl/flag-vsync-hint 260)
|
||||
;; The C's TextFormat("Screen Size: [%i, %i]", ...), reassembled out of
|
||||
;; literals and examples/digits.flan the way the other ports do it: `x`
|
||||
;; walks along the line, and draw-int hands back the width it drew.
|
||||
(let [x 10]
|
||||
(rl/draw-text "Screen Size: [" x 40 10 rl/green)
|
||||
(set x (+ x (rl/measure-text "Screen Size: [" 10)))
|
||||
(set x (+ x (d/draw-int (rl/get-screen-width) x 40 10 rl/green)))
|
||||
(rl/draw-text ", " x 40 10 rl/green)
|
||||
(set x (+ x (rl/measure-text ", " 10)))
|
||||
(set x (+ x (d/draw-int (rl/get-screen-height) x 40 10 rl/green)))
|
||||
(rl/draw-text "]" x 40 10 rl/green))
|
||||
(rl/draw-text "Following flags can be set after window creation:"
|
||||
10 60 10 rl/gray)
|
||||
(draw-flag "[F] FLAG_FULLSCREEN_MODE:" rl/flag-fullscreen-mode 80)
|
||||
(draw-flag "[R] FLAG_WINDOW_RESIZABLE:" rl/flag-window-resizable 100)
|
||||
(draw-flag "[D] FLAG_WINDOW_UNDECORATED:" rl/flag-window-undecorated 120)
|
||||
(draw-flag "[H] FLAG_WINDOW_HIDDEN:" rl/flag-window-hidden 140)
|
||||
(draw-flag "[N] FLAG_WINDOW_MINIMIZED:" rl/flag-window-minimized 160)
|
||||
(draw-flag "[M] FLAG_WINDOW_MAXIMIZED:" rl/flag-window-maximized 180)
|
||||
(draw-flag "[U] FLAG_WINDOW_UNFOCUSED:" rl/flag-window-unfocused 200)
|
||||
(draw-flag "[T] FLAG_WINDOW_TOPMOST:" rl/flag-window-topmost 220)
|
||||
(draw-flag "[A] FLAG_WINDOW_ALWAYS_RUN:" rl/flag-window-always-run 240)
|
||||
(draw-flag "[V] FLAG_VSYNC_HINT:" rl/flag-vsync-hint 260)
|
||||
|
||||
(rl/draw-text "Following flags can only be set before window creation:"
|
||||
10 300 10 rl/gray)
|
||||
(draw-flag "FLAG_WINDOW_HIGHDPI:" rl/flag-window-highdpi 320)
|
||||
(draw-flag "FLAG_WINDOW_TRANSPARENT:" rl/flag-window-transparent 340)
|
||||
(draw-flag "FLAG_MSAA_4X_HINT:" rl/flag-msaa-4x-hint 360)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-text "Following flags can only be set before window creation:"
|
||||
10 300 10 rl/gray)
|
||||
(draw-flag "FLAG_WINDOW_HIGHDPI:" rl/flag-window-highdpi 320)
|
||||
(draw-flag "FLAG_WINDOW_TRANSPARENT:" rl/flag-window-transparent 340)
|
||||
(draw-flag "FLAG_MSAA_4X_HINT:" rl/flag-msaa-4x-hint 360))))
|
||||
|
||||
@ -54,15 +54,13 @@
|
||||
(when (rl/key-pressed? :n) (set exit-requested false))))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(if exit-requested
|
||||
(do
|
||||
(rl/draw-rectangle 0 100 screen-width 200 rl/black)
|
||||
(rl/draw-text "Are you sure you want to exit program? [Y/N]" 40 180 30
|
||||
rl/white))
|
||||
(rl/draw-text "Try to close the window to get confirmation message!"
|
||||
120 200 20 rl/lightgray))
|
||||
|
||||
(rl/end-drawing)))
|
||||
(if exit-requested
|
||||
(do
|
||||
(rl/draw-rectangle 0 100 screen-width 200 rl/black)
|
||||
(rl/draw-text "Are you sure you want to exit program? [Y/N]" 40 180 30
|
||||
rl/white))
|
||||
(rl/draw-text "Try to close the window to get confirmation message!"
|
||||
120 200 20 rl/lightgray)))))
|
||||
|
||||
@ -80,35 +80,32 @@
|
||||
camera)]
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/begin-mode-3d camera)
|
||||
(rl/draw-cube cube 2.0 2.0 2.0 rl/red)
|
||||
(rl/draw-cube-wires cube 2.0 2.0 2.0 rl/maroon)
|
||||
(rl/draw-grid 10 1.0)
|
||||
(rl/end-mode-3d)
|
||||
(rl/with-mode-3d camera
|
||||
(rl/draw-cube cube 2.0 2.0 2.0 rl/red)
|
||||
(rl/draw-cube-wires cube 2.0 2.0 2.0 rl/maroon)
|
||||
(rl/draw-grid 10 1.0))
|
||||
|
||||
;; And the 2D half, drawn after end-mode-3d and therefore on top of the
|
||||
;; cube whatever the depth buffer says — which is the second half of
|
||||
;; what the example demonstrates.
|
||||
(rl/draw-text "Enemy: 100 / 100"
|
||||
(- (i32 (.x label-pos))
|
||||
(/ (rl/measure-text "Enemy: 100/100" 20) 2))
|
||||
(i32 (.y label-pos)) 20 rl/black)
|
||||
;; And the 2D half, drawn after end-mode-3d and therefore on top of the
|
||||
;; cube whatever the depth buffer says — which is the second half of
|
||||
;; what the example demonstrates.
|
||||
(rl/draw-text "Enemy: 100 / 100"
|
||||
(- (i32 (.x label-pos))
|
||||
(/ (rl/measure-text "Enemy: 100/100" 20) 2))
|
||||
(i32 (.y label-pos)) 20 rl/black)
|
||||
|
||||
(let [x 10]
|
||||
(rl/draw-text "Cube position in screen space coordinates: [" x 10 20
|
||||
rl/lime)
|
||||
(set x (+ x (rl/measure-text
|
||||
"Cube position in screen space coordinates: [" 20)))
|
||||
(set x (+ x (d/draw-int (i32 (.x label-pos)) x 10 20 rl/lime)))
|
||||
(rl/draw-text ", " x 10 20 rl/lime)
|
||||
(set x (+ x (rl/measure-text ", " 20)))
|
||||
(set x (+ x (d/draw-int (i32 (.y label-pos)) x 10 20 rl/lime)))
|
||||
(rl/draw-text "]" x 10 20 rl/lime))
|
||||
(let [x 10]
|
||||
(rl/draw-text "Cube position in screen space coordinates: [" x 10 20
|
||||
rl/lime)
|
||||
(set x (+ x (rl/measure-text
|
||||
"Cube position in screen space coordinates: [" 20)))
|
||||
(set x (+ x (d/draw-int (i32 (.x label-pos)) x 10 20 rl/lime)))
|
||||
(rl/draw-text ", " x 10 20 rl/lime)
|
||||
(set x (+ x (rl/measure-text ", " 20)))
|
||||
(set x (+ x (d/draw-int (i32 (.y label-pos)) x 10 20 rl/lime)))
|
||||
(rl/draw-text "]" x 10 20 rl/lime))
|
||||
|
||||
(rl/draw-text "Text 2d should be always on top of the cube" 10 40 20
|
||||
rl/gray)
|
||||
|
||||
(rl/end-drawing))))
|
||||
(rl/draw-text "Text 2d should be always on top of the cube" 10 40 20
|
||||
rl/gray)))))
|
||||
|
||||
@ -106,29 +106,24 @@
|
||||
(set player-color (if hit rl/red rl/green)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/begin-mode-3d camera)
|
||||
(rl/with-mode-3d camera
|
||||
(rl/draw-cube enemy-box-pos (.x enemy-box-size) (.y enemy-box-size)
|
||||
(.z enemy-box-size) rl/gray)
|
||||
(rl/draw-cube-wires enemy-box-pos (.x enemy-box-size) (.y enemy-box-size)
|
||||
(.z enemy-box-size) rl/darkgray)
|
||||
|
||||
(rl/draw-cube enemy-box-pos (.x enemy-box-size) (.y enemy-box-size)
|
||||
(.z enemy-box-size) rl/gray)
|
||||
(rl/draw-cube-wires enemy-box-pos (.x enemy-box-size) (.y enemy-box-size)
|
||||
(.z enemy-box-size) rl/darkgray)
|
||||
;; draw-sphere is draw-sphere-ex at 16 rings and 16 slices; the wires form
|
||||
;; takes them because the tessellation is only visible in the wireframe.
|
||||
(rl/draw-sphere enemy-sphere-pos enemy-sphere-size rl/gray)
|
||||
(rl/draw-sphere-wires enemy-sphere-pos enemy-sphere-size 16 16 rl/darkgray)
|
||||
|
||||
;; draw-sphere is draw-sphere-ex at 16 rings and 16 slices; the wires form
|
||||
;; takes them because the tessellation is only visible in the wireframe.
|
||||
(rl/draw-sphere enemy-sphere-pos enemy-sphere-size rl/gray)
|
||||
(rl/draw-sphere-wires enemy-sphere-pos enemy-sphere-size 16 16 rl/darkgray)
|
||||
(rl/draw-cube-v player-position player-size player-color)
|
||||
|
||||
(rl/draw-cube-v player-position player-size player-color)
|
||||
(rl/draw-grid 10 1.0))
|
||||
|
||||
(rl/draw-grid 10 1.0)
|
||||
(rl/draw-text "Move player with arrow keys to collide" 220 40 20 rl/gray)
|
||||
|
||||
(rl/end-mode-3d)
|
||||
|
||||
(rl/draw-text "Move player with arrow keys to collide" 220 40 20 rl/gray)
|
||||
|
||||
(rl/draw-fps 10 10)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-fps 10 10))))
|
||||
|
||||
@ -54,49 +54,47 @@
|
||||
(set rotation (+ rotation 0.2))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/draw-text "some basic shapes available on raylib" 20 20 20 rl/darkgray)
|
||||
(rl/draw-text "some basic shapes available on raylib" 20 20 20 rl/darkgray)
|
||||
|
||||
;; Circles. The gradient one takes an inner and an outer colour and is the
|
||||
;; first call in the corpus to pass two Colors at once.
|
||||
(rl/draw-circle col-left 120 35.0 rl/darkblue)
|
||||
(rl/draw-circle-gradient col-left 220 60.0 rl/green rl/skyblue)
|
||||
(rl/draw-circle-lines col-left 340 80.0 rl/darkblue)
|
||||
;; Circles. The gradient one takes an inner and an outer colour and is the
|
||||
;; first call in the corpus to pass two Colors at once.
|
||||
(rl/draw-circle col-left 120 35.0 rl/darkblue)
|
||||
(rl/draw-circle-gradient col-left 220 60.0 rl/green rl/skyblue)
|
||||
(rl/draw-circle-lines col-left 340 80.0 rl/darkblue)
|
||||
|
||||
;; Rectangles. draw-rectangle-gradient-h runs the colour left to right;
|
||||
;; the -v form runs it top to bottom and the -ex form takes all four
|
||||
;; corners. The C uses the horizontal one here.
|
||||
(rl/draw-rectangle (- col-mid 60) 100 120 60 rl/red)
|
||||
(rl/draw-rectangle-gradient-h (- col-mid 90) 170 180 130 rl/maroon rl/gold)
|
||||
;; raylib draws this with quads internally rather than with lines, which
|
||||
;; is why its thickness does not follow the line width anywhere.
|
||||
(rl/draw-rectangle-lines (- col-mid 40) 320 80 60 rl/orange)
|
||||
;; Rectangles. draw-rectangle-gradient-h runs the colour left to right;
|
||||
;; the -v form runs it top to bottom and the -ex form takes all four
|
||||
;; corners. The C uses the horizontal one here.
|
||||
(rl/draw-rectangle (- col-mid 60) 100 120 60 rl/red)
|
||||
(rl/draw-rectangle-gradient-h (- col-mid 90) 170 180 130 rl/maroon rl/gold)
|
||||
;; raylib draws this with quads internally rather than with lines, which
|
||||
;; is why its thickness does not follow the line width anywhere.
|
||||
(rl/draw-rectangle-lines (- col-mid 40) 320 80 60 rl/orange)
|
||||
|
||||
;; Triangles. raylib wants the three vertices in counter-clockwise order
|
||||
;; and draws nothing at all for a clockwise one, so the order here is not
|
||||
;; cosmetic.
|
||||
(rl/draw-triangle (rl/Vector2 {.x 600.0 .y 80.0})
|
||||
(rl/Vector2 {.x 540.0 .y 150.0})
|
||||
(rl/Vector2 {.x 660.0 .y 150.0})
|
||||
rl/violet)
|
||||
;; Triangles. raylib wants the three vertices in counter-clockwise order
|
||||
;; and draws nothing at all for a clockwise one, so the order here is not
|
||||
;; cosmetic.
|
||||
(rl/draw-triangle (rl/Vector2 {.x 600.0 .y 80.0})
|
||||
(rl/Vector2 {.x 540.0 .y 150.0})
|
||||
(rl/Vector2 {.x 660.0 .y 150.0})
|
||||
rl/violet)
|
||||
|
||||
(rl/draw-triangle-lines (rl/Vector2 {.x 600.0 .y 160.0})
|
||||
(rl/Vector2 {.x 580.0 .y 230.0})
|
||||
(rl/Vector2 {.x 620.0 .y 230.0})
|
||||
rl/darkblue)
|
||||
(rl/draw-triangle-lines (rl/Vector2 {.x 600.0 .y 160.0})
|
||||
(rl/Vector2 {.x 580.0 .y 230.0})
|
||||
(rl/Vector2 {.x 620.0 .y 230.0})
|
||||
rl/darkblue)
|
||||
|
||||
;; Polygons, all three at the same centre and the same rotation, at three
|
||||
;; radii, so the filled hexagon sits inside the two outlines.
|
||||
(let [centre (rl/Vector2 {.x (f32 col-right) .y 330.0})]
|
||||
(rl/draw-poly centre 6 80.0 rotation rl/brown)
|
||||
(rl/draw-poly-lines centre 6 90.0 rotation rl/brown)
|
||||
(rl/draw-poly-lines-ex centre 6 85.0 rotation 6.0 rl/beige))
|
||||
;; Polygons, all three at the same centre and the same rotation, at three
|
||||
;; radii, so the filled hexagon sits inside the two outlines.
|
||||
(let [centre (rl/Vector2 {.x (f32 col-right) .y 330.0})]
|
||||
(rl/draw-poly centre 6 80.0 rotation rl/brown)
|
||||
(rl/draw-poly-lines centre 6 90.0 rotation rl/brown)
|
||||
(rl/draw-poly-lines-ex centre 6 85.0 rotation 6.0 rl/beige))
|
||||
|
||||
;; The C draws every LINES-based shape together so raylib can batch them
|
||||
;; into one pass. This last line is part of that comment and not an
|
||||
;; afterthought, so it stays where the C has it.
|
||||
(rl/draw-line 18 42 (- screen-width 18) 42 rl/black)
|
||||
|
||||
(rl/end-drawing)))
|
||||
;; The C draws every LINES-based shape together so raylib can batch them
|
||||
;; into one pass. This last line is part of that comment and not an
|
||||
;; afterthought, so it stays where the C has it.
|
||||
(rl/draw-line 18 42 (- screen-width 18) 42 rl/black))))
|
||||
|
||||
@ -93,37 +93,35 @@
|
||||
(when (rl/key-pressed? :space) (set paused (not paused)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/draw-rectangle 0 0 screen-width screen-upper-limit
|
||||
(if collision rl/red rl/black))
|
||||
(rl/draw-rectangle 0 0 screen-width screen-upper-limit
|
||||
(if collision rl/red rl/black))
|
||||
|
||||
(rl/draw-rectangle-rec box-a rl/gold)
|
||||
(rl/draw-rectangle-rec box-b rl/blue)
|
||||
(rl/draw-rectangle-rec box-a rl/gold)
|
||||
(rl/draw-rectangle-rec box-b rl/blue)
|
||||
|
||||
(when collision
|
||||
;; The overlap itself, drawn over both boxes. This patch landing
|
||||
;; anywhere other than where the gold and the blue cross is what a
|
||||
;; permuted Rectangle would look like.
|
||||
(rl/draw-rectangle-rec box-collision rl/lime)
|
||||
(when collision
|
||||
;; The overlap itself, drawn over both boxes. This patch landing
|
||||
;; anywhere other than where the gold and the blue cross is what a
|
||||
;; permuted Rectangle would look like.
|
||||
(rl/draw-rectangle-rec box-collision rl/lime)
|
||||
|
||||
(rl/draw-text "COLLISION!"
|
||||
(- (/ (rl/get-screen-width) 2)
|
||||
(/ (rl/measure-text "COLLISION!" 20) 2))
|
||||
(- (/ screen-upper-limit 2) 10) 20 rl/black)
|
||||
(rl/draw-text "COLLISION!"
|
||||
(- (/ (rl/get-screen-width) 2)
|
||||
(/ (rl/measure-text "COLLISION!" 20) 2))
|
||||
(- (/ screen-upper-limit 2) 10) 20 rl/black)
|
||||
|
||||
;; The C's TextFormat("Collision Area: %i", ...). Both dimensions are
|
||||
;; truncated to int before multiplying, as the C's two casts do.
|
||||
(let [x (- (/ (rl/get-screen-width) 2) 100)
|
||||
y (+ screen-upper-limit 10)]
|
||||
(set x (+ x (d/draw-piece "Collision Area: " x y 20 rl/black)))
|
||||
(d/draw-int (* (i32 (.width box-collision)) (i32 (.height box-collision)))
|
||||
x y 20 rl/black)))
|
||||
;; The C's TextFormat("Collision Area: %i", ...). Both dimensions are
|
||||
;; truncated to int before multiplying, as the C's two casts do.
|
||||
(let [x (- (/ (rl/get-screen-width) 2) 100)
|
||||
y (+ screen-upper-limit 10)]
|
||||
(set x (+ x (d/draw-piece "Collision Area: " x y 20 rl/black)))
|
||||
(d/draw-int (* (i32 (.width box-collision)) (i32 (.height box-collision)))
|
||||
x y 20 rl/black)))
|
||||
|
||||
(rl/draw-text "Press SPACE to PAUSE/RESUME" 20 (- screen-height 35) 20
|
||||
rl/lightgray)
|
||||
(rl/draw-text "Press SPACE to PAUSE/RESUME" 20 (- screen-height 35) 20
|
||||
rl/lightgray)
|
||||
|
||||
(rl/draw-fps 10 10)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-fps 10 10))))
|
||||
|
||||
@ -95,18 +95,16 @@
|
||||
(set iris-right (track mouse sclera-right)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
;; White of the eye, iris, pupil — in that order, each over the last.
|
||||
(rl/draw-circle-v sclera-left sclera-radius rl/lightgray)
|
||||
(rl/draw-circle-v iris-left iris-radius rl/brown)
|
||||
(rl/draw-circle-v iris-left 10.0 rl/black)
|
||||
;; White of the eye, iris, pupil — in that order, each over the last.
|
||||
(rl/draw-circle-v sclera-left sclera-radius rl/lightgray)
|
||||
(rl/draw-circle-v iris-left iris-radius rl/brown)
|
||||
(rl/draw-circle-v iris-left 10.0 rl/black)
|
||||
|
||||
(rl/draw-circle-v sclera-right sclera-radius rl/lightgray)
|
||||
(rl/draw-circle-v iris-right iris-radius rl/darkgreen)
|
||||
(rl/draw-circle-v iris-right 10.0 rl/black)
|
||||
(rl/draw-circle-v sclera-right sclera-radius rl/lightgray)
|
||||
(rl/draw-circle-v iris-right iris-radius rl/darkgreen)
|
||||
(rl/draw-circle-v iris-right 10.0 rl/black)
|
||||
|
||||
(rl/draw-fps 10 10)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-fps 10 10))))
|
||||
|
||||
@ -112,40 +112,38 @@
|
||||
(set frames-counter 0))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/draw-text "PLACE MOUSE OVER INPUT BOX!" 240 140 20 rl/gray)
|
||||
(rl/draw-text "PLACE MOUSE OVER INPUT BOX!" 240 140 20 rl/gray)
|
||||
|
||||
(rl/draw-rectangle-rec text-box rl/lightgray)
|
||||
(rl/draw-rectangle-lines (i32 (.x text-box)) (i32 (.y text-box))
|
||||
(i32 (.width text-box)) (i32 (.height text-box))
|
||||
(if mouse-on-text rl/red rl/darkgray))
|
||||
(rl/draw-rectangle-rec text-box rl/lightgray)
|
||||
(rl/draw-rectangle-lines (i32 (.x text-box)) (i32 (.y text-box))
|
||||
(i32 (.width text-box)) (i32 (.height text-box))
|
||||
(if mouse-on-text rl/red rl/darkgray))
|
||||
|
||||
(let [typed (string (slice name 0 letter-count))]
|
||||
(rl/draw-text typed (+ (i32 (.x text-box)) 5) (+ (i32 (.y text-box)) 8)
|
||||
40 rl/maroon)
|
||||
(let [typed (string (slice name 0 letter-count))]
|
||||
(rl/draw-text typed (+ (i32 (.x text-box)) 5) (+ (i32 (.y text-box)) 8)
|
||||
40 rl/maroon)
|
||||
|
||||
;; The C's TextFormat("INPUT CHARS: %i/%i", ...), reassembled out of
|
||||
;; examples/digits.flan the way the other ports do it. `typed` is a view
|
||||
;; of `name` and not of the runtime's shared format buffer, so it
|
||||
;; survives the two numbers being formatted — which a value from
|
||||
;; i64->bytes would not.
|
||||
(let [x 315]
|
||||
(set x (+ x (d/draw-piece "INPUT CHARS: " x 250 20 rl/darkgray)))
|
||||
(set x (+ x (d/draw-int letter-count x 250 20 rl/darkgray)))
|
||||
(set x (+ x (d/draw-piece "/" x 250 20 rl/darkgray)))
|
||||
(d/draw-int max-input-chars x 250 20 rl/darkgray))
|
||||
;; The C's TextFormat("INPUT CHARS: %i/%i", ...), reassembled out of
|
||||
;; examples/digits.flan the way the other ports do it. `typed` is a view
|
||||
;; of `name` and not of the runtime's shared format buffer, so it
|
||||
;; survives the two numbers being formatted — which a value from
|
||||
;; i64->bytes would not.
|
||||
(let [x 315]
|
||||
(set x (+ x (d/draw-piece "INPUT CHARS: " x 250 20 rl/darkgray)))
|
||||
(set x (+ x (d/draw-int letter-count x 250 20 rl/darkgray)))
|
||||
(set x (+ x (d/draw-piece "/" x 250 20 rl/darkgray)))
|
||||
(d/draw-int max-input-chars x 250 20 rl/darkgray))
|
||||
|
||||
(when mouse-on-text
|
||||
(if (< letter-count max-input-chars)
|
||||
;; Twenty frames on, twenty frames off, at the pen position after
|
||||
;; whatever has been typed.
|
||||
(when (= (% (/ frames-counter 20) 2) 0)
|
||||
(rl/draw-text "_"
|
||||
(+ (i32 (.x text-box)) 8 (rl/measure-text typed 40))
|
||||
(+ (i32 (.y text-box)) 12) 40 rl/maroon))
|
||||
(rl/draw-text "Press BACKSPACE to delete chars..." 230 300 20
|
||||
rl/gray))))
|
||||
|
||||
(rl/end-drawing)))
|
||||
(when mouse-on-text
|
||||
(if (< letter-count max-input-chars)
|
||||
;; Twenty frames on, twenty frames off, at the pen position after
|
||||
;; whatever has been typed.
|
||||
(when (= (% (/ frames-counter 20) 2) 0)
|
||||
(rl/draw-text "_"
|
||||
(+ (i32 (.x text-box)) 8 (rl/measure-text typed 40))
|
||||
(+ (i32 (.y text-box)) 12) 40 rl/maroon))
|
||||
(rl/draw-text "Press BACKSPACE to delete chars..." 230 300 20
|
||||
rl/gray)))))))
|
||||
|
||||
@ -61,16 +61,14 @@
|
||||
(when (rl/key-pressed? :enter) (set frames-counter 0))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(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 message)
|
||||
n (min (i32 (len b)) (/ frames-counter 10))]
|
||||
(rl/draw-text (string (slice b 0 n)) 210 160 20 rl/maroon))
|
||||
;; One character every ten frames. The clamp is the whole difference from
|
||||
;; the C — see the header comment.
|
||||
(let [b (bytes 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)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(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))))
|
||||
|
||||
@ -138,60 +138,57 @@
|
||||
;; Draw the fog into its own little target first, at one pixel per tile.
|
||||
;; blank is alpha 0, so a tile that is neither unseen nor remembered
|
||||
;; leaves nothing behind and the map below shows through unmodified.
|
||||
(rl/begin-texture-mode fog-of-war)
|
||||
(rl/clear-background rl/blank)
|
||||
(dotimes [y tiles-y]
|
||||
(dotimes [x tiles-x]
|
||||
;; A tile in view (1) draws nothing at all and stays transparent.
|
||||
(let [f (at tile-fog (+ (* y tiles-x) x))]
|
||||
(when (!= f 1)
|
||||
(rl/draw-rectangle x y 1 1
|
||||
(if (= f 0) rl/black (rl/fade rl/black 0.8)))))))
|
||||
(rl/end-texture-mode)
|
||||
(rl/with-texture-mode fog-of-war
|
||||
(rl/clear-background rl/blank)
|
||||
(dotimes [y tiles-y]
|
||||
(dotimes [x tiles-x]
|
||||
;; A tile in view (1) draws nothing at all and stays transparent.
|
||||
(let [f (at tile-fog (+ (* y tiles-x) x))]
|
||||
(when (!= f 1)
|
||||
(rl/draw-rectangle x y 1 1
|
||||
(if (= f 0) rl/black (rl/fade rl/black 0.8))))))))
|
||||
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
;; The map itself, in full size.
|
||||
(dotimes [y tiles-y]
|
||||
(dotimes [x tiles-x]
|
||||
(rl/draw-rectangle (* x map-tile-size) (* y map-tile-size)
|
||||
map-tile-size map-tile-size
|
||||
(if (= (at tile-ids (+ (* y tiles-x) x)) 0)
|
||||
rl/blue
|
||||
(rl/fade rl/blue 0.9)))
|
||||
(rl/draw-rectangle-lines (* x map-tile-size) (* y map-tile-size)
|
||||
map-tile-size map-tile-size
|
||||
(rl/fade rl/darkblue 0.5))))
|
||||
;; The map itself, in full size.
|
||||
(dotimes [y tiles-y]
|
||||
(dotimes [x tiles-x]
|
||||
(rl/draw-rectangle (* x map-tile-size) (* y map-tile-size)
|
||||
map-tile-size map-tile-size
|
||||
(if (= (at tile-ids (+ (* y tiles-x) x)) 0)
|
||||
rl/blue
|
||||
(rl/fade rl/blue 0.9)))
|
||||
(rl/draw-rectangle-lines (* x map-tile-size) (* y map-tile-size)
|
||||
map-tile-size map-tile-size
|
||||
(rl/fade rl/darkblue 0.5))))
|
||||
|
||||
(rl/draw-rectangle-v player-position
|
||||
(rl/Vector2 {.x (f32 player-size) .y (f32 player-size)})
|
||||
rl/red)
|
||||
(rl/draw-rectangle-v player-position
|
||||
(rl/Vector2 {.x (f32 player-size) .y (f32 player-size)})
|
||||
rl/red)
|
||||
|
||||
;; The fog, stretched over the whole map. The negative source height is
|
||||
;; the flip — see the header comment.
|
||||
(rl/draw-texture-pro
|
||||
(.texture fog-of-war)
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (.width (.texture fog-of-war)))
|
||||
.height (- 0.0 (f32 (.height (.texture fog-of-war))))})
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (* tiles-x map-tile-size))
|
||||
.height (f32 (* tiles-y map-tile-size))})
|
||||
(rl/Vector2 {.x 0.0 .y 0.0})
|
||||
0.0
|
||||
rl/white)
|
||||
;; The fog, stretched over the whole map. The negative source height is
|
||||
;; the flip — see the header comment.
|
||||
(rl/draw-texture-pro
|
||||
(.texture fog-of-war)
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (.width (.texture fog-of-war)))
|
||||
.height (- 0.0 (f32 (.height (.texture fog-of-war))))})
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (* tiles-x map-tile-size))
|
||||
.height (f32 (* tiles-y map-tile-size))})
|
||||
(rl/Vector2 {.x 0.0 .y 0.0})
|
||||
0.0
|
||||
rl/white)
|
||||
|
||||
;; The C's TextFormat("Current tile: [%i,%i]", ...). Each number is drawn
|
||||
;; before the next is formatted, which examples/digits.flan requires:
|
||||
;; both share one static buffer in the runtime.
|
||||
(let [x 10]
|
||||
(set x (+ x (d/draw-piece "Current tile: [" x 10 20 rl/raywhite)))
|
||||
(set x (+ x (d/draw-int player-tile-x x 10 20 rl/raywhite)))
|
||||
(set x (+ x (d/draw-piece "," x 10 20 rl/raywhite)))
|
||||
(set x (+ x (d/draw-int player-tile-y x 10 20 rl/raywhite)))
|
||||
(d/draw-piece "]" x 10 20 rl/raywhite))
|
||||
;; The C's TextFormat("Current tile: [%i,%i]", ...). Each number is drawn
|
||||
;; before the next is formatted, which examples/digits.flan requires:
|
||||
;; both share one static buffer in the runtime.
|
||||
(let [x 10]
|
||||
(set x (+ x (d/draw-piece "Current tile: [" x 10 20 rl/raywhite)))
|
||||
(set x (+ x (d/draw-int player-tile-x x 10 20 rl/raywhite)))
|
||||
(set x (+ x (d/draw-piece "," x 10 20 rl/raywhite)))
|
||||
(set x (+ x (d/draw-int player-tile-y x 10 20 rl/raywhite)))
|
||||
(d/draw-piece "]" x 10 20 rl/raywhite))
|
||||
|
||||
(rl/draw-text "ARROW KEYS to move" 10 (- screen-height 25) 20 rl/raywhite)
|
||||
|
||||
(rl/end-drawing)))
|
||||
(rl/draw-text "ARROW KEYS to move" 10 (- screen-height 25) 20 rl/raywhite))))
|
||||
|
||||
@ -104,27 +104,25 @@
|
||||
(set current-texture (% (+ current-texture 1) num-textures)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/draw-texture (at textures current-texture) 0 0 rl/white)
|
||||
(rl/draw-texture (at textures current-texture) 0 0 rl/white)
|
||||
|
||||
(rl/draw-rectangle 30 400 325 30 (rl/fade rl/skyblue 0.5))
|
||||
(rl/draw-rectangle-lines 30 400 325 30 (rl/fade rl/white 0.5))
|
||||
(rl/draw-text "MOUSE LEFT BUTTON to CYCLE PROCEDURAL TEXTURES"
|
||||
40 410 10 rl/white)
|
||||
(rl/draw-rectangle 30 400 325 30 (rl/fade rl/skyblue 0.5))
|
||||
(rl/draw-rectangle-lines 30 400 325 30 (rl/fade rl/white 0.5))
|
||||
(rl/draw-text "MOUSE LEFT BUTTON to CYCLE PROCEDURAL TEXTURES"
|
||||
40 410 10 rl/white)
|
||||
|
||||
;; The C's switch. Each label is positioned so its right edge lands in the
|
||||
;; same place, which is why the x differs per line.
|
||||
(cond
|
||||
(= current-texture 0) (rl/draw-text "VERTICAL GRADIENT" 560 10 20 rl/raywhite)
|
||||
(= current-texture 1) (rl/draw-text "HORIZONTAL GRADIENT" 540 10 20 rl/raywhite)
|
||||
(= current-texture 2) (rl/draw-text "DIAGONAL GRADIENT" 540 10 20 rl/raywhite)
|
||||
(= current-texture 3) (rl/draw-text "RADIAL GRADIENT" 580 10 20 rl/lightgray)
|
||||
(= current-texture 4) (rl/draw-text "SQUARE GRADIENT" 580 10 20 rl/lightgray)
|
||||
(= current-texture 5) (rl/draw-text "CHECKED" 680 10 20 rl/raywhite)
|
||||
(= current-texture 6) (rl/draw-text "WHITE NOISE" 640 10 20 rl/red)
|
||||
(= current-texture 7) (rl/draw-text "PERLIN NOISE" 640 10 20 rl/red)
|
||||
:else (rl/draw-text "CELLULAR" 670 10 20 rl/raywhite))
|
||||
|
||||
(rl/end-drawing)))
|
||||
;; The C's switch. Each label is positioned so its right edge lands in the
|
||||
;; same place, which is why the x differs per line.
|
||||
(cond
|
||||
(= current-texture 0) (rl/draw-text "VERTICAL GRADIENT" 560 10 20 rl/raywhite)
|
||||
(= current-texture 1) (rl/draw-text "HORIZONTAL GRADIENT" 540 10 20 rl/raywhite)
|
||||
(= current-texture 2) (rl/draw-text "DIAGONAL GRADIENT" 540 10 20 rl/raywhite)
|
||||
(= current-texture 3) (rl/draw-text "RADIAL GRADIENT" 580 10 20 rl/lightgray)
|
||||
(= current-texture 4) (rl/draw-text "SQUARE GRADIENT" 580 10 20 rl/lightgray)
|
||||
(= current-texture 5) (rl/draw-text "CHECKED" 680 10 20 rl/raywhite)
|
||||
(= current-texture 6) (rl/draw-text "WHITE NOISE" 640 10 20 rl/red)
|
||||
(= current-texture 7) (rl/draw-text "PERLIN NOISE" 640 10 20 rl/red)
|
||||
:else (rl/draw-text "CELLULAR" 670 10 20 rl/raywhite)))))
|
||||
|
||||
@ -114,9 +114,8 @@
|
||||
(set target (rl/load-render-texture screen-width screen-height))
|
||||
(defer (rl/unload-render-texture target))
|
||||
|
||||
(rl/begin-texture-mode target)
|
||||
(rl/clear-background (at colors 0))
|
||||
(rl/end-texture-mode)
|
||||
(rl/with-texture-mode target
|
||||
(rl/clear-background (at colors 0)))
|
||||
|
||||
;; 120 and not 60: the stroke is a circle stamped at the mouse position once
|
||||
;; per frame, so the gaps between stamps during a fast drag are a function
|
||||
@ -148,21 +147,19 @@
|
||||
2.0 50.0))
|
||||
|
||||
(when (rl/key-pressed? :c)
|
||||
(rl/begin-texture-mode target)
|
||||
(rl/clear-background (at colors 0))
|
||||
(rl/end-texture-mode))
|
||||
(rl/with-texture-mode target
|
||||
(rl/clear-background (at colors 0))))
|
||||
|
||||
;; Paint. The gesture test is what makes the example work on a
|
||||
;; touchscreen, where there is no mouse button to hold.
|
||||
(when (or (rl/mouse-button-down? :left)
|
||||
(= (rl/get-gesture-detected) :drag))
|
||||
(rl/begin-texture-mode target)
|
||||
;; Above y=50 is the palette strip, and a stroke there would paint
|
||||
;; under the toolbar where it could never be seen.
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(rl/draw-circle (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size (at colors color-selected)))
|
||||
(rl/end-texture-mode))
|
||||
(rl/with-texture-mode target
|
||||
;; Above y=50 is the palette strip, and a stroke there would paint
|
||||
;; under the toolbar where it could never be seen.
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(rl/draw-circle (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size (at colors color-selected)))))
|
||||
|
||||
;; Right button erases, which is painting in the clear colour. The
|
||||
;; selected swatch is parked while the button is held so the toolbar
|
||||
@ -173,11 +170,10 @@
|
||||
(set color-selected-prev color-selected)
|
||||
(set color-selected 0))
|
||||
(set mouse-was-pressed true)
|
||||
(rl/begin-texture-mode target)
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(rl/draw-circle (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size (at colors 0)))
|
||||
(rl/end-texture-mode))
|
||||
(rl/with-texture-mode target
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(rl/draw-circle (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size (at colors 0)))))
|
||||
(when (and (rl/mouse-button-released? :right) mouse-was-pressed)
|
||||
(set color-selected color-selected-prev)
|
||||
(set mouse-was-pressed false)))
|
||||
@ -201,55 +197,53 @@
|
||||
(set save-message-counter 0)))
|
||||
|
||||
;; Draw
|
||||
(rl/begin-drawing)
|
||||
(rl/clear-background rl/raywhite)
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
;; The canvas, flipped by the negative source height.
|
||||
(rl/draw-texture-rec (.texture target)
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (.width (.texture target)))
|
||||
.height (- 0.0 (f32 (.height (.texture target))))})
|
||||
(rl/Vector2 {.x 0.0 .y 0.0})
|
||||
rl/white)
|
||||
;; The canvas, flipped by the negative source height.
|
||||
(rl/draw-texture-rec (.texture target)
|
||||
(rl/Rectangle {.x 0.0 .y 0.0
|
||||
.width (f32 (.width (.texture target)))
|
||||
.height (- 0.0 (f32 (.height (.texture target))))})
|
||||
(rl/Vector2 {.x 0.0 .y 0.0})
|
||||
rl/white)
|
||||
|
||||
;; The brush preview, drawn on the screen and not into the canvas.
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(if (rl/mouse-button-down? :right)
|
||||
(rl/draw-circle-lines (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size rl/gray)
|
||||
(rl/draw-circle (rl/get-mouse-x) (rl/get-mouse-y)
|
||||
brush-size (at colors color-selected))))
|
||||
;; The brush preview, drawn on the screen and not into the canvas.
|
||||
(when (> (.y mouse-pos) 50.0)
|
||||
(if (rl/mouse-button-down? :right)
|
||||
(rl/draw-circle-lines (i32 (.x mouse-pos)) (i32 (.y mouse-pos))
|
||||
brush-size rl/gray)
|
||||
(rl/draw-circle (rl/get-mouse-x) (rl/get-mouse-y)
|
||||
brush-size (at colors color-selected))))
|
||||
|
||||
;; The toolbar, over the canvas.
|
||||
(rl/draw-rectangle 0 0 (rl/get-screen-width) 50 rl/raywhite)
|
||||
(rl/draw-line 0 50 (rl/get-screen-width) 50 rl/lightgray)
|
||||
;; The toolbar, over the canvas.
|
||||
(rl/draw-rectangle 0 0 (rl/get-screen-width) 50 rl/raywhite)
|
||||
(rl/draw-line 0 50 (rl/get-screen-width) 50 rl/lightgray)
|
||||
|
||||
(dotimes [i max-colors-count]
|
||||
(rl/draw-rectangle-rec (at colors-recs i) (at colors i)))
|
||||
;; The first swatch is raywhite on raywhite, so it needs an outline to
|
||||
;; be visible at all.
|
||||
(rl/draw-rectangle-lines 10 10 30 30 rl/lightgray)
|
||||
(dotimes [i max-colors-count]
|
||||
(rl/draw-rectangle-rec (at colors-recs i) (at colors i)))
|
||||
;; The first swatch is raywhite on raywhite, so it needs an outline to
|
||||
;; be visible at all.
|
||||
(rl/draw-rectangle-lines 10 10 30 30 rl/lightgray)
|
||||
|
||||
(when (>= color-mouse-hover 0)
|
||||
(rl/draw-rectangle-rec (at colors-recs color-mouse-hover)
|
||||
(rl/fade rl/white 0.6)))
|
||||
(when (>= color-mouse-hover 0)
|
||||
(rl/draw-rectangle-rec (at colors-recs color-mouse-hover)
|
||||
(rl/fade rl/white 0.6)))
|
||||
|
||||
(let [r (at colors-recs color-selected)]
|
||||
(rl/draw-rectangle-lines-ex
|
||||
(rl/Rectangle {.x (- (.x r) 2.0) .y (- (.y r) 2.0)
|
||||
.width (+ (.width r) 4.0) .height (+ (.height r) 4.0)})
|
||||
2.0 rl/black))
|
||||
(let [r (at colors-recs color-selected)]
|
||||
(rl/draw-rectangle-lines-ex
|
||||
(rl/Rectangle {.x (- (.x r) 2.0) .y (- (.y r) 2.0)
|
||||
.width (+ (.width r) 4.0) .height (+ (.height r) 4.0)})
|
||||
2.0 rl/black))
|
||||
|
||||
(rl/draw-rectangle-lines-ex btn-save-rec 2.0
|
||||
(if btn-save-mouse-hover rl/red rl/black))
|
||||
(rl/draw-text "SAVE!" 755 20 10
|
||||
(if btn-save-mouse-hover rl/red rl/black))
|
||||
(rl/draw-rectangle-lines-ex btn-save-rec 2.0
|
||||
(if btn-save-mouse-hover rl/red rl/black))
|
||||
(rl/draw-text "SAVE!" 755 20 10
|
||||
(if btn-save-mouse-hover rl/red rl/black))
|
||||
|
||||
(when show-save-message
|
||||
(rl/draw-rectangle 0 0 (rl/get-screen-width) (rl/get-screen-height)
|
||||
(rl/fade rl/raywhite 0.8))
|
||||
(rl/draw-rectangle 0 150 (rl/get-screen-width) 80 rl/black)
|
||||
(rl/draw-text "IMAGE SAVED: my_amazing_texture_painting.png"
|
||||
150 180 20 rl/raywhite))
|
||||
|
||||
(rl/end-drawing))))
|
||||
(when show-save-message
|
||||
(rl/draw-rectangle 0 0 (rl/get-screen-width) (rl/get-screen-height)
|
||||
(rl/fade rl/raywhite 0.8))
|
||||
(rl/draw-rectangle 0 150 (rl/get-screen-width) 80 rl/black)
|
||||
(rl/draw-text "IMAGE SAVED: my_amazing_texture_painting.png"
|
||||
150 180 20 rl/raywhite))))))
|
||||
|
||||
15
sand.flan
15
sand.flan
@ -15,7 +15,10 @@
|
||||
;;;; offers.
|
||||
;;;;
|
||||
;;;; Note what it deliberately does not use: no Vec, no Map, no generics, no
|
||||
;;;; user-written macros, no allocator other than the stack and static storage.
|
||||
;;;; macros of its own, no allocator other than the stack and static storage.
|
||||
;;;; It does call rl/with-drawing, which is the raylib package's macro over
|
||||
;;;; the BeginDrawing/EndDrawing pair — the parity rule is what the reference
|
||||
;;;; versions do, and lisp/sand.lisp writes rl:with-drawing there.
|
||||
;;;;
|
||||
;;;; Notation reminders (see plan.org and spec-memory.md):
|
||||
;;;; [n T] fixed array, length n, element T — a VALUE, copies
|
||||
@ -191,11 +194,13 @@
|
||||
;; leaves one CL-style escape hatch: choose `continue' in the editor to
|
||||
;; abandon this frame and return to the next one with the game still live.
|
||||
;; Keep drawing outside it. Skipping between BeginDrawing and EndDrawing
|
||||
;; would leave raylib's frame unbalanced.
|
||||
;; would leave raylib's frame unbalanced, and rl/with-drawing does not
|
||||
;; change that — it guarantees the two calls stay together and stay
|
||||
;; matched, not that a transfer out of the body reaches the second one.
|
||||
;; The restart being out here is still what makes `continue' safe.
|
||||
(restart-case
|
||||
(do (agent/poll)
|
||||
(game-update))
|
||||
(continue [] (do)))
|
||||
(rl/begin-drawing)
|
||||
(game-draw)
|
||||
(rl/end-drawing)))
|
||||
(rl/with-drawing
|
||||
(game-draw))))
|
||||
|
||||
16
test/programs/rl-with-reject.flan
Normal file
16
test/programs/rl-with-reject.flan
Normal file
@ -0,0 +1,16 @@
|
||||
;;;; with-mode-2d without a camera.
|
||||
;;;;
|
||||
;;;; The prelude's idiom for a macro's own arity check, which clamp and unless
|
||||
;;;; and into all use: answer a symbol that is not a name, spelled as the
|
||||
;;;; sentence the author needed to read. There is no way for a macro to signal
|
||||
;;;; at expansion time, so the message travels as the unknown function — and
|
||||
;;;; what makes it land usefully is the note the expander adds beneath it,
|
||||
;;;; naming the macro and the call site.
|
||||
;;;;
|
||||
;;;; Being refused is the whole test; this is never built.
|
||||
|
||||
(import rl "vendor:raylib")
|
||||
|
||||
(defn main [] i32
|
||||
(rl/with-mode-2d)
|
||||
0)
|
||||
43
test/programs/rl-with.flan
Normal file
43
test/programs/rl-with.flan
Normal file
@ -0,0 +1,43 @@
|
||||
;;;; The raylib package's five begin/end macros, expanded.
|
||||
;;;;
|
||||
;;;; They cannot be *run* here. Every one of them brackets calls that need a
|
||||
;;;; window and a GL context, so a headless case can only assert what the
|
||||
;;;; expansion is, not what it draws — which is the whole of what a macro
|
||||
;;;; over a pair can get wrong. The four examples/ uses of with-drawing and
|
||||
;;;; friends already prove they compile; what this adds is with-scissor-mode,
|
||||
;;;; which no example can use (examples/core-scissor-test.flan turns its
|
||||
;;;; scissor on and off from a flag, so its Begin and its End sit inside two
|
||||
;;;; separate `when`s and there is no body to wrap). The arity refusals are
|
||||
;;;; rl-with-reject.flan, beside this.
|
||||
;;;;
|
||||
;;;; [frame] is deliberately not reached from [main]. lib/reach.ml answers the
|
||||
;;;; link from the checked program, so an unreachable frame means this case
|
||||
;;;; needs no libraylib to run and goes in the suite unconditionally — while
|
||||
;;;; [check] still walks every line of it, which is where a wrong expansion
|
||||
;;;; would show.
|
||||
|
||||
(import rl "vendor:raylib")
|
||||
|
||||
(defn frame [cam rl/Camera2D cam3 rl/Camera3D target rl/RenderTexture2D] ()
|
||||
(rl/with-drawing
|
||||
(rl/clear-background rl/raywhite)
|
||||
|
||||
(rl/with-mode-2d cam
|
||||
(rl/draw-rectangle 0 0 10 10 rl/red))
|
||||
|
||||
(rl/with-mode-3d cam3
|
||||
(rl/draw-fps 0 0))
|
||||
|
||||
(rl/with-scissor-mode 10 10 100 100
|
||||
(rl/draw-rectangle 0 0 320 240 rl/blue)
|
||||
(rl/draw-text "clipped" 20 20 10 rl/black))
|
||||
|
||||
(rl/draw-fps 10 10))
|
||||
|
||||
;; Off-screen, outside the frame, which is where a render texture belongs.
|
||||
(rl/with-texture-mode target
|
||||
(rl/clear-background rl/blank)))
|
||||
|
||||
(defn main [] i32
|
||||
(println "expanded")
|
||||
0)
|
||||
@ -896,6 +896,16 @@ let () =
|
||||
outputs ~opt:"-O0" "raylib, bindings generated from the header, -O0"
|
||||
"programs/raylib-imported.flan" out;
|
||||
|
||||
(* The raylib package's begin/end macros — vendor/raylib/modes.flan.
|
||||
Nothing here draws: every one of the five brackets calls that want a
|
||||
window and a GL context, so what can be asserted headless is that the
|
||||
expansion compiles, which is the whole of what a macro over a pair can
|
||||
get wrong. The program keeps the frame function unreachable from main
|
||||
on purpose, so reach.ml links no libraylib and this runs unconditionally
|
||||
alongside the cases that need one. See the file's header. *)
|
||||
outputs "raylib begin/end macros expand" "programs/rl-with.flan"
|
||||
"expanded\n";
|
||||
|
||||
(* raylib's Image family, headless, and the strongest FFI case here: an
|
||||
Image is pixels in RAM, so raylib *computes* with it rather than
|
||||
storing and returning it.
|
||||
@ -1397,6 +1407,17 @@ let () =
|
||||
name m needle
|
||||
end
|
||||
in
|
||||
(* A package macro's arity check. A macro cannot signal while it expands,
|
||||
so the prelude's idiom — clamp's, unless's, into's — is to answer a
|
||||
symbol that is not a name and reads as the sentence the caller needs.
|
||||
What makes that usable rather than baffling is the expander's note
|
||||
beneath it, naming rl/with-mode-2d at the call site rather than
|
||||
pointing into the package — that half is rendering and is not asserted
|
||||
here. *)
|
||||
refuses "with-mode-2d written without a camera"
|
||||
"programs/rl-with-reject.flan"
|
||||
"with-mode-2d-takes-a-camera-and-a-body";
|
||||
|
||||
(* Visibility: main is not a name a package offers, and saying so is the
|
||||
point — "unknown name sand/main" would be true and useless. *)
|
||||
(* Generics, at the definition rather than at a call site. Both of these
|
||||
|
||||
125
vendor/raylib/modes.flan
vendored
Normal file
125
vendor/raylib/modes.flan
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
;;;; The begin/end pairs, as macros that cannot come apart.
|
||||
;;;;
|
||||
;;;; raylib has five pairs this package binds — drawing, 2D camera, 3D camera,
|
||||
;;;; render texture, scissor — and every one of them is the same hazard: two
|
||||
;;;; calls that have to bracket a body, written by hand, with nothing checking
|
||||
;;;; that the second one is there or that it is the matching one. An
|
||||
;;;; EndDrawing that is missing hangs the frame; an EndMode2D that should have
|
||||
;;;; been EndMode3D corrupts the matrix stack; a pair that drifted apart during
|
||||
;;;; an edit does either. NEXT.md put `unwind-protect` for this and rejected
|
||||
;;;; it, with the note that these are "three-line macros once the expander
|
||||
;;;; lands". They are, and this is them.
|
||||
;;;;
|
||||
;;;; (rl/with-drawing
|
||||
;;;; (rl/clear-background rl/raywhite)
|
||||
;;;; (rl/draw-fps 10 10))
|
||||
;;;;
|
||||
;;;; expands to exactly what the caller used to type, in the order they used
|
||||
;;;; to type it:
|
||||
;;;;
|
||||
;;;; (do (rl/begin-drawing)
|
||||
;;;; (rl/clear-background rl/raywhite)
|
||||
;;;; (rl/draw-fps 10 10)
|
||||
;;;; (rl/end-drawing))
|
||||
;;;;
|
||||
;;;; The argument-taking ones put the argument where it always went, evaluated
|
||||
;;;; once, in place. There is no `let` and no `gensym` anywhere below: nothing
|
||||
;;;; here binds a name, so there is no name for a caller's to collide with,
|
||||
;;;; and introducing one in a deliberately non-hygienic macro that does not
|
||||
;;;; need it would be a step backwards.
|
||||
;;;;
|
||||
;;;; ── What this does not fix, and why it cannot ───────────────────────
|
||||
;;;;
|
||||
;;;; The bug class removed is "the End* is missing, wrong, or no longer
|
||||
;;;; beside its Begin*". The bug class NOT removed is a body that leaves
|
||||
;;;; through the unwind path instead of the bottom: a `return`, or an
|
||||
;;;; `invoke-restart` reaching an enclosing `restart-case`. Both of those skip
|
||||
;;;; the rest of the `do` and the `End*` with it, exactly as they would skip a
|
||||
;;;; hand-written one.
|
||||
;;;;
|
||||
;;;; The obvious fix is `defer`, and it is not available here. `defer` is a
|
||||
;;;; compile-time construct — the forms are copied into the function's exit
|
||||
;;;; paths — so BUILT.md refuses it inside a loop or a branch, and a
|
||||
;;;; begin/end pair lives inside the game loop essentially always. Were it
|
||||
;;;; permitted there it would be wrong in the worse direction: one EndDrawing
|
||||
;;;; at function exit for N BeginDrawings. A macro expanding to a defer would
|
||||
;;;; therefore compile at a function body's top level and be refused in the
|
||||
;;;; one place anybody writes it, which is a worse thing to hand somebody than
|
||||
;;;; a macro that is honest about its extent.
|
||||
;;;;
|
||||
;;;; So the discipline sand.flan already writes down stays the discipline:
|
||||
;;;; keep the restart boundary OUTSIDE the pair, so choosing `continue` for a
|
||||
;;;; frame abandons the update and still reaches the drawing. spec-conditions
|
||||
;;;; §5 is the rule behind that — a transfer runs the intervening frames'
|
||||
;;;; defers and moves control, and there are no defers here to run.
|
||||
;;;;
|
||||
;;;; ── Why this is a file of its own ───────────────────────────────────
|
||||
;;;;
|
||||
;;;; vector.flan's reasoning, unchanged: the split is on `declare-c`.
|
||||
;;;; raylib.flan is the package's statement about C, it is the file the header
|
||||
;;;; check reads hand-written signatures out of, and a wrong line in it stops
|
||||
;;;; the build. There is not one `declare-c` below — every macro here expands
|
||||
;;;; into names raylib.flan already declares — so there is nothing for the
|
||||
;;;; header check to read and nothing raylib can make wrong. A package is a
|
||||
;;;; directory, so this is another .flan beside the others and is qualified
|
||||
;;;; `rl/` like the rest of it.
|
||||
;;;;
|
||||
;;;; The names come out qualified: the importer writes `(rl/with-drawing …)`
|
||||
;;;; and a bare `(with-drawing …)` is an unknown name there, the rule every
|
||||
;;;; declaration in this package follows. The expansions name this package's
|
||||
;;;; own functions unqualified and the expander qualifies them on the way out
|
||||
;;;; — see test/programs/pkgs/mac/mac.flan, which is that rule's worked
|
||||
;;;; example.
|
||||
;;;;
|
||||
;;;; Each macro answers the value of its `End*` call, which is (). A pair was
|
||||
;;;; never an expression worth reading anyway.
|
||||
|
||||
;; The frame. Everything drawn lands on the back buffer; end-drawing swaps it
|
||||
;; and waits out the frame time set by set-target-fps.
|
||||
(defmacro with-drawing [args]
|
||||
(if (< (len args) 1)
|
||||
`(with-drawing-takes-a-body)
|
||||
`(do (begin-drawing)
|
||||
~@args
|
||||
(end-drawing))))
|
||||
|
||||
;; The 2D camera. The argument is a Camera2D value, evaluated once where it
|
||||
;; always was. Remember that a fresh (Camera2D {}) has zoom 0.0 and is not
|
||||
;; usable as an identity — raylib.flan says so beside the struct.
|
||||
(defmacro with-mode-2d [args]
|
||||
(if (< (len args) 2)
|
||||
`(with-mode-2d-takes-a-camera-and-a-body)
|
||||
`(do (begin-mode-2d ~(at args 0))
|
||||
~@(form-rest args 1)
|
||||
(end-mode-2d))))
|
||||
|
||||
;; The 3D camera. Same shape, same argument-once rule, and the pair matters
|
||||
;; more here than anywhere: ending a 3D mode with end-mode-2d type-checks
|
||||
;; fine and leaves the projection matrix wrong for everything after it.
|
||||
(defmacro with-mode-3d [args]
|
||||
(if (< (len args) 2)
|
||||
`(with-mode-3d-takes-a-camera-and-a-body)
|
||||
`(do (begin-mode-3d ~(at args 0))
|
||||
~@(form-rest args 1)
|
||||
(end-mode-3d))))
|
||||
|
||||
;; Render to a texture instead of the screen. The target's texture comes out
|
||||
;; of the GPU upside down, so drawing it back wants a negative source height —
|
||||
;; that correction is the caller's and is deliberately not hidden here, since
|
||||
;; it belongs with the draw and not with the mode.
|
||||
(defmacro with-texture-mode [args]
|
||||
(if (< (len args) 2)
|
||||
`(with-texture-mode-takes-a-target-and-a-body)
|
||||
`(do (begin-texture-mode ~(at args 0))
|
||||
~@(form-rest args 1)
|
||||
(end-texture-mode))))
|
||||
|
||||
;; Clip to a rectangle, in screen pixels with y down from the top. Four
|
||||
;; scalars rather than a Rectangle, because that is what BeginScissorMode
|
||||
;; takes and this file is not the place to invent a second spelling.
|
||||
(defmacro with-scissor-mode [args]
|
||||
(if (< (len args) 5)
|
||||
`(with-scissor-mode-takes-x-y-width-height-and-a-body)
|
||||
`(do (begin-scissor-mode ~(at args 0) ~(at args 1) ~(at args 2) ~(at args 3))
|
||||
~@(form-rest args 4)
|
||||
(end-scissor-mode))))
|
||||
Loading…
x
Reference in New Issue
Block a user