code wiki / (root) / nx_wasm_thirdperson.nx

nx_wasm_thirdperson.nx source

↩ module page · 119 lines · 5294 B

1// nx_wasm_thirdperson.nx -- BROWSER-PLAYABLE sovereign Third-Person explorer: BASE-RELATIVE integer core, runs 2// native (-> PNG) AND in the browser (base = 0). NO float, NO JS logic, NO canvas drawing. A FOLLOW CAMERA 3// keeps the avatar centered while a world LARGER than the screen scrolls under it; move 4-directionally to 4// collect every item then reach the goal (win). init()/tick(input)/render()/score()/ww()/hh()/fb_off() = the 5// wasm interface; input bits 1=up 2=down 4=left 8=right. license_tier: ORIGINAL 6import "nx_nishi_font_core.nx" 7const W: i64 = 128 // viewport 8const H: i64 = 112 9const WW: i64 = 288 // world 10const WH: i64 = 224 11const NI: i64 = 5 12const MOVE: i64 = 2 13const O_FB: i64 = 0 // framebuffer W*H i64 14const O_IX: i64 = 114688 // item world-x[16] (W*H*8) 15const O_IY: i64 = 114816 16const O_IG: i64 = 114944 // item collected[16] 17const O_ST: i64 = 115072 // scalars[16]: 0=wx 1=wy 2=collected 3=won 4=gx 5=gy 18const O_MSK: i64 = 115200 19const O_STR: i64 = 123392 20 21func rgb(r: i64, g: i64, b: i64) -> i64 { return (r & 255) | ((g & 255) << 8) | ((b & 255) << 16) } 22func clampi(v: i64, lo: i64, hi: i64) -> i64 { if v < lo { return lo } if v > hi { return hi } return v } 23func iabs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 24 25func fillr(base: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 { 26 let fb: *i64 = (base + O_FB) as *i64 27 var yy: i64 = y0; if yy < 0 { yy = 0 } 28 var ye: i64 = y1; if ye > H { ye = H } 29 while yy < ye { 30 var xx: i64 = x0; if xx < 0 { xx = 0 } 31 var xe: i64 = x1; if xe > W { xe = W } 32 while xx < xe { fb[yy*W + xx] = c; xx = xx + 1 } 33 yy = yy + 1 34 } 35 return 0 36} 37func disc(base: i64, cx: i64, cy: i64, rad: i64, c: i64) -> i64 { 38 let fb: *i64 = (base + O_FB) as *i64 39 var dy: i64 = 0 - rad; let r2: i64 = rad*rad 40 while dy <= rad { 41 var dx: i64 = 0 - rad 42 while dx <= rad { 43 if dx*dx + dy*dy <= r2 { let x: i64 = cx+dx; let y: i64 = cy+dy 44 if x >= 0 { if y >= 0 { if x < W { if y < H { fb[y*W + x] = c } } } } } 45 dx = dx + 1 46 } 47 dy = dy + 1 48 } 49 return 0 50} 51 52func init_impl(base: i64) -> i64 { 53 let ix: *i64 = (base + O_IX) as *i64 54 let iy: *i64 = (base + O_IY) as *i64 55 let ig: *i64 = (base + O_IG) as *i64 56 let st: *i64 = (base + O_ST) as *i64 57 ix[0]=40; iy[0]=40; ix[1]=248; iy[1]=40; ix[2]=40; iy[2]=184; ix[3]=248; iy[3]=184; ix[4]=144; iy[4]=150 58 var i: i64 = 0; while i < NI { ig[i] = 0; i = i + 1 } 59 st[0]=144; st[1]=64; st[2]=0; st[3]=0; st[4]=250; st[5]=196 60 return 0 61} 62 63func tick_impl(base: i64, input: i64) -> i64 { 64 let ix: *i64 = (base + O_IX) as *i64 65 let iy: *i64 = (base + O_IY) as *i64 66 let ig: *i64 = (base + O_IG) as *i64 67 let st: *i64 = (base + O_ST) as *i64 68 if (input & 1) != 0 { st[1] = clampi(st[1] - MOVE, 8, WH - 8) } 69 if (input & 2) != 0 { st[1] = clampi(st[1] + MOVE, 8, WH - 8) } 70 if (input & 4) != 0 { st[0] = clampi(st[0] - MOVE, 8, WW - 8) } 71 if (input & 8) != 0 { st[0] = clampi(st[0] + MOVE, 8, WW - 8) } 72 var i: i64 = 0 73 while i < NI { 74 if ig[i] == 0 { if iabs(st[0] - ix[i]) < 9 { if iabs(st[1] - iy[i]) < 9 { ig[i] = 1; st[2] = st[2] + 1 } } } 75 i = i + 1 76 } 77 if iabs(st[0] - st[4]) < 11 { if iabs(st[1] - st[5]) < 11 { if st[2] == NI { st[3] = 1 } } } 78 return 0 79} 80 81func render_impl(base: i64) -> i64 { 82 let fb: *i64 = (base + O_FB) as *i64 83 let ix: *i64 = (base + O_IX) as *i64 84 let iy: *i64 = (base + O_IY) as *i64 85 let ig: *i64 = (base + O_IG) as *i64 86 let st: *i64 = (base + O_ST) as *i64 87 let camx: i64 = clampi(st[0] - W/2, 0, WW - W) 88 let camy: i64 = clampi(st[1] - H/2, 0, WH - H) 89 // checker floor (only visible tiles) 90 var ty: i64 = camy/16 91 while ty*16 - camy < H { 92 var tx: i64 = camx/16 93 while tx*16 - camx < W { 94 var col: i64 = rgb(40, 70, 46); if ((tx + ty) & 1) == 1 { col = rgb(48, 84, 54) } 95 fillr(base, tx*16 - camx, ty*16 - camy, tx*16 + 16 - camx, ty*16 + 16 - camy, col) 96 tx = tx + 1 97 } 98 ty = ty + 1 99 } 100 fillr(base, st[4]-camx-7, st[5]-camy-7, st[4]-camx+7, st[5]-camy+7, rgb(90, 210, 220)) // goal (cyan) 101 var i: i64 = 0 102 while i < NI { if ig[i] == 0 { disc(base, ix[i]-camx, iy[i]-camy, 4, rgb(245, 210, 70)) } i = i + 1 } 103 fillr(base, st[0]-camx-5, st[1]-camy-5, st[0]-camx+5, st[1]-camy+5, rgb(90, 210, 122)) // avatar (green) 104 if st[3] == 1 { fillr(base, 0,0,W,3, rgb(90,220,120)); fillr(base, 0,H-3,W,H, rgb(90,220,120)); fillr(base, 0,0,3,H, rgb(90,220,120)); fillr(base, W-3,0,W,H, rgb(90,220,120)) } 105 // HUD: collected / NI 106 let sbuf: *u8 = (base + O_STR) as *u8 107 sbuf[0] = (48 + st[2]) as u8; sbuf[1] = 47 as u8; sbuf[2] = (48 + NI) as u8 108 let mask: *u8 = (base + O_MSK) as *u8 109 nf_draw_text_mem(fb, W, H, mask, 4, 3, 16, sbuf, 3, rgb(235, 240, 250)) 110 return 0 111} 112 113func init() -> i64 { return init_impl(0) } 114func tick(input: i64) -> i64 { return tick_impl(0, input) } 115func render() -> i64 { return render_impl(0) } 116func score() -> i64 { let st: *i64 = (0 + O_ST) as *i64; return st[2] } 117func fb_off() -> i64 { return O_FB } 118func ww() -> i64 { return W } 119func hh() -> i64 { return H }