sourceextensions/scene/demos/voxels-walk.xtl

1⍝# Voxels, 5: walking. The island of voxels-world, seen from inside it. 2⍝# The player is nine numbers -- x y z (feet), vx vy vz, yaw, pitch, on 3⍝# the ground -- and every frame X_eTaL reads the keys and the mouse, 4⍝# turns, falls, jumps, and moves one axis at a time against the solid 5⍝# blocks the player's box would overlap, stopping at the face of the 6⍝# block it hits (a swept box per axis, as the APL game collides); then 7⍝# it sets scene's first-person camera. It also tests the 32 chunks 8⍝# against the planes of the view, as the APL game culls (key c). 9⍝# Run: just demo scene voxels-walk (a new island each run; --seed 1) 10⍝# W A S D walk, Shift run, Space jump (in water: swim up; at the 11⍝# surface: climb out onto a bank one block high), drag the mouse or the 12⍝# arrows to look, c: the chunks in view, H: back to the start, q or 13⍝# close: quit 14 15ᵛˣ⁼u̲se< "Voxels" 16ˢᶜ⁼u̲se< "Scene" 17 18h ← ᵛˣh̲eights 64 19b ← ᵛˣt̲errain h 20ts ← 12 2 r̲eshape 3 + r̲oll! 24 r̲eshape 58 21b ← ts ᵛˣf̲orest b 22f ← ᵛˣw̲orldFaces b 23sv ← r̲avel ᵛˣs̲olid b 24"faces, and solid blocks:" 25(t̲ally f) c̲at '+ r̲/ sv 26 27w ← "Voxels 5: walking -- X_eTaL" ˢᶜo̲pen! 640 400 28g ← w ˢᶜf̲og! 24.0 56.0 29c ← ᵛˣc̲hunkOf f 30keys ← u̲nique (10 × c) + 5 s̲elect₂ f 31ᵘp̲ut ← { i → 32 key ← i s̲elect keys 33 sel ← key = (10 × c) + 5 s̲elect₂ f 34 head ← (f̲loat w c̲at key) c̲at (1 + key m̲od 10) s̲elect ᵛˣcolors 35 x ← head ˢᶜq̲uads! ᵛˣc̲orners sel r̲eplicate f 36 i + 1 37} 38put ← (t̲ally keys) 'ᵘp̲ut p̲ower 1 39 40⍝## The player 41 42⍝# a box 0.6 wide and 1.75 tall, the eye 1.6 up; a frame is 1/60 s 43dt ← 1.0 ÷ 60.0 44 45⍝# (i c_at v) u:s_et p: the state with element i replaced by v 46ᵘs̲et ← { l p → p + (f̲loat (r̲ange 9) = f̲loor 1 s̲elect l) × (2 s̲elect l) − p } 47 48⍝# whether the box with its feet at (x y z) overlaps a solid block: 49⍝# beyond the island's sides and below it is solid, above it is air 50ᵘh̲it ← { q → 51 x ← 1 s̲elect q 52 y ← 2 s̲elect q 53 z ← 3 s̲elect q 54 cx ← u̲nique f̲loor (x − 0.3) c̲at x + 0.3 55 cy ← u̲nique f̲loor y c̲at (y + 0.9) c̲at y + 1.75 56 cz ← u̲nique f̲loor (z − 0.3) c̲at z + 0.3 57 out ← ('+ r̲/ (cx < 0) + cx > 63) + ('+ r̲/ (cz < 0) + cz > 63) + '+ r̲/ cy < 0 58 out > 0 ? 1 59 cy ← (cy ≤ 31) r̲eplicate cy 60 0 = t̲ally cy ? 0 61 i ← 1 + (2048 × cx) '+ t̲able (64 × cy) '+ t̲able cz 62 f̲loat 0 < '+ r̲/ (r̲avel i) s̲elect sv 63} 64 65⍝# v u:s_nap a: where to stop, moving at v, before the block at a 66⍝# (the box reaches 0.3 to each side) 67ᵘs̲nap ← { v a → 68 v > 0.0 ? (f̲loat f̲loor a + 0.3) − 0.3001 69 (f̲loat 1 + f̲loor a − 0.3) + 0.3001 70} 71 72⍝# the three axes of a move: x and z stop at a wall; y lands (on the 73⍝# ground) or bumps a ceiling 74ᵘm̲x ← { p → 75 a ← (1 s̲elect p) + dt × 4 s̲elect p 76 q ← (1 c̲at a) ᵘs̲et p 77 0 = ᵘh̲it q ? q 78 (4 c̲at 0.0) ᵘs̲et (1 c̲at (4 s̲elect p) ᵘs̲nap a) ᵘs̲et p 79} 80ᵘm̲z ← { p → 81 a ← (3 s̲elect p) + dt × 6 s̲elect p 82 q ← (3 c̲at a) ᵘs̲et p 83 0 = ᵘh̲it q ? q 84 (6 c̲at 0.0) ᵘs̲et (3 c̲at (6 s̲elect p) ᵘs̲nap a) ᵘs̲et p 85} 86ᵘm̲y ← { p → 87 a ← (2 s̲elect p) + dt × 5 s̲elect p 88 q ← (9 c̲at 0.0) ᵘs̲et (2 c̲at a) ᵘs̲et p 89 0 = ᵘh̲it q ? q 90 (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 91 (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 92} 93 94⍝# one frame of the player: the controls are mouse dx dy, then w a s d 95⍝# space shift left right up down (1 held) 96ᵘs̲tep ← { p → 97 k ← ˢᶜc̲ontrols w 98 yaw ← (7 s̲elect p) + (0.005 × 1 s̲elect k) + 2.0 × dt × (10 s̲elect k) − 9 s̲elect k 99 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 100 fwd ← (3 s̲elect k) − 5 s̲elect k 101 side ← (6 s̲elect k) − 4 s̲elect k 102 ⍝ in water: all the air below the sea (14) is water; the body is in 103 ⍝ it when its middle is below the surface 104 wet ← f̲loat 14.0 > 0.9 + 2 s̲elect p 105 speed ← (1.0 − 0.4 × wet) × 4.5 × 1.0 + 8 s̲elect k 106 vx ← speed × ((s̲in yaw) × fwd) + (c̲os yaw) × side 107 vz ← speed × ((0.0 − c̲os yaw) × fwd) + (s̲in yaw) × side 108 ⍝ a jump from the ground, or from the surface of the water (feet 109 ⍝ within half a block above it, not deeper): onto a bank one block high 110 surface ← (f̲loat 14.5 > 2 s̲elect p) × f̲loat 13.0 < 2 s̲elect p 111 jump ← (1.0 m̲in (9 s̲elect p) + surface × 1.0 − wet) × 7 s̲elect k 112 ⍝ swimming: Space rises; otherwise a slow sink 113 swim ← wet × 7 s̲elect k 114 fall ← -30.0 m̲ax (5 s̲elect p) − 22.0 × dt 115 sink ← -2.0 m̲ax (5 s̲elect p) − 6.0 × dt 116 vy ← (7.5 × jump) + (1.0 − jump) × (4.0 × swim) + (1.0 − swim) × (wet × sink) + (1.0 − wet) × fall 117 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 118 p ← ᵘm̲y ᵘm̲z ᵘm̲x p 119 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 120 p 121} 122 123⍝## The chunks in view 124 125⍝# each chunk's box against the planes of the view (left, right, bottom, 126⍝# top, and the plane of the eye): a chunk is out when its box is wholly 127⍝# behind one of them. The planes' normals are made in the camera's 128⍝# frame and turned into the world's by an inner product with the frame. 129ᵘi̲nView ← { p → 130 yaw ← 7 s̲elect p 131 pt ← 8 s̲elect p 132 right ← (c̲os yaw) c̲at 0.0 c̲at s̲in yaw 133 up ← (0.0 − (s̲in yaw) × s̲in pt) c̲at (c̲os pt) c̲at (c̲os yaw) × s̲in pt 134 ahead ← ((s̲in yaw) × c̲os pt) c̲at (s̲in pt) c̲at 0.0 − (c̲os yaw) × c̲os pt 135 v ← 0.6109 136 hh ← a̲tan 1.6 × (s̲in v) ÷ c̲os v 137 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 138 nw ← nc '+ '× i̲nner 3 3 r̲eshape right c̲at up c̲at ahead 139 j ← (r̲ange 32) − 1 140 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 141 eye ← (1 s̲elect p) c̲at ((2 s̲elect p) + 1.6) c̲at 3 s̲elect p 142 rel ← centers − 32 3 r̲eshape eye 143 d ← rel '+ '× i̲nner 2 1 t̲ranspose nw 144 r ← (a̲bs nw) '+ '× i̲nner 8.0 8.0 8.0 145 '∧ r̲/₂ d ≥ 32 5 r̲eshape 0.0 − r 146} 147ᵘc̲hunks ← { p → 148 m ← ᵘi̲nView p 149 a ← p̲rint! "chunks in view (of 32), and by layer (bottom, top; rows north to south):" 150 a ← p̲rint! '+ r̲/ m 151 a ← p̲rint! 2 4 4 r̲eshape m 152 p 153} 154 155⍝## The loop 156 157⍝# start above the island's highest inner column, dropping onto it, facing 158⍝# north when the middle is north of it, else south 159⍝# (the highest of the columns at least 8 from the island's sides) 160j ← (r̲ange 4096) − 1 161inner ← ((j d̲iv 64) ≥ 8) × ((j d̲iv 64) < 56) × ((j m̲od 64) ≥ 8) × (j m̲od 64) < 56 162hv ← r̲avel h 163i ← f̲irst w̲here inner × hv = 'm̲ax r̲/ inner × hv 164sx ← (f̲loat (i − 1) d̲iv 64) + 0.5 165sz ← (f̲loat (i − 1) m̲od 64) + 0.5 166yaw0 ← 3.14159 × f̲loat sz < 32.0 167start ← 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 168s ← ᵘc̲hunks start 169e ← w ˢᶜe̲ye! sx c̲at (f̲loat 5 + i s̲elect hv) c̲at sz c̲at yaw0 c̲at 0.0 170 171ᵘq̲uit ← { p → 172 z ← ˢᶜc̲lose! w 173 0 r̲eshape 0.0 174} 175ᵘf̲rame ← { p → 176 0 = t̲ally p ? p 177 v ← ˢᶜn̲ext! w 178 ((v m̲atch "close") + (v m̲atch "key q") + v m̲atch "key Escape") > 0 ? ᵘq̲uit p 179 (v m̲atch "key c") ? ᵘs̲tep ᵘc̲hunks p 180 (v m̲atch "key h") ? ᵘs̲tep start 181 ᵘs̲tep p 182} 183last ← 100000 'ᵘf̲rame p̲ower start 184"bye"