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;
}