More Smiles!

Based on Smile!

Changed so that height, width, & spacing can be specified.

Log in to post a comment.

// Smile!. Created by Reinder Nijhoff 2018 madified by Jasen Jacobsen 2019
// @reindernijhoff
//
// https://turtletoy.net/turtle/f51d24a066
//

const canvas_height = 70;
const canvas_width = 50;
const max_radius = 20;
const min_radius = 2;
const radius_decr = .995;
const max_tries = 1500;
const spacing = 2; // 1+

let radius = max_radius;

const circles = [];

const turtle = new Turtle();

function add_circle(t, r) {
    let coord_found = false;
    let tries = 0;
    
    while (!coord_found && tries < max_tries) {
        tries ++;
        const x = Math.random() * (canvas_width-r)*2 -canvas_width + r;
        const y = Math.random() * (canvas_height-r)*2 -canvas_height + r;
        let possible = true;
        for (let i=0; i<circles.length; i++) {
            const dx = circles[i][0] - x;
            const dy = circles[i][1] - y;
            const dr = circles[i][2] + r;
            
            if ( dx*dx + dy*dy < dr * dr * spacing) {
                possible = false;
                break;
            }
        }
        if (possible) {
            coord_found = true;
            draw_smiley(x,y,t, r);
            circles.push([x,y,r]);
            return true;
        }
    }
    return false;
}

function draw_smiley(x,y,t, r) {
    draw_imperfect_poly(x,y,t,30,r);
    if (r > 2) { // draw eyes and mouth
        t.right(Math.PI/2);
        t.penup();
        t.forward(r/2);
        t.pendown();
        t.forward(r/6)
        t.left(Math.PI/2);
        t.penup();
        t.forward(r/(1.5+Math.random()));
        t.pendown();
        t.right(Math.PI/2);
        t.forward(r/6)
        t.penup();
        t.forward(r/(1.2+Math.random()));
        t.pendown();
        t.right(Math.PI/3);
        
        const steps = Math.ceil(r*10);
        draw_imperfect_line(t, r, steps, 0.05, 2);
    }
}

function draw_imperfect_poly(x,y,t, c, r) {
    const side = 2*Math.sin(Math.PI/c) * r - 3/c;
    const side_div = 10;
    const rand_angle = Math.max(0.02,0.1/c);
    const steps = Math.ceil(side*side_div);

    t.radians();   
    t.penup();
    t.goto(x,y-r);
    t.setheading(0);
    t.circle(r,(-Math.random())*Math.PI*.3);
    t.pendown();
    
    t.right(Math.PI/c);
    for (let i=0; i<c; i++) {
        draw_imperfect_line(t, side, steps, rand_angle, 0);
        t.circle(3/c,Math.PI*2/c);
    }
    t.forward(Math.random() * r/10);
}

function draw_imperfect_line(t, side, steps, rand_angle, add_angle) {
    for(let j=0; j<steps;j++) {
        t.forward(side/steps);
        t.right((Math.random()-.5)*rand_angle + add_angle/steps);
    }    
}

function walk(i) {
    if (!add_circle(turtle, radius)) {
        radius *= radius_decr;
    }
    return radius >= min_radius;
}