Compare commits
2 Commits
d480d8f4d0
...
ea22b2de6a
| Author | SHA1 | Date | |
|---|---|---|---|
| ea22b2de6a | |||
| 5ae84ad471 |
@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -7,13 +7,6 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
<title>Karlkoder Playground</title>
|
<title>Karlkoder Playground</title>
|
||||||
<link rel="stylesheet" href="./style.css">
|
<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="https://cdnjs.cloudflare.com/ajax/libs/ace/1.43.2/ace.js"></script>
|
||||||
<script src="./playground/index.js" type="module"></script>
|
<script src="./playground/index.js" type="module"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export class CodeRunner {
|
export class CodeRunner {
|
||||||
constructor(cons) {
|
constructor(console, codeStopper) {
|
||||||
this.console = cons;
|
this.console = console;
|
||||||
|
this.codeStopper = codeStopper;
|
||||||
this.isRunning = false;
|
this.isRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,8 +14,7 @@ export class CodeRunner {
|
|||||||
|
|
||||||
this.console.log("Running code...");
|
this.console.log("Running code...");
|
||||||
|
|
||||||
// Stored globally so lib.js can access it
|
this.codeStopper.start();
|
||||||
globalThis.libInternalAbortController = new AbortController();
|
|
||||||
|
|
||||||
// Use RNG to prevent caching
|
// Use RNG to prevent caching
|
||||||
const encodedText = encodeURIComponent(
|
const encodedText = encodeURIComponent(
|
||||||
@ -30,9 +30,7 @@ export class CodeRunner {
|
|||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
this.isRunning = false;
|
this.isRunning = false;
|
||||||
|
this.codeStopper.stop();
|
||||||
globalThis.libInternalAbortController?.abort();
|
|
||||||
|
|
||||||
this.console.log("Stopping code...");
|
this.console.log("Stopping code...");
|
||||||
}
|
}
|
||||||
|
|
||||||
24
src/code_stopper.js
Normal file
24
src/code_stopper.js
Normal 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
54
src/gamelib.js
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,13 +4,26 @@ import { Debounce } from "./debounce.js";
|
|||||||
import { PlaygroundConsole } from "./playground-console.js";
|
import { PlaygroundConsole } from "./playground-console.js";
|
||||||
import { CodeRunner } from "./code-runner.js";
|
import { CodeRunner } from "./code-runner.js";
|
||||||
import { SpriteEditor } from "./sprite-editor.js";
|
import { SpriteEditor } from "./sprite-editor.js";
|
||||||
|
import { Gamelib } from "./gamelib.js";
|
||||||
|
import { CodeStopper } from "./code_stopper.js";
|
||||||
|
|
||||||
const playgroundConsole = new PlaygroundConsole(
|
const playgroundConsole = new PlaygroundConsole(
|
||||||
document.querySelector("#console-code"),
|
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"), []);
|
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");
|
const editor = ace.edit("editor");
|
||||||
editor.setTheme("ace/theme/gruvbox");
|
editor.setTheme("ace/theme/gruvbox");
|
||||||
editor.session.setMode("ace/mode/javascript");
|
editor.session.setMode("ace/mode/javascript");
|
||||||
Loading…
x
Reference in New Issue
Block a user