xxxxxxxxxx
// L-SYSTEMS:
// this p5 sketch takes the turtle we created in the last project and *automates* the drawing based on a Lindenmayer (or L-) system. L-systems are often used in procedural
// graphics to make natural, geometric, or interesting 'fractal-style' patterns.
//
// your tasks:
// (1) take a look at the L-system implemented here, and see if you
// can expand upon it to do some automatic, cool, geometric drawing. Use the turtle that you retooled from the previous sketch as the drawing engine.
// hint: google L-systems. there are lots of them out there. You can use non-drawing symbols as symbolic placeholders to create really complex patterns.
// TURTLE STUFF:
var x, y, a; // the current position of the turtle
var currentangle = 0; // which way the turtle is pointing
var step = 30; // how much the turtle moves with each 'F'
var angle = 90; // how much the turtle turns with a '-' or '+'
// LINDENMAYER STUFF (L-SYSTEMS)
var thestring = 'X'; // "axiom" or start of the string
var numloops, t, d; // how many iterations of the L-system to pre-compute, turn
numloops = 5; t = 45; d = 20;
var therules = []; // array for rules
therules[0] = ['X', 'FB-FF+X+F+FB-']; // first rule
therules[1] = ['F', 'B-FX-FAF-BB']; // second rule
var whereinstring = 0; // where in the L-system are we drawing right now?
// THIS RUNS WHEN WE HIT GO
function setup()
{
createCanvas(windowWidth, windowHeight); // this is the size of the window
background(0);
stroke(255, 255, 255, 0); // draw in white
strokeWeight(1,10);
fill(random(255), random(255), random(255), 50);
x = width/2; y = height/2;
// COMPUTE THE L-SYSTEM
for(let i=0; i<numloops; i++) {
var outstring = '';
for(let j = 0;j<thestring.length;j++)
{
for(let k = 0;k<therules.length;k++)
{
var ismatch = 0;
if(thestring.charAt(j)==therules[k][0]) // MATCH
{
outstring+=therules[k][1]; // copy of the second half
ismatch=1;
break;
}
}
if(ismatch==0) outstring+=thestring.charAt(j);
}
thestring=outstring;
}
// console.log(thestring); // comment this out if it's slowing you down
}
// DO THIS EVERY FRAME
function draw()
{
// draw the current character in the string:
drawIt(thestring.charAt(whereinstring));
// increment the point for where we're reading the string.
// wrap around at the end.
whereinstring++;
if(whereinstring>thestring.length-1) whereinstring = 0;
}
// interpret an L-system
function lindenmayer(s)
{
var outputstring = ''; // start a blank output string
// go through the string, doing rewriting as we go
// iterate through 'therules' looking for symbol matches:
for(var i=0; i<s.length; i++) // every symbol in 's'
{
var ismatch = 0; // by default, no match
for(var j = 0;j<therules.length;j++) // every rule in 'therules'
{
if(s.charAt(i)==therules[j][0]) // MATCH!
{
outputstring+=therules[j][1]; // write substitution
ismatch = 1; // we have a match, so don't copy over symbol
break; // get outta this for() loop
}
}
// if nothing matches in 'therules' array, just copy the symbol over.
if(ismatch===0) outputstring+= s.charAt(i);
}
return(outputstring); // send out the modified string
}
function keyTyped()
{
drawIt(key);
}
// this is a custom function that draws turtle commands
function drawIt(k)
{
if(k=='F') // draw forward
{
// polar to cartesian transformation based on step and currentangle:
var x1 = x + step*cos(radians(currentangle));
var y1 = y + step*sin(radians(currentangle));
line(x, y, x1, y1); // connect the old and the new
// update the turtle's position:
x = x1;
y = y1;
}
if(k=='B')
{
stroke(random(255), random(255), random(255));
ellipse(x[x.length-1], y[y.length-1], d, d);
}
if(k=='+')
{
currentangle+=angle; // turn left
}
if(k=='-')
{
currentangle-=angle; // turn right
}
// DRAW EVERYTHING:
var r = random(255); var g = random(255); var b = random(255); var a = random(50,100);
var radius = random(0,20);
radius+= random(0, 20);
// draw the stuff:
fill(random(255), random(255), random(255), 50); // interior fill color
rect(x, y, radius, radius);
if(k=='C') //add a circle
{
fill(random(255), random(255), random(255), 150); // interior fill color
ellipse(x, y, radius, radius); // circle
}
if(k=='L') //add line
{
fill(random(255), random(255), random(255), 50); // interior fill color
triangle(windowWidth/2, windowHeight/2, x, y, x, y); // circle that chases the mouse
}
}