This commit is contained in:
sfja 2025-08-20 20:10:44 +02:00
commit 41ec0814f7
4 changed files with 236 additions and 0 deletions

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

64
index.html Normal file
View File

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.43.2/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="./index.js" defer></script>
</head>
<body>
<div id="buttons">
<button id="start-stop">Start</button>
<button id="save">Save</button>
</div>
<main>
<div id="dashboard">
<canvas id="canvas-area">
</canvas>
<div id="console">
<pre><code id="console-code">Karlkode 1.0</code></pre>
<input type="text" placeholder=">">
</div>
</div>
<div id="editor-area">
<pre id="editor">
lib.clear("green");
lib.drawRect(100, 100, 100, 100, "blue");
lib.println("hello world!");
let playerX = 0;
function loop(deltaT) {
playerX += 100 * deltaT;
lib.drawRect(playerX, 200, 50, 50, "red");
}
lib.startGameLoop(loop);
return 5;
</pre>
</div>
</main>
<!-- fix flash bug in furry browser -->
<script></script>
</body>
</html>

91
index.js Normal file
View File

@ -0,0 +1,91 @@
"use strict";
let _gameLoopTimeout = undefined;
(function () {
const editor = ace.edit("editor");
editor.setTheme("ace/theme/gruvbox");
editor.session.setMode("ace/mode/javascript");
if (editor.getValue() === "") {
editor.setValue(
``,
);
}
let running = false;
const startStopButton = document.querySelector("#start-stop");
const saveButton = document.querySelector("#save");
const consoleCode = document.querySelector("#console-code");
startStopButton.onclick = (ev) => {
if (running) {
if (_gameLoopTimeout) {
clearTimeout(_gameLoopTimeout);
_gameLoopTimeout = undefined;
}
startStopButton.textContent = "Start";
running = false;
} else {
const code = editor.getValue();
runCode(code, consoleCode);
startStopButton.textContent = "Stop";
running = true;
}
};
})();
const lib = (() => {
const consoleCode = document.querySelector("#console-code");
const width = 480;
const height = 360;
const canvas = document.querySelector("canvas");
canvas.width = width;
canvas.height = height;
const cx = canvas.getContext("2d");
cx.imageSmoothingEnabled = false;
function rgb(red, green, blue) {
return `rgb(${red}, ${green}, ${blue})`;
}
function clear(color) {
cx.fillStyle = color;
cx.fillRect(0, 0, width, height);
}
function drawRect(x, y, width, height, color) {
cx.fillStyle = color;
cx.fillRect(x, y, width, height);
}
function println(msg) {
consoleCode.textContent += `${msg}\n`;
}
function startGameLoop(loopFunction) {
let before = Date.now();
_gameLoopTimeout = setInterval(() => {
const now = Date.now();
const deltaT = (now - before) / 1000;
before = now;
loopFunction(deltaT);
}, 16);
}
return { width, height, rgb, clear, drawRect, println, startGameLoop };
})();
async function runCode(code, consoleCode) {
lib;
consoleCode.textContent += `\nRunning code....\n`;
try {
const result = await eval(`(async function () {${code}})()`);
consoleCode.textContent += `Code returned ${result}\n`;
} catch (error) {
consoleCode.textContent += `${error}\n`;
}
}

81
style.css Normal file
View File

@ -0,0 +1,81 @@
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
}
main {
display: flex;
flex-direction: row;
height: 100vh;
}
#buttons {
width: 100%;
display: flex;
flex-direction: row;
justify-content: end;
align-items: center;
gap: 10px;
}
#buttons button {
margin: 5px;
padding: 10px;
min-width: 100px;
}
#dashboard {
display: flex;
flex-direction: column;
gap: 5px;
width: 40vw;
justify-content: space-evenly;
align-items: center;
}
canvas {
background-color: black;
width: 100%;
}
#console {
width: 100%;
padding: 5px;
}
#console pre {
color: white;
background-color: black;
margin: 0;
width: 100%;
font-size: 1rem;
height: 24rem;
}
#console input {
width: 100%;
margin: 0;
outline: none;
border: 2px solid white;
padding: none;
color: white;
background-color: black;
font-family: monospace;
font-size: 1rem;
}
#editor-area {
width: 100%;
height: 100%;
}
#editor {
margin: 0;
width: 100%;
height: 100%;
font-size: 16px;
}