/// import { Debounce } from "./debounce.js"; import { PlaygroundConsole } from "./playground_console.js"; import { CodeRunner } from "./code_runner.js"; import { SpriteEditor } from "./sprite_editor.js"; import { SpriteProvider } from "./sprite_provider.js"; import { Gamelib } from "./gamelib.js"; import { CodeStopper } from "./code_stopper.js"; import { Vermiparous } from "./vermiparous.js"; import { promptUpload } from "./prompt_upload.js"; const playgroundConsole = new PlaygroundConsole( document.querySelector("#console-code"), ); const codeStopper = new CodeStopper(); const spriteProvider = new SpriteProvider(); const codeRunner = new CodeRunner(playgroundConsole, codeStopper); const spriteEditor = new SpriteEditor(document.querySelector("#sprite-editor"), []); const gamelib = new Gamelib( playgroundConsole, codeStopper, spriteProvider, document.querySelector("canvas"), ); globalThis.karlkoder = { lib() { return gamelib; }, }; const editor = ace.edit("editor"); editor.setTheme("ace/theme/gruvbox"); editor.session.setMode("ace/mode/javascript"); editor.setValue(sessionStorage.getItem("code") ?? editor.getValue(), -1); const importButton = document.querySelector("#import-button"); const runButton = document.querySelector("#run-button"); const saveButton = document.querySelector("#save-button"); const saveDropdown = document.querySelector("#save-dropdown"); const saveJsButton = document.querySelector("#save-js"); const saveHtmlButton = document.querySelector("#save-html"); const saveKarlkoderButton = document.querySelector("#save-karlkoder"); const toggleSpriteEditorButton = document.querySelector("#toggle-sprite-editor-button"); const sessionSaveDebounce = new Debounce(1000); editor.addEventListener("change", (ev) => { sessionSaveDebounce.run(() => { sessionStorage.setItem("code", editor.getValue()); }); }); importButton.onclick = async (ev) => { const files = await promptUpload("", false); if (files.length === 0) { return; } if (files.length > 1) { throw new Error("unreachable: something went wrong ! files.length > 1"); } const item = Vermiparous.de(await fetch(URL.createObjectURL(files[0])).then((x) => x.bytes())); }; runButton.onclick = (ev) => { const code = editor.getValue(); karlkoder.lib().spriteProvider.injectSprites(spriteEditor.sprites); codeRunner.setCode(code); codeRunner.toggle(); document.querySelector("canvas").focus(); if (codeRunner.isRunning) { runButton.textContent = "✋ Stop"; runButton.classList.add("active"); } else { runButton.textContent = "🏃 Run"; runButton.classList.remove("active"); } }; function downloadFile(content, mime, extension) { const filename = prompt("Filename?"); const element = document.createElement("a"); element.href = `data:${mime};charset=utf-8,${encodeURIComponent(content)}`; element.download = filename.endsWith(extension) ? filename : filename + extension; element.style.display = "none"; document.body.appendChild(element); element.click(); document.body.removeChild(element); } function minifyJs(code) { return code .replace(/[\s\n]+/g, " ") .replace(/;\s+/g, ";"); } saveButton.onclick = (ev) => { if (saveButton.classList.contains("active")) { saveButton.classList.remove("active"); saveDropdown.style.display = "none"; } else { saveButton.classList.add("active"); saveDropdown.style.display = "block"; } }; saveJsButton.onclick = (ev) => { downloadFile(editor.getValue(), "text/javascript", ".js"); }; saveHtmlButton.onclick = async (ev) => { const js = editor.getValue() .split("\n") .map((line) => " ".repeat(12) + line).join("\n"); let lib = await (await fetch("./js/lib.js")).text(); lib = minifyJs(lib); const html = ` Game `; downloadFile(html, "text/html", ".html"); }; saveKarlkoderButton.onclick = (ev) => { downloadFile( Vermiparous.en( editor.getValue() .split("\n") .map((line) => " ".repeat(12) + line).join("\n"), spriteEditor.sprites, ), "", ".karlkode", ); }; toggleSpriteEditorButton.addEventListener("click", () => { const container = document.querySelector("#sprite-editor-container"); const editor = document.querySelector("#sprite-editor"); const button = document.querySelector("#toggle-sprite-editor-button"); if (getComputedStyle(editor).display === "none") { editor.style.display = "block"; container.style.flexGrow = "1"; button.innerHTML = "›"; button.setAttribute("expanded", true); } else { editor.style.display = "none"; container.style.flexGrow = "0"; button.innerHTML = "‹"; button.removeAttribute("expanded"); } });