147 lines
3.3 KiB
JavaScript
147 lines
3.3 KiB
JavaScript
import { getRandomInt, sleep } from './common.js';
|
|
import {
|
|
evolve2d, initialState1d, initialState2d, conwayRules, createBoard,
|
|
} from './automata.js';
|
|
|
|
let drawing = 1;
|
|
|
|
const form = Array.from(document.forms.rules.elements);
|
|
const canvas = document.querySelector('#canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
const main = document.querySelector('#main');
|
|
const dead = document.querySelector('#dead');
|
|
const live = document.querySelector('#live');
|
|
const cellSize = document.querySelector('#cellSize');
|
|
const startBtn = document.querySelector('#start');
|
|
const startBtn2d = document.querySelector('#start2d');
|
|
const canvasRefreshBtn = document.querySelector('#canvasRefresh');
|
|
const resetBtn = document.querySelectorAll('.reset');
|
|
const stopBtn = document.querySelectorAll('.stop');
|
|
// const loop = document.querySelector('#loop');
|
|
const menuRow = document.querySelectorAll('.menu-row');
|
|
const menuRowContent = document.querySelectorAll('.menu-row-content');
|
|
|
|
function drawCanvas(board, props) {
|
|
board.map((row, y) => {
|
|
const d = props.size;
|
|
return row.map(
|
|
(cell, x) => {
|
|
ctx.fillStyle = (
|
|
() => {
|
|
if (cell === 1) return props.liveColor;
|
|
return props.deadColor;
|
|
})();
|
|
ctx.fillRect(x * d, y * d, d, d);
|
|
return cell;
|
|
},
|
|
);
|
|
});
|
|
}
|
|
|
|
function getRules() {
|
|
const rules = {};
|
|
|
|
form.reduce((_, i) => {
|
|
if (i !== undefined
|
|
&& i.type === 'checkbox') {
|
|
if (i.checked) rules[i.name] = '1';
|
|
else rules[i.name] = '0';
|
|
}
|
|
return rules;
|
|
}, rules);
|
|
|
|
return rules;
|
|
}
|
|
|
|
function getCellProperties() {
|
|
return {
|
|
size: cellSize.value,
|
|
liveColor: live.value,
|
|
deadColor: dead.value,
|
|
};
|
|
}
|
|
|
|
function reset() {
|
|
drawing = 0;
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
}
|
|
|
|
function resizeCanvas() {
|
|
canvas.width = main.offsetWidth * 0.9;
|
|
canvas.height = main.offsetHeight * 0.9;
|
|
}
|
|
|
|
async function draw1d() {
|
|
const rules = getRules();
|
|
const props = getCellProperties();
|
|
const initialState = initialState1d(
|
|
Math.floor(canvas.width / props.size),
|
|
getRandomInt,
|
|
[0, 2],
|
|
);
|
|
const board = createBoard(initialState, rules, Math.floor(canvas.height / props.size));
|
|
|
|
drawCanvas(board, props);
|
|
}
|
|
|
|
async function draw2d() {
|
|
const props = getCellProperties();
|
|
const initialState = initialState2d(
|
|
Math.floor(canvas.width / props.size),
|
|
Math.floor(canvas.height / props.size),
|
|
getRandomInt,
|
|
[0, 2],
|
|
);
|
|
const board = evolve2d(initialState, conwayRules);
|
|
|
|
async function draw2dNext(b) {
|
|
if (drawing === 0) return;
|
|
const newBoard = evolve2d(b, conwayRules);
|
|
drawCanvas(b, props);
|
|
await sleep(300);
|
|
draw2dNext(newBoard);
|
|
}
|
|
return draw2dNext(board);
|
|
}
|
|
|
|
// Listeners
|
|
|
|
startBtn.addEventListener('click', async () => {
|
|
reset();
|
|
|
|
await sleep(60);
|
|
|
|
drawing = 1;
|
|
|
|
draw1d();
|
|
});
|
|
|
|
startBtn2d.addEventListener('click', async () => {
|
|
reset();
|
|
|
|
await sleep(60);
|
|
|
|
drawing = 1;
|
|
|
|
draw2d();
|
|
});
|
|
|
|
resetBtn.forEach((elem) => {
|
|
elem.addEventListener('click', async () => {
|
|
reset();
|
|
});
|
|
});
|
|
|
|
stopBtn.forEach((elem) => {
|
|
elem.addEventListener('click', async () => {
|
|
drawing = 0;
|
|
});
|
|
});
|
|
|
|
canvasRefreshBtn.addEventListener('click', () => {
|
|
const width = document.querySelector('#canvasWidth').value;
|
|
const height = document.querySelector('#canvasWidth').value;
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
});
|