{"name":"starfield.nu","source":"// starfield.nu — 3D Warp Speed Starfield with Motion Blur\n// NURL Canvas demo.\n\n& `libc` @ rand → i\n\n& `canvas` @ canvas_open i w i h → *i\n\n& `canvas` @ canvas_present → v\n\n& `canvas` @ canvas_sleep i ms → v\n\n& `canvas` @ canvas_should_close → i\n\n& `canvas` @ canvas_close → v\n\n// Suurempi resoluutio ja 60 FPS\n: i W 640\n: i H 360\n: i FPS 60\n: i NUM_STARS 1000\n\n@ main → i {\n    // Varataan taulukot tähtien 3D-koordinaateille\n    : *i stars_x # *i ( malloc * NUM_STARS 8 )\n    : *i stars_y # *i ( malloc * NUM_STARS 8 )\n    : *i stars_z # *i ( malloc * NUM_STARS 8 )\n\n    // Alustetaan tähdet satunnaisiin paikkoihin\n    : ~ i init_idx 0\n    ~ < init_idx NUM_STARS {\n        // Arvotaan X ja Y väliltä -2000 ... 2000\n        = . stars_x init_idx - % ( rand ) 4000 2000\n        = . stars_y init_idx - % ( rand ) 4000 2000\n        // Arvotaan Z (syvyys) väliltä 1 ... 1000\n        = . stars_z init_idx + 1 % ( rand ) 1000\n        = init_idx + init_idx 1\n    }\n\n    : *i fb ( canvas_open W H )\n    : i frame_ms / 1000 FPS\n    : ~ i t 0\n\n    ~ == 0 ( canvas_should_close ) {\n        // 1. MOTION BLUR\n        // Koko ruudun mustaamisen sijaan himmennetään kaikkia pikseleitä.\n        : ~ i px_idx 0\n        : i total_px * W H\n        ~ < px_idx total_px {\n            : i old . fb px_idx\n            // Maskataan 0x00FEFEFE (16711422) jotta kanavat eivät vuoda yli\n            // ja jaetaan kahdella (bitti kerrallaan oikealle).\n            : i masked & old 16711422\n            : i faded / masked 2\n            // Palautetaan läpinäkymätön alpha (0xFF000000 = 4278190080)\n            = . fb px_idx | 4278190080 faded\n            = px_idx + px_idx 1\n        }\n\n        // 2. Sykkivä vauhti \"warp-moottorille\" (kolmioaalto)\n        : i cycle % t 100\n        : i speed + 5 ? < cycle 50 cycle - 100 cycle\n\n        // 3. Tähtien päivitys ja piirto\n        : ~ i i 0\n        ~ < i NUM_STARS {\n            // Tähti liikkuu kameraa kohti\n            = . stars_z i - . stars_z i speed\n\n            // Jos tähti ohittaa kameran, nollataan se kauas taakse\n            ? <= . stars_z i 0 {\n                = . stars_z i 1000\n                = . stars_x i - % ( rand ) 4000 2000\n                = . stars_y i - % ( rand ) 4000 2000\n            } {}\n\n            // 3D -> 2D projektio (FOV-kerroin 300)\n            : i z . stars_z i\n            : i sx + / W 2 / * . stars_x i 300 z\n            : i sy + / H 2 / * . stars_y i 300 z\n\n            // Piirretään pikseli vain, jos se on ruudun sisällä\n            ? & & >= sx 0 < sx W & >= sy 0 < sy H {\n                // Mitä lähempänä (pienempi z), sen kirkkaampi (0-255)\n                : i intensity - 255 / * z 255 1000\n\n                // Generoidaan tähdille vähän väriä indeksin mukaan\n                : i c_mod % i 3\n                // Sinertävä\n                : i r ? == c_mod 1 / intensity 2 intensity\n                // Kellertävä / normaali\n                : i g ? == c_mod 1 / intensity 2 intensity\n                // Valkoinen\n                : i b ? == c_mod 2 / intensity 2 intensity\n\n                // ARGB-pakkaus: 0xFF000000 | (r<<16) | (g<<8) | b\n                : i color | 4278190080 | | * r 65536 * g 256 b\n\n                = . fb + * sy W sx color\n            } {}\n\n            = i + i 1\n        }\n\n        ( canvas_present )\n        ( canvas_sleep frame_ms )\n        = t + t 1\n    }\n\n    ( canvas_close )\n    ^ 0\n}\n","bytes":3426}