I need help figuring out how to add start and rules to the code. I'd like to be able to specify rules and type in a start function into the menu. I'm a math student and not really versed in js, but any help is appreciated!
Here's the code:
https://codepen.io/odedw/pen/RwVyaR
Thanks so much in advance for anyone who helps!
(function(){
//input
var input = {
angle: 25,
segmentLength: 5,
iterations: 6,
scale: 1,
redraw:function(){
shouldStop = true;
setTimeout(init,50);
},
lSystem: {
start: 'X',
rules: {
'F': 'FF',
'X': 'F-[[X]+X]+F[+FX]-X'
}
}
};
var color = '#fff',
angleInRadians,
canvas,
context,
expression,
currentInstructionIndex = 0,
currentPosition = {x: 0, y: 0, angle: Math.PI/2},
positionStack = [],
shouldStop;
function computeExpression(system, n) {
var result = '';
var exp = system.start;
for (var i=0; i<n; i++){
for (var j=0; j<exp.length; j++){
var c = exp[j];
result += system.rules[c] ? system.rules[c] : c;
}
exp = result;
result = '';
}
return exp;
}
function initCanvas(){
canvas = document.getElementsByTagName('canvas')[0];
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
context = canvas.getContext("2d");
context.strokeStyle = color;
context.lineWidth = 1;
}
function start(){
currentInstructionIndex = 0;
shouldStop = false;
context.clearRect(0, 0, canvas.width, canvas.height);
context.scale(input.scale, input.scale);
currentPosition.x = 0;
currentPosition.y = context.canvas.height / (2 * input.scale);
currentPosition.angle = Math.PI/2;
context.beginPath();
drawExpression();
}
function drawExpression(){
if (shouldStop) {
return;
}
var inst = expression[currentInstructionIndex];
var shouldRequestFrame = processInstruction(inst);
currentInstructionIndex++;
if (shouldRequestFrame){
requestAnimationFrame(drawExpression);
}
else {
drawExpression();
}
}
function processInstruction(instruction){
angleInRadians = input.angle * Math.PI / 180;
switch(instruction){
case 'F':
context.moveTo(currentPosition.x, currentPosition.y);
currentPosition.x = currentPosition.x + Math.sin(currentPosition.angle) * input.segmentLength;
currentPosition.y = currentPosition.y + Math.cos(currentPosition.angle) * input.segmentLength;
context.lineTo(currentPosition.x, currentPosition.y);
context.stroke();
return true;
case '+':
currentPosition.angle += angleInRadians;
break;
case '-':
currentPosition.angle -= angleInRadians;
break;
case '[':
positionStack.push({x: currentPosition.x, y: currentPosition.y, angle: currentPosition.angle});
break;
case ']':
currentPosition = positionStack.pop();
break;
}
return false;
}
function init(){
expression = computeExpression(input.lSystem, input.iterations);
initCanvas();
start();
}
document.addEventListener("DOMContentLoaded", function() {
var gui = new dat.GUI();
gui.add(input, 'angle',15,90).step(1);
gui.add(input, 'segmentLength', 5, 30).step(1);
gui.add(input, 'iterations', 1, 9).step(1);
gui.add(input, 'redraw');
init();
});
}());