"let setTimeout, setInterval, clearInterval, clearTimeout;\n" "const {\n" " /* sprite interactions */ setSolids, setPushables,\n" " /* see also: sprite.x +=, sprite.y += */\n" "\n" " /* art */ setLegend, setBackground,\n" " /* text */ addText, clearText,\n" "\n" " /* spawn sprites */ setMap, addSprite,\n" " /* despawn sprites */ clearTile, /* sprite.remove() */\n" "\n" " /* tile queries */ getGrid, getTile, getFirst, getAll, tilesWith,\n" " /* see also: sprite.type */\n" "\n" " /* map dimensions */ width, height,\n" "\n" " /* constructors */ bitmap, tune, map, color,\n" "\n" " /* input handling */ onInput, afterInput,\n" "\n" " /* how much sprite has moved since last onInput: sprite.dx, sprite.dy */\n" "\n" " playTune,\n" "} = (() => {\n" "const exports = {};\n" "/* re-exports from C; bottom of module_native.c has notes about why these are in C */\n" "exports.setMap = map => native.setMap(map.trim());\n" "exports.addSprite = native.addSprite;\n" "exports.getGrid = native.getGrid;\n" "exports.getTile = native.getTile;\n" "exports.tilesWith = native.tilesWith;\n" "exports.clearTile = native.clearTile;\n" "exports.getFirst = native.getFirst;\n" "exports.getAll = native.getAll;\n" "exports.width = native.width;\n" "exports.height = native.height;\n" "exports.setBackground = native.setBackground;\n" "exports.playTune = (str, times) => {\n" " native.piano_queue_song(str, times);\n" " return {\n" " end: () => native.piano_unqueue_song(str),\n" " isPlaying: () => native.piano_is_song_queued(str)\n" " }\n" "}\n" "\n" "/* opts: x, y, color (all optional) */\n" "exports.addText = (str, opts={}) => {\n" " const CHARS_MAX_X = 21;\n" " const padLeft = Math.floor((CHARS_MAX_X - str.length)/2);\n" "\n" " for (const char of str.split('')) {\n" " if (\" !\\\"#%&\\'()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\\\^_-`abcdefghijklmnopqrstuvwxyz|~¦§¨©¬®¯°±´¶·¸ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ÙÚÛÜÝÞßàáâãäåæçèéêëìíîïñòóôõö÷ùúûüýþÿĀāĂ㥹ĆćĊċČčĎĐđĒēĖėĘęĚěĞğĠġĦħĪīĮįİıŃńŇňŌōŒœŞşŨũŪūŮůŲųŴŵŶŷŸǍǎǏǐǑǒǓǔˆˇ˘˙˚˛˜˝ẀẁẂẃẄẅỲỳ†‡•…‰⁄™∂∅∏∑−√∞∫≈≠≤≥◊\".indexOf(char) === -1)\n" " console.log(`WARN: Character ${char} is no longer in supported in the Sprig editor.`); \n" " }\n" "\n" " native.text_add(\n" " str,\n" " opts.color ?? [10, 10, 40],\n" " opts.x ?? padLeft,\n" " opts.y ?? 0\n" " );\n" "}\n" "\n" "exports.clearText = () => native.text_clear();\n" "\n" "\n" "exports.setLegend = (...bitmaps) => {\n" " native.legend_clear();\n" "\n" " for (const [key, bitmap] of bitmaps) {\n" " const rows = bitmap.trim().split(\"\\n\").map(x => x.trim())\n" " const rowLengths = rows.map(x => x.length);\n" " const isRect = rowLengths.every(val => val === rowLengths[0])\n" " if (!isRect) throw new Error(`Bitmap with key ${key} is not rectangular.`)\n" " }\n" "\n" " for (const [charStr, bitmap] of bitmaps) {\n" " native.legend_doodle_set(charStr, bitmap.trim());\n" " }\n" " native.legend_prepare();\n" "};\n" "\n" "exports.setSolids = solids => {\n" " native.solids_clear();\n" " solids.forEach(native.solids_push);\n" "};\n" "\n" "exports.setPushables = pushTable => {\n" " native.push_table_clear();\n" " for (const [pusher, pushesList] of Object.entries(pushTable))\n" " for (const pushes of pushesList)\n" " native.push_table_set(pusher, pushes);\n" "};\n" "\n" "let afterInputs = [];\n" "exports.afterInput = fn => (console.log('engine.js:afterInputs'), afterInputs.push(fn));\n" "// exports.afterInput = fn => afterInputs.push(fn);\n" "\n" "const button = {\n" " pinToHandlers: [...Array(8)].map(_ => []),\n" " keys: [\"w\", \"s\", \"a\", \"d\", \"i\", \"k\", \"j\", \"l\"]\n" "};\n" "\n" "native.press_cb(pin => {\n" " if (button.pinToHandlers[pin])\n" " button.pinToHandlers[pin].forEach(f => f());\n" "\n" " afterInputs.forEach(f => f());\n" "\n" " native.map_clear_deltas();\n" "});\n" "\n" "{\n" " const timers = {};\n" " let id = 0;\n" " let firstClearId = -1;\n" " setTimeout = (fn, ms=10) => (timers[id] = { fn, ms }, id++);\n" " setInterval = (fn, ms=10) => (timers[id] = { fn, ms, restartAt: ms }, id++);\n" " clearTimeout = clearInterval = id => {\n" " delete timers[id]\n" " if (id === firstClearId + 1) firstClearId++;\n" " };\n" "\n" " native.frame_cb(dt => {\n" " /* we'll never need to throw more than one error -ced */\n" " let errorForLater;\n" "\n" " for (let i = firstClearId + 1; i < id; i++) {\n" " const tim = timers[i];\n" " if (!tim) continue;\n" "\n" " if (tim.ms <= 0) {\n" " /* trigger their callback */\n" " try {\n" " tim.fn();\n" " } catch (error) {\n" " /* we'll never need to throw more than one error -ced */\n" " if (error && !errorForLater) errorForLater = error;\n" " }\n" "\n" " /* restart intervals, clear timeouts */\n" " if (tim.restartAt !== undefined) {\n" " tim.ms = tim.restartAt;\n" " } else {\n" " delete timers[i];\n" " if (i === firstClearId + 1) firstClearId++;\n" " }\n" " }\n" " tim.ms -= dt;\n" " }\n" "\n" " if (errorForLater) throw errorForLater;\n" " });\n" "}\n" "\n" "exports.onInput = (key, fn) => {\n" " const pin = button.keys.indexOf(key);\n" "\n" " if (pin === -1)\n" " throw new Error(`the sprig doesn't have a \"${key}\" button!`);\n" "\n" " button.pinToHandlers[pin].push(fn);\n" "};\n" "\n" "function _makeTag(cb) {\n" " return (strings, ...interps) => {\n" " if (typeof strings === \"string\") {\n" " throw new Error(\"Tagged template literal must be used like name`text`, instead of name(`text`)\");\n" " }\n" " const string = strings.reduce((p, c, i) => p + c + (interps[i] ?? ''), '');\n" " return cb(string);\n" " }\n" "}\n" "exports.bitmap = _makeTag(text => text);\n" "exports.tune = _makeTag(text => text);\n" "exports.map = _makeTag(text => text);\n" "exports.color = _makeTag(text => text);\n" "\n" "// .at polyfill\n" "function at(n) {\n" " // ToInteger() abstract op\n" " n = Math.trunc(n) || 0;\n" " // Allow negative indexing from the end\n" " if (n < 0) n += this.length;\n" " // OOB access is guaranteed to return undefined\n" " if (n < 0 || n >= this.length) return undefined;\n" " // Otherwise, this is just normal property access\n" " return this[n];\n" "}\n" "\n" "const TypedArray = Reflect.getPrototypeOf(Int8Array);\n" "for (const C of [Array, String, TypedArray]) {\n" " Object.defineProperty(C.prototype, \"at\",\n" " { value: at,\n" " writable: true,\n" " enumerable: false,\n" " configurable: true });\n" "}\n" "\n" "return exports;\n" "})();\n"