2d logics fully ready (me think)
This commit is contained in:
parent
1a14e2d028
commit
74e9667c51
@ -7,6 +7,25 @@
|
||||
<h1>Cellular Automata Explorer</h1>
|
||||
<div id="container">
|
||||
<sidebar>
|
||||
<div class="menu-row">
|
||||
<h2> Cell Properties</h2>
|
||||
<div class="menu-row-content">
|
||||
<form>
|
||||
<div class="form-field">
|
||||
<label for="live">Living cell color</label>
|
||||
<input name="live" type="color" id="live" value="#000000"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="dead">Dead cell color</label>
|
||||
<input name="dead" type="color" id="dead" value="#AA78E8"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>Cell size</label>
|
||||
<input name="cellSize" type="number" id="cellSize" value="5"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-row">
|
||||
<h2>Elementary Cellular Automata</h2>
|
||||
<div class="menu-row-content">
|
||||
@ -56,31 +75,8 @@
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<input type="button" name="start" id="start" value="start"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<input type="button" name="stop" id="stop" value="stop"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<input type="button" name="reset" id="reset" value="reset"/>
|
||||
</div>
|
||||
</form>
|
||||
<form>
|
||||
<div class="form-field">
|
||||
<label for="live">Living cell color</label>
|
||||
<input name="live" type="color" id="live" value="#000000"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="dead">Dead cell color</label>
|
||||
<input name="dead" type="color" id="dead" value="#AA78E8"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>Cell size</label>
|
||||
<input name="cellSize" type="number" id="cellSize" value="5"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>Loop
|
||||
<input name="loop" type="checkbox" id="loop"/>
|
||||
</label>
|
||||
<input type="button" name="stop" class="stop" value="stop"/>
|
||||
<input type="button" name="reset" class="reset" value="reset"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -91,12 +87,8 @@
|
||||
<form>
|
||||
<div class="form-field">
|
||||
<input type="button" name="start2d" id="start2d" value="start"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<input type="button" name="stop2d" id="stop2d" value="stop"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<input type="button" name="reset2d" id="reset2d" value="reset"/>
|
||||
<input type="button" name="stop" class="stop" value="stop"/>
|
||||
<input type="button" name="reset" class="reset" value="reset"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -6,7 +6,7 @@ function guard(index, array) {
|
||||
}
|
||||
|
||||
// get the next evolution of a 1D CA initial state
|
||||
function evolve(state, rules) {
|
||||
function evolve1d(state, rules) {
|
||||
function getCell(index) {
|
||||
const safeIndex = guard(index, state);
|
||||
return state[safeIndex];
|
||||
@ -26,7 +26,7 @@ function evolve(state, rules) {
|
||||
function createBoard(state, rules, height) {
|
||||
function createBoardAcc(s, h, acc) {
|
||||
if (h === 0) return acc;
|
||||
const newState = evolve(s, rules);
|
||||
const newState = evolve1d(s, rules);
|
||||
const newAcc = acc.concat([s]);
|
||||
return createBoardAcc(newState, h - 1, newAcc);
|
||||
}
|
||||
@ -118,5 +118,5 @@ function initialState2d(width, height, initFn, args) {
|
||||
}
|
||||
|
||||
export {
|
||||
getDrawingValues, initialState1d, initialState2d, evolve, evolve2d, conwayRules, createBoard,
|
||||
getDrawingValues, initialState1d, initialState2d, evolve1d, evolve2d, conwayRules, createBoard,
|
||||
};
|
||||
|
136
src/js/main.js
136
src/js/main.js
@ -1,7 +1,6 @@
|
||||
// TODO : Change board resolution according to the set cell dimensions
|
||||
import { getRandomInt, sleep } from './common.js';
|
||||
import {
|
||||
evolve, evolve2d, getDrawingValues, initialState1d, initialState2d, conwayRules, createBoard,
|
||||
evolve2d, initialState1d, initialState2d, conwayRules, createBoard,
|
||||
} from './automata.js';
|
||||
|
||||
let drawing = 1;
|
||||
@ -12,16 +11,30 @@ 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 resetBtn = document.querySelector('#reset');
|
||||
const stopBtn = document.querySelector('#stop');
|
||||
const cellSize = document.querySelector('#cellSize');
|
||||
const loop = document.querySelector('#loop');
|
||||
const resetBtn = document.querySelectorAll('.reset');
|
||||
const stopBtn = document.querySelectorAll('.stop');
|
||||
// const loop = document.querySelector('#loop');
|
||||
const menuRow = document.querySelectorAll('.menu-row');
|
||||
|
||||
canvas.width = main.offsetWidth * 0.9;
|
||||
canvas.height = main.offsetHeight * 0.9;
|
||||
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 = {};
|
||||
@ -38,60 +51,55 @@ function getRules() {
|
||||
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);
|
||||
}
|
||||
|
||||
async function draw(dimension) {
|
||||
if (drawing === 0) {
|
||||
return;
|
||||
}
|
||||
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));
|
||||
|
||||
const cellProperties = {
|
||||
dimensions: cellSize.value,
|
||||
liveColor: live.value,
|
||||
deadColor: dead.value,
|
||||
};
|
||||
drawCanvas(board, props);
|
||||
}
|
||||
|
||||
const initialState = (
|
||||
() => {
|
||||
if (dimension === '1d') {
|
||||
return initialState1d(
|
||||
Math.floor(canvas.width / cellProperties.dimensions),
|
||||
getRandomInt,
|
||||
[0, 2],
|
||||
);
|
||||
}
|
||||
return evolve2d(initialState2d(
|
||||
Math.floor(canvas.width / cellProperties.dimensions),
|
||||
Math.floor(canvas.height / cellProperties.dimensions),
|
||||
getRandomInt,
|
||||
[0, 2]), conwayRules);
|
||||
})();
|
||||
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);
|
||||
|
||||
const board = (
|
||||
() => {
|
||||
if (dimension === '1d') return createBoard(initialState, rules, Math.floor(canvas.height / cellProperties.dimensions));
|
||||
return initialState;
|
||||
})();
|
||||
|
||||
board.map((row, y) => {
|
||||
const d = cellProperties.dimensions;
|
||||
return row.map(
|
||||
(cell, x) => {
|
||||
ctx.fillStyle = (
|
||||
() => {
|
||||
if (cell === 1) return cellProperties.liveColor;
|
||||
return cellProperties.deadColor;
|
||||
})();
|
||||
ctx.fillRect(x * d, y * d, d, d);
|
||||
return cell;
|
||||
},
|
||||
);
|
||||
});
|
||||
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
|
||||
@ -103,7 +111,7 @@ startBtn.addEventListener('click', async () => {
|
||||
|
||||
drawing = 1;
|
||||
|
||||
draw('1d');
|
||||
draw1d();
|
||||
});
|
||||
|
||||
startBtn2d.addEventListener('click', async () => {
|
||||
@ -113,15 +121,19 @@ startBtn2d.addEventListener('click', async () => {
|
||||
|
||||
drawing = 1;
|
||||
|
||||
draw('2d');
|
||||
draw2d();
|
||||
});
|
||||
|
||||
resetBtn.addEventListener('click', async () => {
|
||||
reset();
|
||||
resetBtn.forEach((elem) => {
|
||||
elem.addEventListener('click', async () => {
|
||||
reset();
|
||||
});
|
||||
});
|
||||
|
||||
stopBtn.addEventListener('click', async () => {
|
||||
drawing = 0;
|
||||
stopBtn.forEach((elem) => {
|
||||
elem.addEventListener('click', async () => {
|
||||
drawing = 0;
|
||||
});
|
||||
});
|
||||
|
||||
menuRow.forEach((elem) => {
|
||||
@ -132,3 +144,11 @@ menuRow.forEach((elem) => {
|
||||
else menuDisplay.setProperty('display', 'block');
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
resizeCanvas();
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
resizeCanvas();
|
||||
});
|
||||
|
@ -40,6 +40,7 @@ input[type="button"] {
|
||||
min-width: 60px;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
|
Loading…
Reference in New Issue
Block a user