programextensions/scene/demos/voxels-walk.xtl
Voxels, 5: walking. The island of voxels-world, seen from inside it. The player is nine numbers -- x y z (feet), vx vy vz, yaw, pitch, on the ground -- and every frame X_eTaL reads the keys and the mouse, turns, falls, jumps, and moves one axis at a time against the solid blocks the player's box would overlap, stopping at the face of the block it hits (a swept box per axis, as the APL game collides); then it sets scene's first-person camera. It also tests the 32 chunks against the planes of the view, as the APL game culls (key c). Run: just demo scene voxels-walk (a new island each run; --seed 1) W A S D walk, Shift run, Space jump (in water: swim up; at the surface: climb out onto a bank one block high), drag the mouse or the arrows to look, c: the chunks in view, H: back to the start, q or close: quit
ᵘp̲ut : Int -> Int
ᵘp̲ut ← { i → key ← i s̲elect keys sel ← key = (10 × c) + 5 s̲elect₂ f head ← (f̲loat w c̲at key) c̲at (1 + key m̲od 10) s̲elect ᵛˣcolors x ← head ˢᶜq̲uads! ᵛˣc̲orners sel r̲eplicate f i + 1 }
The player
ᵘs̲et : Float -> Float -> Float
(i c_at v) u:s_et p: the state with element i replaced by v
ᵘs̲et ← { l p → p + (f̲loat (r̲ange 9) = f̲loor 1 s̲elect l) × (2 s̲elect l) − p }
ᵘh̲it : Float -> Float
whether the box with its feet at (x y z) overlaps a solid block: beyond the island's sides and below it is solid, above it is air
ᵘh̲it ← { q → x ← 1 s̲elect q y ← 2 s̲elect q z ← 3 s̲elect q cx ← u̲nique f̲loor (x − 0.3) c̲at x + 0.3 cy ← u̲nique f̲loor y c̲at (y + 0.9) c̲at y + 1.75 cz ← u̲nique f̲loor (z − 0.3) c̲at z + 0.3 out ← ('+ r̲/ (cx < 0) + cx > 63) + ('+ r̲/ (cz < 0) + cz > 63) + '+ r̲/ cy < 0 out > 0 ? 1 cy ← (cy ≤ 31) r̲eplicate cy 0 = t̲ally cy ? 0 i ← 1 + (2048 × cx) '+ t̲able (64 × cy) '+ t̲able cz f̲loat 0 < '+ r̲/ (r̲avel i) s̲elect sv }
ᵘs̲nap : Float -> Float -> Float
v u:s_nap a: where to stop, moving at v, before the block at a (the box reaches 0.3 to each side)
ᵘs̲nap ← { v a → v > 0.0 ? (f̲loat f̲loor a + 0.3) − 0.3001 (f̲loat 1 + f̲loor a − 0.3) + 0.3001 }
ᵘm̲x : Float -> Float
the three axes of a move: x and z stop at a wall; y lands (on the ground) or bumps a ceiling
ᵘm̲x ← { p → a ← (1 s̲elect p) + dt × 4 s̲elect p q ← (1 c̲at a) ᵘs̲et p 0 = ᵘh̲it q ? q (4 c̲at 0.0) ᵘs̲et (1 c̲at (4 s̲elect p) ᵘs̲nap a) ᵘs̲et p }
ᵘm̲z : Float -> Float
ᵘm̲z ← { p → a ← (3 s̲elect p) + dt × 6 s̲elect p q ← (3 c̲at a) ᵘs̲et p 0 = ᵘh̲it q ? q (6 c̲at 0.0) ᵘs̲et (3 c̲at (6 s̲elect p) ᵘs̲nap a) ᵘs̲et p }
ᵘm̲y : Float -> Float
ᵘm̲y ← { p → a ← (2 s̲elect p) + dt × 5 s̲elect p q ← (9 c̲at 0.0) ᵘs̲et (2 c̲at a) ᵘs̲et p 0 = ᵘh̲it q ? q (5 s̲elect p) > 0.0 ? (5 c̲at 0.0) ᵘs̲et (2 c̲at (f̲loat f̲loor a + 1.75) − 1.7501) ᵘs̲et p (9 c̲at 1.0) ᵘs̲et (5 c̲at 0.0) ᵘs̲et (2 c̲at f̲loat 1 + f̲loor a) ᵘs̲et p }
ᵘs̲tep : Float -> Float
one frame of the player: the controls are mouse dx dy, then w a s d space shift left right up down (1 held)
ᵘs̲tep ← { p → k ← ˢᶜc̲ontrols w yaw ← (7 s̲elect p) + (0.005 × 1 s̲elect k) + 2.0 × dt × (10 s̲elect k) − 9 s̲elect k pitch ← -1.5 m̲ax 1.5 m̲in (8 s̲elect p) + (-0.005 × 2 s̲elect k) + 1.5 × dt × (11 s̲elect k) − 12 s̲elect k fwd ← (3 s̲elect k) − 5 s̲elect k side ← (6 s̲elect k) − 4 s̲elect k ⍝ in water: all the air below the sea (14) is water; the body is in ⍝ it when its middle is below the surface wet ← f̲loat 14.0 > 0.9 + 2 s̲elect p speed ← (1.0 − 0.4 × wet) × 4.5 × 1.0 + 8 s̲elect k vx ← speed × ((s̲in yaw) × fwd) + (c̲os yaw) × side vz ← speed × ((0.0 − c̲os yaw) × fwd) + (s̲in yaw) × side ⍝ a jump from the ground, or from the surface of the water (feet ⍝ within half a block above it, not deeper): onto a bank one block high surface ← (f̲loat 14.5 > 2 s̲elect p) × f̲loat 13.0 < 2 s̲elect p jump ← (1.0 m̲in (9 s̲elect p) + surface × 1.0 − wet) × 7 s̲elect k ⍝ swimming: Space rises; otherwise a slow sink swim ← wet × 7 s̲elect k fall ← -30.0 m̲ax (5 s̲elect p) − 22.0 × dt sink ← -2.0 m̲ax (5 s̲elect p) − 6.0 × dt vy ← (7.5 × jump) + (1.0 − jump) × (4.0 × swim) + (1.0 − swim) × (wet × sink) + (1.0 − wet) × fall p ← (7 c̲at yaw) ᵘs̲et (8 c̲at pitch) ᵘs̲et (4 c̲at vx) ᵘs̲et (5 c̲at vy) ᵘs̲et (6 c̲at vz) ᵘs̲et p p ← ᵘm̲y ᵘm̲z ᵘm̲x p e ← w ˢᶜe̲ye! (1 s̲elect p) c̲at ((2 s̲elect p) + 1.6) c̲at (3 s̲elect p) c̲at yaw c̲at pitch p }
The chunks in view
ᵘi̲nView : Truthy a => Float -> a
each chunk's box against the planes of the view (left, right, bottom, top, and the plane of the eye): a chunk is out when its box is wholly behind one of them. The planes' normals are made in the camera's frame and turned into the world's by an inner product with the frame.
ᵘi̲nView ← { p → yaw ← 7 s̲elect p pt ← 8 s̲elect p right ← (c̲os yaw) c̲at 0.0 c̲at s̲in yaw up ← (0.0 − (s̲in yaw) × s̲in pt) c̲at (c̲os pt) c̲at (c̲os yaw) × s̲in pt ahead ← ((s̲in yaw) × c̲os pt) c̲at (s̲in pt) c̲at 0.0 − (c̲os yaw) × c̲os pt v ← 0.6109 hh ← a̲tan 1.6 × (s̲in v) ÷ c̲os v nc ← 5 3 r̲eshape (c̲os hh) c̲at 0.0 c̲at (s̲in hh) c̲at (0.0 − c̲os hh) c̲at 0.0 c̲at (s̲in hh) c̲at 0.0 c̲at (c̲os v) c̲at (s̲in v) c̲at 0.0 c̲at (0.0 − c̲os v) c̲at (s̲in v) c̲at 0.0 0.0 1.0 nw ← nc '+ '× i̲nner 3 3 r̲eshape right c̲at up c̲at ahead j ← (r̲ange 32) − 1 centers ← 2 1 t̲ranspose 3 32 r̲eshape (8.0 + 16.0 × f̲loat j m̲od 4) c̲at (8.0 + 16.0 × f̲loat j d̲iv 16) c̲at 8.0 + 16.0 × f̲loat (j d̲iv 4) m̲od 4 eye ← (1 s̲elect p) c̲at ((2 s̲elect p) + 1.6) c̲at 3 s̲elect p rel ← centers − 32 3 r̲eshape eye d ← rel '+ '× i̲nner 2 1 t̲ranspose nw r ← (a̲bs nw) '+ '× i̲nner 8.0 8.0 8.0 '∧ r̲/₂ d ≥ 32 5 r̲eshape 0.0 − r }
ᵘc̲hunks : Float -> Float
ᵘc̲hunks ← { p → m ← ᵘi̲nView p a ← p̲rint! "chunks in view (of 32), and by layer (bottom, top; rows north to south):" a ← p̲rint! '+ r̲/ m a ← p̲rint! 2 4 4 r̲eshape m p }
The loop
j : Int
start above the island's highest inner column, dropping onto it, facing north when the middle is north of it, else south (the highest of the columns at least 8 from the island's sides)
j ← (r̲ange 4096) − 1
inner : Int
inner ← ((j d̲iv 64) ≥ 8) × ((j d̲iv 64) < 56) × ((j m̲od 64) ≥ 8) × (j m̲od 64) < 56
start : Float
start ← sx c̲at (f̲loat 3 + i s̲elect hv) c̲at sz c̲at 0.0 0.0 0.0 c̲at yaw0 c̲at 0.0 0.0