Mirai's Miscellaneous Misadventures
M50 / index.html
1<!-- license: AGPLv3 or later -->
2<!-- copyright 2024 zamfofex -->
3
4<!doctype html>
5<html lang="en">
6<meta charset="utf-8">
7<meta name="viewport" content="width=device-width">
8
9<title> Mirai's Miscellaneous Misadventures </title>
10
11<style>
12
13*, ::before, ::after
14{
15 touch-action: none;
16}
17
18html, body
19{
20 width: 100%;
21 height: 100%;
22 display: flex;
23}
24
25body
26{
27 margin: 0;
28 background: #000;
29}
30
31canvas
32{
33 width: 100%;
34 height: 100%;
35 image-rendering: crisp-edges;
36 image-rendering: pixelated;
37 object-fit: contain;
38 outline: none;
39}
40
41</style>
42
43<script type="module">
44
45import * as WebAssembly from "https://esm.sh/asyncify-wasm@1.2.1"
46
47let canvas = document.querySelector("canvas")
48let context = canvas.getContext("2d")
49
50let cache = new Map()
51
52let rch = [0x11, 0x44, 0x77, 0x99, 0xCC, 0xFF]
53let gch = [0x11, 0x33, 0x55, 0x77, 0x99, 0xBB, 0xDD, 0xFF]
54let bch = [0x22, 0x55, 0x88, 0xBB, 0xEE]
55
56let createTexture = async (data0, asset) =>
57{
58 let view = new DataView(memory.buffer)
59
60 if (asset < 0) asset = 0x10000 + asset
61
62 let width = view.getUint32(asset, true)
63 let height = view.getUint32(asset + 4, true)
64 let colors = view.getUint32(asset + 8, true)
65
66 let image = new ImageData(width, height)
67 let {data} = image
68
69 for (let x = 0 ; x < width ; x++)
70 for (let y = 0 ; y < height ; y++)
71 {
72 let o = x + y * width
73 let color = view.getUint8(colors + o)
74
75 if (color === 0) continue
76
77 if (color < 0x10)
78 {
79 let ch = color * 0x11
80 data[o * 4 + 0] = ch
81 data[o * 4 + 1] = ch
82 data[o * 4 + 2] = ch
83 data[o * 4 + 3] = 0xFF
84 }
85 else
86 {
87 color -= 0x10
88 let r = rch[Math.floor(color / 40) % 6]
89 let g = gch[Math.floor(color / 5) % 8]
90 let b = bch[Math.floor(color / 1) % 5]
91
92 data[o * 4 + 0] = r
93 data[o * 4 + 1] = g
94 data[o * 4 + 2] = b
95 data[o * 4 + 3] = 0xFF
96 }
97 }
98
99 cache.set(asset, await createImageBitmap(image))
100 return asset
101}
102
103let stamp = (data, x, y, asset) => context.drawImage(cache.get(asset), x, y)
104
105let invalidate = (data, asset) => cache.delete(asset)
106
107let past = performance.now()
108
109let promise
110let resolve = () => { }
111let tick = () =>
112{
113 let now = performance.now()
114 resolve(left * 2 + right)
115 promise = new Promise(f => { setTimeout(tick, (100 / 3) + past - now) ; resolve = f })
116 past = now
117}
118
119let imports =
120{
121 env:
122 {
123 mimimi_wasm_texture: createTexture,
124 mimimi_wasm_invalidate: invalidate,
125 mimimi_wasm_stamp: stamp,
126 mimimi_wasm_sync: () => promise,
127 },
128 wasi_snapshot_preview1: {proc_exit: () => { throw new Error("exit called") }},
129}
130
131let response = await fetch("mimimi.wasm")
132let buffer = await response.arrayBuffer()
133let {instance} = await WebAssembly.instantiate(buffer, imports)
134let {memory, _start} = instance.exports
135
136let left = 0
137let right = 0
138
139addEventListener("keydown", ({code}) =>
140{
141 if (code === "ArrowLeft") left = 1
142 if (code === "ArrowRight") right = 1
143 if (code === "KeyA") left = 1
144 if (code === "KeyD") right = 1
145})
146
147addEventListener("keyup", ({code}) =>
148{
149 if (code === "ArrowLeft") left = 0
150 if (code === "ArrowRight") right = 0
151 if (code === "KeyA") left = 0
152 if (code === "KeyD") right = 0
153})
154
155addEventListener("contextmenu", event => event.preventDefault())
156
157addEventListener("pointerdown", event =>
158{
159 if (event.pointerType === "mouse") return
160 if (event.button !== 0) return
161
162 if (event.offsetX < innerWidth / 2)
163 left = 1
164 else
165 right = 1
166})
167
168addEventListener("pointerup", event =>
169{
170 if (event.pointerType === "mouse") return
171 if (event.button !== 0) return
172
173 left = 0
174 right = 0
175})
176
177addEventListener("mousedown", ({button}) =>
178{
179 if (button === 0) left = 1
180 if (button === 2) right = 1
181})
182
183addEventListener("mouseup", ({button}) =>
184{
185 if (button === 0) left = 0
186 if (button === 2) right = 0
187})
188
189tick()
190_start()
191
192</script>
193
194<canvas width="512" height="256"></canvas>