Compare commits

...

2 Commits

Author SHA1 Message Date
ea22b2de6a mv playground src 2025-10-10 18:01:15 +02:00
5ae84ad471 make gamelib rational 2025-10-10 18:01:02 +02:00
9 changed files with 97 additions and 66 deletions

View File

@ -1,51 +0,0 @@
const consoleCode = document.querySelector("#console-code");
export const width = 480;
export const height = 360;
const canvas = document.querySelector("canvas");
canvas.width = width;
canvas.height = height;
const cx = canvas.getContext("2d");
cx.imageSmoothingEnabled = false;
export function rgb(red, green, blue) {
return `rgb(${red}, ${green}, ${blue})`;
}
export function clear(color) {
cx.fillStyle = color;
cx.fillRect(0, 0, width, height);
}
export function drawRect(x, y, width, height, color) {
cx.fillStyle = color;
cx.fillRect(x, y, width, height);
}
export function println(msg) {
if (consoleCode) {
consoleCode.textContent += `${msg}\n`;
} else {
console.log(msg);
}
}
export function startGameLoop(loopFunction) {
let before = Date.now();
const loopInterval = setInterval(() => {
const now = Date.now();
const deltaT = (now - before) / 1000;
before = now;
loopFunction(deltaT);
}, 16);
const abortSignal = globalThis.libInternalAbortController.signal;
if (abortSignal.aborted) {
clearInterval(loopInterval);
}
abortSignal.addEventListener("abort", () => {
clearInterval(loopInterval);
});
}

View File

@ -7,13 +7,6 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Karlkoder Playground</title>
<link rel="stylesheet" href="./style.css">
<script type="importmap">
{
"imports": {
"lib": "./gamelib/lib.js"
}
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.43.2/ace.js"></script>
<script src="./playground/index.js" type="module"></script>
</head>

View File

@ -1,6 +1,7 @@
export class CodeRunner {
constructor(cons) {
this.console = cons;
constructor(console, codeStopper) {
this.console = console;
this.codeStopper = codeStopper;
this.isRunning = false;
}
@ -13,8 +14,7 @@ export class CodeRunner {
this.console.log("Running code...");
// Stored globally so lib.js can access it
globalThis.libInternalAbortController = new AbortController();
this.codeStopper.start();
// Use RNG to prevent caching
const encodedText = encodeURIComponent(
@ -30,9 +30,7 @@ export class CodeRunner {
stop() {
this.isRunning = false;
globalThis.libInternalAbortController?.abort();
this.codeStopper.stop();
this.console.log("Stopping code...");
}

24
src/code_stopper.js Normal file
View File

@ -0,0 +1,24 @@
export class CodeStopper {
constructor() {
this.abortController = new AbortController();
}
start() {
this.abortController = new AbortController();
}
stop() {
this.abortController.abort();
}
isStopped() {
return this.abortController.signal.aborted;
}
addListener(fn) {
this.abortController.signal
.addEventListener("abort", () => {
fn();
});
}
}

54
src/gamelib.js Normal file
View File

@ -0,0 +1,54 @@
export class Gamelib {
constructor(console, codeStopper, canvasElement) {
this.console = console;
this.codeStopper = codeStopper;
this.canvas = canvasElement;
this.width = 480;
this.height = 360;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.cx = this.canvas.getContext("2d");
this.cx.imageSmootingEnabled = false;
}
println(msg) {
this.console.log(msg);
}
startGameLoop(loopFunction) {
let before = Date.now();
const loopInterval = setInterval(() => {
const now = Date.now();
const deltaT = (now - before) / 1000;
before = now;
loopFunction(deltaT);
}, 16);
if (this.codeStopper.isStopped()) {
clearInterval(loopInterval);
}
this.codeStopper.addListener(() => {
clearInterval(loopInterval);
});
}
rgb(red, green, blue) {
return `rgb(${red}, ${green}, ${blue})`;
}
clear(color) {
const cx = this.cx;
cx.fillStyle = color;
cx.fillRect(0, 0, this.width, this.height);
}
drawRect(x, y, width, height, color) {
const cx = this.cx;
cx.fillStyle = color;
cx.fillRect(x, y, width, height);
}
}

View File

@ -4,13 +4,26 @@ import { Debounce } from "./debounce.js";
import { PlaygroundConsole } from "./playground-console.js";
import { CodeRunner } from "./code-runner.js";
import { SpriteEditor } from "./sprite-editor.js";
import { Gamelib } from "./gamelib.js";
import { CodeStopper } from "./code_stopper.js";
const playgroundConsole = new PlaygroundConsole(
document.querySelector("#console-code"),
);
const codeRunner = new CodeRunner(playgroundConsole);
const codeStopper = new CodeStopper();
const codeRunner = new CodeRunner(playgroundConsole, codeStopper);
new SpriteEditor(document.querySelector("#sprite-editor"), []);
const gamelib = new Gamelib(playgroundConsole, codeStopper, document.querySelector("canvas"));
globalThis.karlkoder = {
lib() {
return gamelib;
},
};
const editor = ace.edit("editor");
editor.setTheme("ace/theme/gruvbox");
editor.session.setMode("ace/mode/javascript");