code wiki / (root) / nx_scene_demo.nx

nx_scene_demo.nx source

↩ module page · 106 lines · 5297 B

1// nx_scene_demo.nx -- SOVEREIGN VISUAL ENGINE: sprites + Image->browser-canvas. 2// 3// Reuses nx_image (RGB container) for the framebuffer; adds color drawing 4// (px/fill_rect), pixel-art SPRITE blit (palette index grid, 0=transparent), a 5// small game scene, and the missing bridge: emit a rendered Image as a scaled, 6// pixel-perfect HTML canvas (base64 RGB -> ImageData). No external images, no 7// library -- pixels authored in .nx. license_tier: ORIGINAL. 8 9import "nx_syscalls.nx" 10import "nx_image.nx" 11import "nx_base64.nx" 12const K_MAGIC_262144: i64 = 262144 13 14func sc_px(img: *Image, x: i64, y: i64, r: i64, g: i64, b: i64) -> i64 { 15 nx_image_set(img, x, y, 0, r) 16 nx_image_set(img, x, y, 1, g) 17 nx_image_set(img, x, y, 2, b) 18 return 0 19} 20func sc_fill(img: *Image, x0: i64, y0: i64, w: i64, h: i64, r: i64, g: i64, b: i64) -> i64 { 21 var y: i64 = y0 22 while y < y0 + h { var x: i64 = x0; while x < x0 + w { sc_px(img, x, y, r, g, b); x = x + 1 } y = y + 1 } 23 return 0 24} 25// blit an 8x8 sprite from a 64-char index string ('0'=transparent) with one color 26func sc_blit8(img: *Image, dx: i64, dy: i64, grid: *u8, r: i64, g: i64, b: i64) -> i64 { 27 var i: i64 = 0 28 while i < 64 { 29 if grid[i] != (48 as u8) { // not '0' 30 sc_px(img, dx + (i % 8), dy + (i / 8), r, g, b) 31 } 32 i = i + 1 33 } 34 return 0 35} 36 37func sc_app(out: *u8, off: *i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { out[off[0]] = s[i]; off[0] = off[0] + 1; i = i + 1 } return 0 } 38func sc_app_n(out: *u8, off: *i64, v: i64) -> i64 { 39 let t: *u8 = sys_mmap(28); var m: i64 = v; var k: i64 = 0 40 if m == 0 { t[0] = 48 as u8; k = 1 } 41 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 42 var q: i64 = k - 1; while q >= 0 { out[off[0]] = t[q]; off[0] = off[0] + 1; q = q - 1 } 43 return 0 44} 45 46// build a small game scene into a fresh RGB image; returns the image 47func nx_scene_build() -> *Image { 48 let W: i64 = 64 49 let H: i64 = 48 50 let img: *Image = nx_image_alloc(W, H, 3) 51 sc_fill(img, 0, 0, W, 28, 135, 206, 235) // sky 52 sc_fill(img, 0, 28, W, 20, 92, 160, 74) // grass 53 // factory: body, roof, chimney, door, windows 54 sc_fill(img, 8, 18, 22, 14, 120, 124, 132) // body 55 sc_fill(img, 8, 14, 22, 4, 80, 84, 92) // roof 56 sc_fill(img, 24, 8, 4, 7, 70, 74, 82) // chimney 57 sc_fill(img, 16, 25, 5, 7, 60, 44, 30) // door 58 sc_fill(img, 11, 21, 4, 4, 200, 230, 255) // window 59 sc_fill(img, 22, 21, 4, 4, 200, 230, 255) // window 60 // store (right) 61 sc_fill(img, 40, 20, 18, 12, 150, 90, 70) // body 62 sc_fill(img, 39, 16, 20, 4, 200, 70, 60) // awning 63 sc_fill(img, 46, 25, 6, 7, 230, 220, 180) // door 64 // coins (gold pixel-art discs) 65 let coin: *u8 = "0011110001111110111111111111111111111111111111110111111000111100" as *u8 66 sc_blit8(img, 33, 34, coin, 255, 200, 40) 67 sc_blit8(img, 45, 36, coin, 255, 200, 40) 68 sc_blit8(img, 21, 37, coin, 255, 200, 40) 69 return img 70} 71 72// emit `img` (RGB) as a scaled pixel-perfect HTML canvas page; returns length 73func nx_img_canvas_page(img: *Image, scale: i64, out: *u8, cap: i64) -> i64 { 74 let W: i64 = img.width 75 let H: i64 = img.height 76 let nbytes: i64 = W * H * 3 77 let b64: *u8 = sys_mmap(nbytes * 2 + 64) 78 let bn: i64 = b64_encode(img.pixels, nbytes, b64) 79 let off: *i64 = (sys_mmap(8)) as *i64 80 off[0] = 0 81 sc_app(out, off, "<!doctype html><html><head><meta charset=\"utf-8\"><title>Nishi Scene</title></head><body style=\"background:#111;text-align:center\">" as *u8) 82 sc_app(out, off, "<h2 style=\"color:#dde;font-family:sans-serif\">Sovereign render &mdash; pixels authored in NishiLang, no images, no library</h2>" as *u8) 83 sc_app(out, off, "<canvas id=c width=" as *u8); sc_app_n(out, off, W * scale) 84 sc_app(out, off, " height=" as *u8); sc_app_n(out, off, H * scale) 85 sc_app(out, off, " style=\"image-rendering:pixelated;border:2px solid #444\"></canvas><script>var W=" as *u8); sc_app_n(out, off, W) 86 sc_app(out, off, ",H=" as *u8); sc_app_n(out, off, H) 87 sc_app(out, off, ",S=" as *u8); sc_app_n(out, off, scale) 88 sc_app(out, off, ",b=\"" as *u8) 89 var i: i64 = 0 90 while i < bn { out[off[0]] = b64[i]; off[0] = off[0] + 1; i = i + 1 } 91 sc_app(out, off, "\";var r=atob(b),o=document.createElement('canvas');o.width=W;o.height=H;var x=o.getContext('2d'),d=x.createImageData(W,H),p=0,i2=0;for(i2=0;i2<W*H;i2++){d.data[i2*4]=r.charCodeAt(p++);d.data[i2*4+1]=r.charCodeAt(p++);d.data[i2*4+2]=r.charCodeAt(p++);d.data[i2*4+3]=255;}x.putImageData(d,0,0);var c=document.getElementById('c'),t=c.getContext('2d');t.imageSmoothingEnabled=false;t.drawImage(o,0,0,W*S,H*S);</script></body></html>\n" as *u8) 92 out[off[0]] = 0 as u8 93 return off[0] 94} 95 96func nx_scene_save(path: *u8, scale: i64) -> i64 { 97 let img: *Image = nx_scene_build() 98 let out: *u8 = sys_mmap(K_MAGIC_262144) 99 let len: i64 = nx_img_canvas_page(img, scale, out, K_MAGIC_262144) 100 let fd: i64 = sys_openat_wr(path, 420) 101 if fd < 0 { return 0 - 1 } 102 var wr: i64 = 0 103 while wr < len { let c: i64 = sys_write(fd, out + wr, len - wr); if c <= 0 { break } wr = wr + c } 104 sys_close(fd) 105 return wr 106}