### Emerging circles

Inspiration: vecteezy.com/vector-…-checkerboard-vector

```// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);

function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max + 1));
}
function rndm(min, max) {
return min + getRandomInt(max - min);
}

// Global code will be evaluated once.
const turtle = new Turtle();
var lines = [
new Ray2(new Vec2(rndm(-95, -85), -110), new Vec2(rndm(-15, 25), 220))
,new Ray2(new Vec2(rndm(-55, -45), -110), new Vec2(rndm(-15, 25), 220))
,new Ray2(new Vec2(rndm(-15, -5), -110), new Vec2(rndm(-15, 25), 220))
,new Ray2(new Vec2(rndm(25, 35), -110), new Vec2(rndm(-15, 25), 220))
,new Ray2(new Vec2(rndm(65, 75), -110), new Vec2(rndm(-15, 25), 220))
]
var circles = [
new Circle(new Vec2(50, -50), rndm(20, 40))
,new Circle(new Vec2(0, 10), rndm(30, 60))
,new Circle(new Vec2(30, 70), rndm(30, 60))
,new Circle(new Vec2(-30, -50), rndm(20, 40))
, new Circle(new Vec2(-80, 40), rndm(20, 30))
]
var penState = 0;

function togglePen() {
//console.log(penState);
if(penState == 0) {
turtle.penup();
penState = 1;
return;
}
turtle.pendown();
penState = 0;
}

// The walk function will be called until it returns false.
function walk(i) {
var r = new Ray2(new Vec2(-100, (i / 8) - 100), new Vec2(200, 0));
intersections = [r.o];

for(var j = 0; j < lines.length; j++) {
var ints = r.getIntersectionRay2(lines[j]);
if(ints) {
intersections.push(ints.point);
}
}
for(var j = 0; j < circles.length; j++) {
var ints = circles[j].getIntersectionsRay2(r);
if(ints && ints.length > 1) {
intersections.push(ints[0].point);
intersections.push(ints[1].point);
}
}

intersections.sort(function(a,b) { return a.x - b.x;})

penState = (r.o.y + 110) % 60 > 30? 1: 0;
turtle.penup();
for(var j = 0; j < intersections.length; j++) {
turtle.goto(intersections[j].simple());
togglePen();
}
return i < 1600;
}

/* All methods by Jurgen, some are commodity, some from Reinder's vec2 functions, some methods implemented to comply with the Vector2 class of the Unity framework */
function Vec2(x, y) {if(typeof y == 'undefined') {this.x = x[0]; this.y = x[1];} else {this.x = x; this.y = y;}}
/* returns scalar: length of vector */
Vec2.prototype.length = function() {return Math.sqrt(this.dot(this));}
/* returns this after making this' length 1 */
Vec2.prototype.normalize = function() {var l = this.length(); this.x /= l; this.y /= l; return this;}
/* returns this after rotating this in radians in clockwise direction for positive rads */
Vec2.prototype.rotate = function(rads) {var x = (Math.cos(rads) * this.x) - (Math.sin(rads) * this.y); var y = (Math.sin(rads) * this.x) + (Math.cos(rads) * this.y); this.x = x; this.y = y; return this;}
/* returns Vec2: a copy of this */
Vec2.prototype.clone = function() {return new Vec2(this.x, this.y);}
/* returns this after adding parameter Vec2 */
Vec2.prototype.add = function(v) {this.x += v.x; this.y += v.y; return this;}
/* returns this after subtracting parameter Vec2 */
Vec2.prototype.subtract = function(v) {this.x -= v.x; this.y -= v.y; return this;}
/* returns scalar: dot product of this and parameter Vec2 */
Vec2.prototype.dot = function(v) {return (this.x * v.x) + (this.y * v.y);}
/* returns boolean: true if distance(squared) between this and parameter Vec2 v is smaller than optional parameter scalar margin */
Vec2.prototype.equals = function(v, margin = .001) {return this.distanceSquared(v) < margin;}
/* returns boolean: true if this and parameter Vec2 are on lines that are parallel to each other within scalar parameter margin */
Vec2.prototype.isParallel = function(v, margin = .001) { var thi = this.clone().normalize().scale(100); var tha = v.clone().normalize().scale(100); return thi.equals(tha, margin) || thi.equals(tha.scale(-1), margin);}
/* returns scalar: the squared distance between this an parameter Vec2 */
Vec2.prototype.distanceSquared = function(v) {return Math.pow(this.x - v.x, 2) + Math.pow(this.y - v.y, 2);}
/* returns scalar: the distance between this an parameter Vec2 */
Vec2.prototype.distance = function(v) {return Math.sqrt(this.distanceSquared(v));}
/* returns scalar: the angle in radians between this and parameter Vec2 */
Vec2.prototype.angle = function(v) {return Math.acos( this.dot(v) / (this.length() * v.length()) );}
/* returns Vec2: interpolated linearly between parameter t = 0 (this) and t = 1 (paramter Vec2) (e.g. t = .5 gives a Vec2 with minimum and equal distance to this and parameter Vec2 */
Vec2.prototype.lerp = function(v, t) {if(t < 0 || 1 < t) { throw new Error('Parameter t out of bounds for Vec2.lerp(v, t)'); } var dx = v.x - this.x; var dy = v.y - this.y; this.x += t * dx; this.y += t * dy; return this;}
/* returns Vec2: alias of lerp() */
Vec2.prototype.interpolateLinearly = function(v, t) {return this.lerp(v, t);}
/* returns this after multiplying itself with scalar parameter */
Vec2.prototype.scale = function(s) {this.x *= s; this.y *= s; return this;}
/* returns array[2]: an array representation of this as [x, y] */
Vec2.prototype.simple = function() {return [this.x, this.y];}
/* returns this after making this the length of parameter length */
Vec2.prototype.scaleAbsolute = function(length) {return this.scale(length / this.length());}
/* returns this: alias of scale() */
Vec2.prototype.scaleRelative = function(s) {return this.scale(s);}
/* returns Vec2: a vector of same magnitude as this, perpendicular to this. The result is always rotated 90-degrees in a counter-clockwise direction for a 2D coordinate system where the positive Y axis goes up. */
Vec2.prototype.getPerpendicular = function() {return new Vec2(-this.y, this.x);}
/* returns Vec2: a vector reflected by a surface perpendicular to parameter norm as if the surface is a perfect mirror */
Vec2.prototype.reflect = function(norm) {var n = norm.clone().normalize(); return this.clone().subtract( n.scale(2 * this.dot(n)) ).scale(-1);}
/* return scalar: the Z-component of the resulting 3D Vector would this and parameter Vec2 be in the 3D plane x = 0, y = 0 */
Vec2.prototype.cross = function(v) {return (this.x * v.y) - (this.y * v.x);}

/* All methods by Jurgen, some are commodity, some methods implemented to comply with the Ray2D class of the Unity framework */
function Ray2(originVec2, directionVec2) { this.o = originVec2; this.d = directionVec2; }
/* returns Ray2: a copy of this */
Ray2.prototype.clone = function() { return new Ray2(this.o.clone(), this.d.clone()); }
/* returns this: draws this ray (from t = 0 to t = 1) on parameter turtle t */
Ray2.prototype.draw = function(t) { t.jump(this.o.x, this.o.y); t.goto(this.o.x + this.d.x, this.o.y + this.d.y); return this; }
/* returns this: draws this ray (from t = 0 to t = 1) on parameter turtle t with an arrow head of size parameter ratio */
Ray2.prototype.drawArrow = function(t, arrawHeadRatio=.3) { this.draw(t); var newO = this.o.clone().add(this.d); var c1 = this.d.clone().scale(-1); var c2 = c1.clone().rotate(Math.PI / 4).scale(arrawHeadRatio); c1.rotate(Math.PI / -4).scale(arrawHeadRatio); new Ray2(newO, c1).draw(t); new Ray2(newO, c2).draw(t); return this; }
/* returns Vec2: alias for getPointAbsolute */
Ray2.prototype.getPoint = function(distance) { return this.getPointAbsolute(distance); }
/* returns Vec2: A point on this ray when the direction is resized to length parameter distance */
Ray2.prototype.getPointAbsolute = function(distance) { return this.o.clone().add(this.d.clone().scaleAbsolute( distance )); }
/* returns Vec2: A point on this ray when the direction is multiplied by parameter t */
Ray2.prototype.getPointRelative = function(t) { return this.o.clone().add(this.d.clone().scale(t)); }
/* returns intersectioninfo or false: object with a point (Vec2) of intersection and a t1 and t2 representing the the scalar to apply to resp this' direction or parameter r's direction to get to that point */
Ray2.prototype.getIntersectionRay2 = function (r) { var deltaO = this.o.clone().subtract(r.o); var perp = this.d.getPerpendicular(); var det = r.d.dot(perp); if(det == 0) { return false; } var t1 = r.d.cross(deltaO) / det; var t2 = deltaO.dot(perp) / det; return { point: this.getPointRelative(t1), t1: t1, t2: t2 } }

/* All methods by Jurgen */