petal

Specimen · starfield.ptl

Starfield

A 3D star projection with motion trails. Warp speed, ~30 lines.

3dgenerative
starfield.ptl
compiling petal…
starfield.ptl
1// Starfield — warp drive.
2// 3D star projection with motion trails.
3 
4state stars = []
5state initialized = false
6 
7let cx = float(screen_width()) / 2.0
8let cy = float(screen_height()) / 2.0
9let delta = dt()
10let depth = 1000.0
11let fov = 400.0
12 
13fn clip(v)
14 if v > 30000.0 then 30000.0 else if v < -30000.0 then -30000.0 else v end end
15end
16 
17if !initialized then
18 let temp = []
19 for i in range(0, 200) do
20 push(temp, {
21 x: random(-400.0, 400.0),
22 y: random(-300.0, 300.0),
23 z: random(50.0, depth),
24 pz: depth
25 })
26 end
27 stars = temp
28 initialized = true
29end
30 
31let speed = 300.0
32let new_stars = []
33for s in stars do
34 let pz = s.z
35 let nz = s.z - speed * delta
36 
37 if nz < 30.0 then
38 push(new_stars, {
39 x: random(-400.0, 400.0),
40 y: random(-300.0, 300.0),
41 z: depth,
42 pz: depth
43 })
44 else
45 push(new_stars, { x: s.x, y: s.y, z: nz, pz: pz })
46 end
47end
48stars = new_stars
49 
50// === Draw ===
51clear(0, 0, 8)
52 
53for s in stars do
54 let sx = clip(s.x / s.z * fov + cx)
55 let sy = clip(s.y / s.z * fov + cy)
56 let psx = clip(s.x / s.pz * fov + cx)
57 let psy = clip(s.y / s.pz * fov + cy)
58 
59 let brightness = int((1.0 - s.z / depth) * 255.0)
60 let b = min(255, max(40, brightness))
61 draw_line(int(psx), int(psy), int(sx), int(sy), b, b, b)
62end
63 
64draw_text("Starfield", 16, 12, 14, 180, 180, 220)

The whole program is the source above — there is no hidden runtime. Petal re-runs it every frame: state values persist between frames, draw calls paint to the canvas, and edits take effect live. Open it in the playground to poke at the numbers and watch the picture change.