Experimenting with attractors
Log in to post a comment.
// You can find the Turtle API reference here: https://turtletoy.net/syntax Canvas.setpenopacity(0.5); const circles = 40;//min = 1, max = 250, step = 1 //const force = 30;// min = -200, max = 200, step = 1 const attractors = 2;//min = 1, max = 50, step = 1 const resolution = 0.5;//min = 0.01, max = 1, step = 0.01 // help function to compute the distance from a point (i.e., the hypothenuse of a triangle rectangle) function distance(x, y){ return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); } // An attractor is a point which deflects drawing. It has a position and a force. class Attractor{ constructor(x = 0, y = 0, force = 0){ this.x = x; this.y = y; this.force = force; if( x == 0 && y == 0 && force == 0){ this.x = Math.random() * 200 - 100; this.y = Math.random() * 200 - 100; this.force = Math.random() * 200; } } } // Class that handle tracing of circles, and their behavior regarding attractors. class Circle{ constructor(size = 25){ this.size = size; this.centerX = 0; this.centerY = 0; this.angle = 0; this.turtle = new Turtle(); this.turtle.jump(0, size); } attract(a){ this.attractors = a; } walk(){ let radAngle = this.angle * Math.PI / 180; this.x = Math.sin(radAngle) * this.size; this.y = Math.cos(radAngle) * this.size; if(this.attractors){ let delta; let coef; for(let item of this.attractors){ let deltaX = this.x - item.x; let deltaY = this.y - item.y; delta = distance(deltaX, deltaY); coef = Math.pow(item.force/delta, 2); let moveX = (deltaX / delta) * coef; let moveY = (deltaY / delta) * coef; let dist = distance(moveX, moveY); // if(item.force > 0){ if(dist > delta){ // have to find a way to decrease attraction when move is > delta, instead of topping it. moveX = deltaX; moveY = deltaY; // moveX *= delta / dist; // moveY *= delta / dist; } // } else { /* // same here : have to find a way to limit movement if(distance < item.force / 4){ moveX /= 1/dist; moveY /= 1/dist; } */ // moveX = -moveX; // moveY = -moveY; // } this.x -= moveX; this.y -= moveY; } } if(this.angle == 0) this.turtle.jump(this.x, this.y); else this.turtle.goto(this.x, this.y); this.angle += resolution; if(this.angle >= 360) return false; return true; } } // generate random attractors. const attractorList = []; for(let i = 0; i < attractors; i++){ attractorList.push(new Attractor()); } //attractorList.push(new Attractor(60, 0, 40)); //attractorList.push(new Attractor(-40, 40, -40)); //generate the circles. const circleList = []; for (let i = 0; i < circles; i++){ circleList[i] = new Circle((100 / circles) * (i + 1)); circleList[i].attract(attractorList); } // The walk function will be called until it returns false. function walk(i) { let goOn = true; for(let item of circleList){ goOn = item.walk(); } return goOn; }