summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrian cully <bjc@spork.org>2025-12-23 19:52:31 -0500
committerbrian cully <bjc@spork.org>2025-12-23 19:52:31 -0500
commitd1bc29694219a3d3d34e6dcc696ce249c7540fcd (patch)
tree7bfee157d336f5d61761da50605d4894401186aa
parent511beade910e5115f46d79342af76b81f85cf336 (diff)
downloadautomathon-d1bc29694219a3d3d34e6dcc696ce249c7540fcd.tar.gz
automathon-d1bc29694219a3d3d34e6dcc696ce249c7540fcd.zip
js: begin migration to multi-bot life
-rw-r--r--site/main.mjs108
1 files changed, 54 insertions, 54 deletions
diff --git a/site/main.mjs b/site/main.mjs
index 5a4d94a..fd9abb6 100644
--- a/site/main.mjs
+++ b/site/main.mjs
@@ -11,6 +11,8 @@ const TICK_RATE_SELECTOR = '#tick-rate-select';
const RUN_BUTTON_SELECTOR = '#run';
const FPS_SELECTOR = '#fps';
+const ROBO_RADIUS = 25;
+
function clamp(radius, x, y, width, height) {
const xx = Math.min(Math.max(radius, x), width-radius);
const yy = Math.min(Math.max(radius, y), height-radius);
@@ -21,83 +23,90 @@ function renderRobo(ctx, x, y) {
ctx.fillStyle = 'rgb(200 0 0)';
ctx.beginPath();
//ctx.arc(Math.floor(x), Math.floor(y), 25, 0, 2 * Math.PI);
- ctx.arc(x, y, 25, 0, 2 * Math.PI);
+ ctx.arc(x, y, ROBO_RADIUS, 0, 2 * Math.PI);
ctx.fill();
}
-function renderArena(robos, delta=0) {
+function renderArena(robos, now=0) {
// interpolation factor for smoother movement independent of tick
// rate, but never tween more than 1 tick.
- const timeScale = Math.min(delta / MS_PER_TICK, 1.0);
const canvas = document.querySelector(CANVAS_SELECTOR);
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
robos.forEach(robo => {
+ const delta = robo.lastTick ? now - robo.lastTick : 0;
+ const timeScale = Math.min(delta / MS_PER_TICK, 1.0);
let [x, y] = [robo.x, robo.y];
if (delta > 0) {
const [velx, vely] = [
robo.speedx, robo.speedy
].map(x => timeScale * x);
- [x, y] = clamp(25, robo.x + velx, robo.y + vely, canvas.width, canvas.height);
+ [x, y] = clamp(ROBO_RADIUS, robo.x + velx, robo.y + vely, canvas.width, canvas.height);
}
renderRobo(ctx, x, y);
});
}
async function loaded() {
+ Inspector.register();
+
const canvas = document.querySelector(CANVAS_SELECTOR);
- const roboWorker = new Worker('robo.mjs', { type: 'module' });
- const robo = {
- worker: roboWorker,
+ const robos = [{
+ worker: new Worker('robo.mjs', { type: 'module' }),
lastTick: undefined,
- x: 132,
- y: 25,
+ x: ROBO_RADIUS + Math.floor(Math.random() * (canvas.width - ROBO_RADIUS)),
+ y: ROBO_RADIUS + Math.floor(Math.random() * (canvas.height - ROBO_RADIUS)),
heading: 0,
speed: 0,
speedx: 0,
speedy: 0,
- };
- roboWorker.onmessage = e => {
- const { kind, res, trans } = e.data;
- switch (kind) {
- case 'compile':
- if (res) {
- renderArena([robo]);
- document.querySelector('x-inspector').render(trans, true);
- }
- break;
- case 'tick':
- robo.lastTick = document.timeline.currentTime;
+ }];
+ robos.forEach((robo, i) => {
+ robo.worker.onmessage = e => {
+ const { kind, res, trans } = e.data;
+ switch (kind) {
+ case 'compile':
+ if (res) {
+ renderArena(robos);
+ document.querySelectorAll(Inspector.name)[i].render(trans, true);
+ }
+ break;
+ case 'tick':
+ robo.lastTick = document.timeline.currentTime;
- const [x, y] = clamp(25, robo.x + robo.speedx, robo.y + robo.speedy, canvas.width, canvas.height);
- robo.x = x;
- robo.y = y;
- renderArena([robo]);
+ [robo.x, robo.y] = clamp(ROBO_RADIUS, robo.x + robo.speedx, robo.y + robo.speedy, canvas.width, canvas.height);
+ renderArena(robos);
- robo.heading = trans.vars.heading;
- robo.speed = trans.vars.speed;
- const [speedx, speedy] = [
- Math.cos(2 * Math.PI * robo.heading / 360),
- Math.sin(2 * Math.PI * robo.heading / 360)
- ].map(x => robo.speed * x);
- robo.speedx = speedx;
- robo.speedy = speedy;
+ robo.heading = trans.vars.heading;
+ robo.speed = trans.vars.speed;
+ [robo.speedx, robo.speedy] = [
+ Math.cos(2 * Math.PI * robo.heading / 360),
+ Math.sin(2 * Math.PI * robo.heading / 360)
+ ].map(x => robo.speed * x);
- document.querySelector('x-inspector').render(trans);
- break;
- default:
- console.error('invalid message from robo worker', e.data);
- }
- };
- roboWorker.onerror = e => {
- console.error('error in roboWorker', e);
- };
+ document.querySelectorAll(Inspector.name)[i].render(trans);
+ break;
+ default:
+ console.error('invalid message from robo worker', e.data);
+ }
+ };
+ robo.worker.onerror = e => {
+ console.error('error in roboWorker', e);
+ };
+ });
+
+ document.querySelectorAll(Inspector.name).forEach((elt, i) => {
+ elt.addEventListener(Inspector.compileRequest, e => {
+ console.debug('compiling', e.detail.text);
+ robos[i].worker.postMessage({ kind: 'compile', text: e.detail.text });
+ });
+ });
document.querySelector(TICK_BUTTON_SELECTOR).onclick = e => {
console.debug('tick clicked', e);
- roboWorker.postMessage({ kind: 'tick' });
+ robos.forEach(robo => robo.worker.postMessage({ kind: 'tick' }));
};
document.querySelector(TICK_RATE_SELECTOR).onchange = e => {
@@ -120,8 +129,7 @@ async function loaded() {
const ms = t - lastTime;
if (ms > 0) {
lastTime = t;
- const delta = robo.lastTick ? t - robo.lastTick : 0;
- renderArena([robo], delta);
+ renderArena(robos, t);
const fps = document.querySelector(FPS_SELECTOR);
fps.textContent = ms > 0 ? Math.floor(1_000 / ms) : '0';
}
@@ -133,7 +141,7 @@ async function loaded() {
}
self.setTimeout(timeout, MS_PER_TICK);
- robo.worker.postMessage({ kind: 'tick' });
+ robos.forEach(robo => robo.worker.postMessage({ kind: 'tick' }));
}
document.querySelector(RUN_BUTTON_SELECTOR).onclick = e => {
@@ -153,14 +161,6 @@ async function loaded() {
document.querySelector(FPS_SELECTOR).textContent = 'n/a';
}
}
-
- Inspector.register();
- document.querySelectorAll(Inspector.name).forEach(elt => {
- elt.addEventListener(Inspector.compileRequest, e => {
- console.debug('compiling', e.detail.text);
- roboWorker.postMessage({ kind: 'compile', text: e.detail.text });
- });
- });
}
document.addEventListener('DOMContentLoaded', loaded);