sourceextensions/scene/demos/Endless.xtl
1⍝# Endless.xtl -- the endless world and its player, shared by the voxel
2⍝# demos that walk or fly in it (voxels-endless, voxels-fly, and those
3⍝# after): columns of 16 by 16 blocks made around the player and dropped
4⍝# behind it, each made over three frames so no frame waits long, and the
5⍝# player -- walking, swimming, flying -- moving against them.
6⍝# Import: "en:" u_se< "Endless"
7
8ᵛˣ⁼u̲se< "Voxels"
9ˢᶜ⁼u̲se< "Scene"
10
11⍝## The state
12
13⍝# The state is a list of boxes of Floats (the boxes of one array share
14⍝# a type): 1 the player (ten numbers: x y z, vx vy vz, yaw, pitch, on
15⍝# the ground, flying), 2 the columns' keys, 3 their numbers (a column's
16⍝# scene objects are 10 * number + block), 4 the settings (the window,
17⍝# the next number, the job's part 0 to 2, the job's column cx cz and
18⍝# number, the start x y z), 5 the job's data, and from 6 on each
19⍝# column's solid mask, in the keys' order. Made by en:n_ew.
20
21⍝# the columns are kept this many (16-block steps) from the player's,
22⍝# each way, and made within it; beyond one more they are dropped
23ˡreach ← 3
24
25⍝# en:p_layer s: the player's ten numbers
26ˡp̲layer ← { s → d̲isclose 1 s̲elect s }
27⍝# en:k_eys s: the columns' keys
28ˡk̲eys ← { s → d̲isclose 2 s̲elect s }
29⍝# en:n_umbers s: the columns' numbers
30ˡn̲umbers ← { s → d̲isclose 3 s̲elect s }
31⍝# en:s_ettings s: the window, the next number, the job, the start
32ˡs̲ettings ← { s → d̲isclose 4 s̲elect s }
33⍝# en:w_indow s: the scene window the world is drawn in
34ˡw̲indow ← { s → 1 s̲elect ˡs̲ettings s }
35
36⍝ a column's key from its coordinates (cx cz), and back
37ʰk̲ey ← { c → f̲loat (10000 × 1000 + 1 s̲elect c) + 1000 + 2 s̲elect c }
38ʰc̲x ← { k → ((f̲loor k) d̲iv 10000) − 1000 }
39ʰc̲z ← { k → ((f̲loor k) m̲od 10000) − 1000 }
40
41⍝ the state with its keys (box 2), numbers (3), settings (4) or the
42⍝ job's data (5) replaced
43ʰw̲ithKeys ← { v s → (1 t̲ake s) c̲at (e̲nclose v) c̲at 2 d̲rop s }
44ʰw̲ithNumbers ← { v s → (2 t̲ake s) c̲at (e̲nclose v) c̲at 3 d̲rop s }
45ʰw̲ithSettings ← { v s → (3 t̲ake s) c̲at (e̲nclose v) c̲at 4 d̲rop s }
46ʰw̲ithJob ← { v s → (4 t̲ake s) c̲at (e̲nclose v) c̲at 5 d̲rop s }
47
48⍝# en:w_ithPlayer p s: the state with the player p
49ˡw̲ithPlayer ← { p s → (e̲nclose p) c̲at 1 d̲rop s }
50
51⍝# en:n_ew w: a world for window w, no columns made yet, the player
52⍝# standing above the highest ground of column (0, 0), facing north
53ˡn̲ew ← { w →
54 hv ← r̲avel ᵛˣh̲eightsAt 0 0 16
55 i ← f̲irst w̲here hv = 'm̲ax r̲/ hv
56 x ← (f̲loat (i − 1) d̲iv 16) + 0.5
57 y ← f̲loat 2 + i s̲elect hv
58 z ← (f̲loat (i − 1) m̲od 16) + 0.5
59 p ← x c̲at y c̲at z c̲at 0.0 0.0 0.0 0.0 0.0 0.0 0.0
60 none ← 0 r̲eshape 0.0
61 set ← (f̲loat w) c̲at 1.0 0.0 0.0 0.0 0.0 c̲at x c̲at y c̲at z
62 (e̲nclose p) c̲at (e̲nclose none) c̲at (e̲nclose none) c̲at (e̲nclose set) c̲at e̲nclose none
63}
64
65⍝# en:s_tart s: where the player started (x y z)
66ˡs̲tart ← { s → 3 t̲ake 6 d̲rop ˡs̲ettings s }
67
68⍝## Making and dropping columns
69
70⍝# the player's column (cx cz)
71ʰh̲ome ← { s →
72 p ← ˡp̲layer s
73 (f̲loor (1 s̲elect p) ÷ 16.0) c̲at f̲loor (3 s̲elect p) ÷ 16.0
74}
75
76⍝ the first column too far away, if any, dropped: its objects out of
77⍝ scene, its key, number and mask out of the state
78ʰt̲rim ← { s →
79 h ← ʰh̲ome s
80 ks ← ˡk̲eys s
81 far ← ((a̲bs (ʰc̲x ks) − 1 s̲elect h) > ˡreach + 1) + (a̲bs (ʰc̲z ks) − 2 s̲elect h) > ˡreach + 1
82 0 = '+ r̲/ far ? s
83 j ← f̲irst w̲here far > 0
84 n ← j s̲elect ˡn̲umbers s
85 w ← ˡw̲indow s
86 gone ← '{ w ˢᶜr̲emove! (10.0 × n) + f̲loat ⍵ } m̲ap r̲ange 7
87 keep ← j ≠ r̲ange t̲ally ks
88 s ← (keep r̲eplicate ks) ʰw̲ithKeys s
89 s ← (keep r̲eplicate ˡn̲umbers s) ʰw̲ithNumbers s
90 ((5 + j) t̲ake s) c̲at (6 + j) d̲rop s
91}
92
93⍝ (n t) s_endOne f: block t's faces of column n, one object of quads
94ʰs̲endOne ← { nt f →
95 w ← 1 s̲elect nt
96 t ← f̲loor 3 s̲elect nt
97 sel ← (5 s̲elect₂ f) = t
98 0 = '+ r̲/ sel ? 0
99 head ← (f̲loat w) c̲at ((10.0 × 2 s̲elect nt) + f̲loat t) c̲at (1 + t) s̲elect ᵛˣcolors
100 head ˢᶜq̲uads! ᵛˣc̲orners sel r̲eplicate f
101}
102
103⍝# en:s_tream s: one frame's work on the world: the first column too far
104⍝# away dropped, then a third of making a column -- the nearest missing
105⍝# one's blocks and solid mask (part 0), its faces (part 1), or sending
106⍝# them to scene (part 2) -- about 12 ms at most
107ˡs̲tream ← { s →
108 s ← ʰt̲rim s
109 set ← ˡs̲ettings s
110 part ← 3 s̲elect set
111 part = 1.0 ? ʰf̲aces s
112 part = 2.0 ? ʰs̲end s
113 ʰb̲locks s
114}
115
116⍝ part 0: the nearest missing column's blocks and mask; the column is
117⍝ known (collision sees it) from now on, drawn two frames later
118ʰb̲locks ← { s →
119 h ← ʰh̲ome s
120 ks ← ˡk̲eys s
121 r ← ˡreach
122 o ← (r̲ange 1 + 2 × r) − 1 + r
123 dx ← r̲avel o '+ t̲able 0 × o
124 dz ← r̲avel (0 × o) '+ t̲able o
125 ws ← f̲loat (10000 × 1000 + dx + 1 s̲elect h) + 1000 + dz + 2 s̲elect h
126 miss ← (0 = ws m̲ember? ks) r̲eplicate (r̲ange t̲ally ws)
127 0 = t̲ally miss ? s
128 d ← (miss s̲elect dx × dx) + miss s̲elect dz × dz
129 i ← f̲irst (d = 'm̲in r̲/ d) r̲eplicate miss
130 c ← ((i s̲elect dx) + 1 s̲elect h) c̲at (i s̲elect dz) + 2 s̲elect h
131 b ← ᵛˣc̲olumnBlocks c
132 set ← ˡs̲ettings s
133 n ← 2 s̲elect set
134 set ← (1 s̲elect set) c̲at (n + 1.0) c̲at 1.0 c̲at (f̲loat c) c̲at n c̲at 6 d̲rop set
135 s ← (ks c̲at i s̲elect ws) ʰw̲ithKeys s
136 s ← ((ˡn̲umbers s) c̲at n) ʰw̲ithNumbers s
137 s ← (set) ʰw̲ithSettings s
138 s ← (f̲loat r̲avel b) ʰw̲ithJob s
139 s c̲at e̲nclose f̲loat ᵛˣc̲olumnMask b
140}
141
142⍝ part 1: the job's faces, from its blocks
143ʰf̲aces ← { s →
144 set ← ˡs̲ettings s
145 c ← f̲loor 4 5 s̲elect set
146 b ← 18 32 18 r̲eshape f̲loor d̲isclose 5 s̲elect s
147 f ← c ᵛˣc̲olumnFaces b
148 s ← ((2 t̲ake set) c̲at 2.0 c̲at 3 d̲rop set) ʰw̲ithSettings s
149 (f̲loat r̲avel f) ʰw̲ithJob s
150}
151
152⍝ part 2: the job's faces to scene, one object for each kind of block
153ʰs̲end ← { s →
154 set ← ˡs̲ettings s
155 v ← d̲isclose 5 s̲elect s
156 f ← (((t̲ally v) d̲iv 5) c̲at 5) r̲eshape f̲loor v
157 n ← 6 s̲elect set
158 w ← 1 s̲elect set
159 sent ← '{ (w c̲at n c̲at f̲loat ⍵) ʰs̲endOne f } m̲ap r̲ange 7
160 s ← ((2 t̲ake set) c̲at 0.0 c̲at 3 d̲rop set) ʰw̲ithSettings s
161 (0 r̲eshape 0.0) ʰw̲ithJob s
162}
163
164⍝## Collision
165
166⍝ s c_ell v: whether any of the cells at column (x z) and heights ys (v
167⍝ is x z then the ys) is solid; a column not made yet is solid
168ʰc̲ell ← { s v →
169 x ← 1 s̲elect v
170 z ← 2 s̲elect v
171 ys ← 2 d̲rop v
172 i ← (ˡk̲eys s) i̲ndexOf ʰk̲ey (x d̲iv 16) c̲at z d̲iv 16
173 i > t̲ally ˡk̲eys s ? 1
174 m ← d̲isclose (5 + i) s̲elect s
175 0 < '+ r̲/ (1 + (z m̲od 16) + 16 × ys + 32 × x m̲od 16) s̲elect m
176}
177
178⍝# s en:h_it q: whether the player's box (0.6 wide, 1.75 tall) with its
179⍝# feet at q (x y z) overlaps a solid block; below the world is solid,
180⍝# above it air
181ˡh̲it ← { s q →
182 x ← 1 s̲elect q
183 y ← 2 s̲elect q
184 z ← 3 s̲elect q
185 cx ← u̲nique f̲loor (x − 0.3) c̲at x + 0.3
186 cy ← u̲nique f̲loor y c̲at (y + 0.9) c̲at y + 1.75
187 cz ← u̲nique f̲loor (z − 0.3) c̲at z + 0.3
188 0 < '+ r̲/ cy < 0 ? 1.0
189 cy ← (cy ≤ 31) r̲eplicate cy
190 0 = t̲ally cy ? 0.0
191 px ← r̲avel cx '{ ⍺ + 0 × ⍵ } t̲able cz
192 pz ← r̲avel cx '{ ⍵ + 0 × ⍺ } t̲able cz
193 hits ← '{ s ʰc̲ell (⍵ s̲elect px) c̲at (⍵ s̲elect pz) c̲at cy } e̲ach r̲ange t̲ally px
194 f̲loat 0 < '+ r̲/ hits
195}
196
197⍝## The player
198
199⍝# a frame: 1/60 s
200ˡdt ← 1.0 ÷ 60.0
201
202⍝ (i v) s_et p: the player with number i replaced by v
203ʰs̲et ← { l p → p + (f̲loat (r̲ange 10) = f̲loor 1 s̲elect l) × (2 s̲elect l) − p }
204
205⍝ v s_nap a: where to stop, moving at v, before the block at a
206ʰs̲nap ← { v a →
207 v > 0.0 ? (f̲loat f̲loor a + 0.3) − 0.3001
208 (f̲loat 1 + f̲loor a − 0.3) + 0.3001
209}
210
211⍝ the three axes of a move against the world s: x and z stop at a wall;
212⍝ y lands (on the ground) or bumps a ceiling
213ʰm̲x ← { s p →
214 a ← (1 s̲elect p) + ˡdt × 4 s̲elect p
215 q ← (1 c̲at a) ʰs̲et p
216 0 = s ˡh̲it q ? q
217 (4 c̲at 0.0) ʰs̲et (1 c̲at (4 s̲elect p) ʰs̲nap a) ʰs̲et p
218}
219ʰm̲z ← { s p →
220 a ← (3 s̲elect p) + ˡdt × 6 s̲elect p
221 q ← (3 c̲at a) ʰs̲et p
222 0 = s ˡh̲it q ? q
223 (6 c̲at 0.0) ʰs̲et (3 c̲at (6 s̲elect p) ʰs̲nap a) ʰs̲et p
224}
225ʰm̲y ← { s p →
226 a ← (2 s̲elect p) + ˡdt × 5 s̲elect p
227 q ← (9 c̲at 0.0) ʰs̲et (2 c̲at a) ʰs̲et p
228 0 = s ˡh̲it q ? q
229 (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
230 (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
231}
232
233⍝# s en:m_ove k: one frame of the player under the controls k (mouse dx
234⍝# dy, then 1 for each held: w a s d space shift left right up down),
235⍝# walking or flying, the camera set to its eye. Walking: W A S D, Shift
236⍝# runs, Space jumps; in water (all air below the sea at 14) it sinks
237⍝# slowly, Space swims up, and from the surface Space climbs onto a bank
238⍝# one block high. Flying: W A S D level by the heading, Space up, Shift
239⍝# down, 15 blocks a second, no gravity, the blocks still stopping it.
240ˡm̲ove ← { s k →
241 p ← ˡp̲layer s
242 yaw ← (7 s̲elect p) + (0.005 × 1 s̲elect k) + 2.0 × ˡdt × (10 s̲elect k) − 9 s̲elect k
243 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
244 fwd ← (3 s̲elect k) − 5 s̲elect k
245 side ← (6 s̲elect k) − 4 s̲elect k
246 fly ← 10 s̲elect p
247 wet ← (1.0 − fly) × f̲loat 14.0 > 0.9 + 2 s̲elect p
248 speed ← (fly × 15.0) + (1.0 − fly) × (1.0 − 0.4 × wet) × 4.5 × 1.0 + 8 s̲elect k
249 vx ← speed × ((s̲in yaw) × fwd) + (c̲os yaw) × side
250 vz ← speed × ((0.0 − c̲os yaw) × fwd) + (s̲in yaw) × side
251 surface ← (1.0 − fly) × (f̲loat 14.5 > 2 s̲elect p) × f̲loat 13.0 < 2 s̲elect p
252 jump ← (1.0 − fly) × (1.0 m̲in (9 s̲elect p) + surface × 1.0 − wet) × 7 s̲elect k
253 swim ← wet × 7 s̲elect k
254 fall ← -30.0 m̲ax (5 s̲elect p) − 22.0 × ˡdt
255 sink ← -2.0 m̲ax (5 s̲elect p) − 6.0 × ˡdt
256 walkVy ← (7.5 × jump) + (1.0 − jump) × (4.0 × swim) + (1.0 − swim) × (wet × sink) + (1.0 − wet) × fall
257 flyVy ← ((80.0 − 2 s̲elect p) × 60.0) m̲in 15.0 × (7 s̲elect k) − 8 s̲elect k
258 vy ← (fly × flyVy) + (1.0 − fly) × walkVy
259 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
260 p ← s ʰm̲y s ʰm̲z s ʰm̲x p
261 e ← (ˡw̲indow s) ˢᶜ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
262 p ˡw̲ithPlayer s
263}
264
265⍝# en:h_omeAgain s: the player back at the start, standing still,
266⍝# walking
267ˡh̲omeAgain ← { s → ((ˡs̲tart s) c̲at 0.0 0.0 0.0 0.0 0.0 0.0 0.0) ˡw̲ithPlayer s }
268
269⍝# en:t_oggleFly s: flying, or walking again (falling from where it is)
270ˡt̲oggleFly ← { s →
271 p ← ˡp̲layer s
272 ((6 t̲ake p) c̲at (7 8 s̲elect p) c̲at 0.0 c̲at 1.0 − 10 s̲elect p) ˡw̲ithPlayer s
273}
274
275⍝# en:s_top s: the state marked as finished (the next number negative)
276ˡs̲top ← { s → ((1 t̲ake ˡs̲ettings s) c̲at (0.0 − 2 s̲elect ˡs̲ettings s) c̲at 2 d̲rop ˡs̲ettings s) ʰw̲ithSettings s }
277⍝# en:s_topped s: whether the state is marked as finished
278ˡs̲topped ← { s → 0.0 > 2 s̲elect ˡs̲ettings s }