code wiki / _hdl_build / nx_game_art.nx

nx_game_art.nx source

↩ module page · 87 lines · 3926 B

1// nx_game_art.nx -- shared RICH-render primitives, the answer to nx_game_critic's TOY verdict. The games 2// scored TOY (120) because they draw flat discs on a near-empty starfield: palette ~10, gradient 0, 3// coverage ~180. These primitives lift all three axes: 2D gradient nebulas (palette+gradient+coverage), 4// radial-falloff glow orbs (gradient+detail), star dust (palette), gradient meters (gradient). ONE 5// definition, used by nx_frontier_engine, nx_drift_engine, and the critic's reference frame -- OO 6// consolidation of the look, so improving the art improves every game at once. LIB. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_game_raster.nx" 9const K_MAGIC_2654435761: i64 = 2654435761 10const K_MAGIC_40503: i64 = 40503 11 12func art_clampb(v: i64) -> i64 { if v<0 { return 0 } if v>255 { return 255 } return v } 13 14// 2D gradient nebula background with per-pixel texture: colour ramps top->bottom AND left->right, plus a 15// cheap deterministic noise so no two pixels are identical (kills the flat-fill palette collapse). 16func art_nebula(fb: *i64, w: i64, h: i64, r0: i64, g0: i64, b0: i64, r1: i64, g1: i64, b1: i64) -> i64 { 17 var y: i64=0 18 while y<h { 19 var x: i64=0 20 while x<w { 21 let ty: i64 = y*256/h 22 let tx: i64 = x*256/w 23 let nz: i64 = ((x*13 + y*7 + (x/5)*(y/9)) % 15) - 7 24 let rr: i64 = art_clampb(r0 + (r1-r0)*ty/256 + (r1-r0)*tx/768 + nz) 25 let gg: i64 = art_clampb(g0 + (g1-g0)*ty/256 + (g1-g0)*tx/768 + nz) 26 let bb: i64 = art_clampb(b0 + (b1-b0)*ty/256 + (b1-b0)*tx/768 + nz) 27 fb[y*w+x] = gr_pack(rr,gg,bb) 28 x=x+1 29 } 30 y=y+1 31 } 32 return 0 33} 34 35// varied-brightness star dust (adds palette + fine detail without flattening) 36func art_stardust(fb: *i64, w: i64, h: i64, count: i64) -> i64 { 37 var s: i64=0 38 while s<count { 39 var px: i64 = (s*K_MAGIC_2654435761)%w 40 if px<0 { px=0-px } 41 var py: i64 = (s*K_MAGIC_40503+17)%(h-40) 42 if py<0 { py=0-py } 43 let b: i64 = 40 + (s*37)%150 44 gr_px(fb, w, h, px%w, py, gr_pack(b, b, art_clampb(b+25))) 45 if (s%5)==0 { gr_px(fb, w, h, (px+1)%w, py, gr_pack(b*3/4, b*3/4, b)) } 46 s=s+1 47 } 48 return 0 49} 50 51// a glowing orb: concentric discs with a smooth radial falloff (bright core -> dim halo) + a lit rim. 52// This is the single biggest lever from flat discs -> RICH: it fills a gradient where a flat disc had one colour. 53func art_glow_orb(fb: *i64, w: i64, h: i64, cx: i64, cy: i64, rad: i64, cr: i64, cg: i64, cb: i64) -> i64 { 54 // outer halo (dim, large) 55 var r: i64 = rad+rad/2 56 while r>rad { 57 let k: i64 = (r-rad)*220/(rad/2+1) 58 gr_disc(fb, w, h, cx, cy, r, gr_pack(art_clampb(cr*(60-k/4)/200), art_clampb(cg*(60-k/4)/200), art_clampb(cb*(70-k/4)/200))) 59 r=r-1 60 } 61 // body: bright core fading to edge 62 r = rad 63 while r>=1 { 64 let k: i64 = r*256/rad 65 gr_disc(fb, w, h, cx, cy, r, gr_pack(art_clampb(cr*(320-k)/300), art_clampb(cg*(320-k)/300), art_clampb(cb*(320-k)/300))) 66 r=r-1 67 } 68 // hot core + a specular pip offset up-left (a lit sphere read) 69 gr_disc(fb, w, h, cx, cy, rad/4, gr_pack(250,250,255)) 70 gr_disc(fb, w, h, cx-rad/3, cy-rad/3, rad/7+1, gr_pack(255,255,255)) 71 return 0 72} 73 74// a gradient-filled meter (many shades across its length) -- replaces the flat-colour HUD bar 75func art_meter(fb: *i64, w: i64, h: i64, x: i64, y: i64, len: i64, ht: i64, filled: i64, r0: i64, g0: i64, b0: i64, r1: i64, g1: i64, b1: i64) -> i64 { 76 // track 77 gr_rect(fb, w, h, x, y, x+len, y+ht, gr_pack(26,24,42)) 78 var i: i64=0 79 while i<filled { 80 if i<len { 81 let t: i64 = i*256/(len) 82 gr_rect(fb, w, h, x+i, y, x+i+1, y+ht, gr_pack(art_clampb(r0+(r1-r0)*t/256), art_clampb(g0+(g1-g0)*t/256), art_clampb(b0+(b1-b0)*t/256))) 83 } 84 i=i+1 85 } 86 return 0 87}