code wiki / (root) / nx_wasm_racing.nx

nx_wasm_racing.nx source

↩ module page · 124 lines · 5095 B

1// nx_wasm_racing.nx -- BROWSER-PLAYABLE sovereign Racing: BASE-RELATIVE integer core, runs native (-> PNG) AND 2// in the browser (base = 0 = our sovereign WASM linear memory). NO float, NO JS logic, NO canvas drawing. A 3// top-down endless dodge racer: hold left/right to steer the car between descending traffic; survive to grow 4// the distance score; a collision ends the run (shoot/space restarts). init()/tick(input)/render()/score()/ 5// ww()/hh()/fb_off() = the wasm interface (auto-exported). license_tier: ORIGINAL 6import "nx_nishi_font_core.nx" 7const O_MAGIC_7919: i64 = 7919 8const W: i64 = 120 9const H: i64 = 180 10const NO: i64 = 5 11const SY: i64 = 156 // player row 12const SPEED: i64 = 2 13const O_FB: i64 = 0 // framebuffer W*H i64 at offset 0 14const O_OX: i64 = 172800 // opponent x[16] (W*H*8) 15const O_OY: i64 = 172928 // opponent y[16] 16const O_ST: i64 = 173056 // scalars[16]: 0=px 1=distance 2=gameover 3=tick 17const O_MSK: i64 = 173184 // HUD glyph scratch 18const O_STR: i64 = 181376 // HUD string scratch 19 20func rgb(r: i64, g: i64, b: i64) -> i64 { return (r & 255) | ((g & 255) << 8) | ((b & 255) << 16) } 21 22func fillr(base: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 { 23 let fb: *i64 = (base + O_FB) as *i64 24 var yy: i64 = y0; if yy < 0 { yy = 0 } 25 var ye: i64 = y1; if ye > H { ye = H } 26 while yy < ye { 27 var xx: i64 = x0; if xx < 0 { xx = 0 } 28 var xe: i64 = x1; if xe > W { xe = W } 29 while xx < xe { fb[yy*W + xx] = c; xx = xx + 1 } 30 yy = yy + 1 31 } 32 return 0 33} 34 35func respawn(base: i64, i: i64) -> i64 { 36 let ox: *i64 = (base + O_OX) as *i64 37 let oy: *i64 = (base + O_OY) as *i64 38 let st: *i64 = (base + O_ST) as *i64 39 oy[i] = 0 - (14 + ((st[3]*13 + i*37) % 50)) 40 ox[i] = 18 + ((st[3]*O_MAGIC_7919 + i*131) % (W - 36)) 41 return 0 42} 43 44func init_impl(base: i64) -> i64 { 45 let oy: *i64 = (base + O_OY) as *i64 46 let ox: *i64 = (base + O_OX) as *i64 47 let st: *i64 = (base + O_ST) as *i64 48 st[0] = W/2; st[1] = 0; st[2] = 0; st[3] = 0 49 var i: i64 = 0 50 while i < NO { oy[i] = 0 - (24 + i*38); ox[i] = 18 + (i*21) % (W - 36); i = i + 1 } 51 return 0 52} 53 54func tick_impl(base: i64, input: i64) -> i64 { 55 let ox: *i64 = (base + O_OX) as *i64 56 let oy: *i64 = (base + O_OY) as *i64 57 let st: *i64 = (base + O_ST) as *i64 58 if st[2] == 1 { if (input & 4) != 0 { init_impl(base) } return 0 } 59 if (input & 1) != 0 { st[0] = st[0] - 3; if st[0] < 14 { st[0] = 14 } } 60 if (input & 2) != 0 { st[0] = st[0] + 3; if st[0] > W-14 { st[0] = W-14 } } 61 var i: i64 = 0 62 while i < NO { 63 oy[i] = oy[i] + SPEED 64 if oy[i] > H + 14 { respawn(base, i) } 65 var dx: i64 = st[0] - ox[i]; if dx < 0 { dx = 0 - dx } 66 var dy: i64 = SY - oy[i]; if dy < 0 { dy = 0 - dy } 67 if dx < 14 { if dy < 15 { st[2] = 1 } } 68 i = i + 1 69 } 70 if st[2] == 0 { st[1] = st[1] + 1 } 71 st[3] = st[3] + 1 72 return 0 73} 74 75func car(base: i64, cx: i64, cy: i64, body: i64, top: i64) -> i64 { 76 fillr(base, cx-9, cy-12, cx+9, cy+12, body) 77 fillr(base, cx-6, cy-12, cx+6, cy-8, top) 78 fillr(base, cx-6, cy+8, cx+6, cy+12, top) 79 return 0 80} 81 82func render_impl(base: i64) -> i64 { 83 let fb: *i64 = (base + O_FB) as *i64 84 let ox: *i64 = (base + O_OX) as *i64 85 let oy: *i64 = (base + O_OY) as *i64 86 let st: *i64 = (base + O_ST) as *i64 87 var p: i64 = 0 88 let road: i64 = rgb(38, 40, 46) 89 while p < W*H { fb[p] = road; p = p + 1 } 90 fillr(base, 8, 0, 12, H, rgb(220, 210, 120)) // left edge 91 fillr(base, W-12, 0, W-8, H, rgb(220, 210, 120)) // right edge 92 var y: i64 = (st[1] % 24) - 24 // scrolling lane dashes 93 while y < H { fillr(base, W/2-2, y, W/2+2, y+12, rgb(210,210,210)); y = y + 24 } 94 var i: i64 = 0 95 while i < NO { car(base, ox[i], oy[i], rgb(224, 90, 70), rgb(60, 30, 30)); i = i + 1 } 96 car(base, st[0], SY, rgb(90, 210, 122), rgb(30, 60, 40)) 97 if st[2] == 1 { 98 fillr(base, 0, 0, W, 3, rgb(200,40,40)); fillr(base, 0, H-3, W, H, rgb(200,40,40)) 99 fillr(base, 0, 0, 3, H, rgb(200,40,40)); fillr(base, W-3, 0, W, H, rgb(200,40,40)) 100 } 101 // HUD distance 102 let sbuf: *u8 = (base + O_STR) as *u8 103 var slen: i64 = 0 104 var sv: i64 = st[1] 105 if sv <= 0 { sbuf[0] = 48 as u8; slen = 1 } else { 106 let tmp: *u8 = (base + O_STR + 16) as *u8 107 var k: i64 = 0 108 while sv > 0 { tmp[k] = (48 + (sv % 10)) as u8; sv = sv / 10; k = k + 1 } 109 var q: i64 = 0 110 while q < k { sbuf[q] = tmp[k - 1 - q]; q = q + 1 } 111 slen = k 112 } 113 let mask: *u8 = (base + O_MSK) as *u8 114 nf_draw_text_mem(fb, W, H, mask, 4, 3, 16, sbuf, slen, rgb(235, 240, 250)) 115 return 0 116} 117 118func init() -> i64 { return init_impl(0) } 119func tick(input: i64) -> i64 { return tick_impl(0, input) } 120func render() -> i64 { return render_impl(0) } 121func score() -> i64 { let st: *i64 = (0 + O_ST) as *i64; return st[1] } 122func fb_off() -> i64 { return O_FB } 123func ww() -> i64 { return W } 124func hh() -> i64 { return H }