Turtle Graphics

Turtle Graphics is a conceptual model for teaching computational thinking, based on a “first-person cursor”. In this schema, developed in the 1960s by computer scientist and constructivist educator Seymour Papert, and inspired by Jean Piaget‘s studies of children’s learning and embodied cognition, vector graphics are produced using a relative cursor (the “turtle”) upon a Cartesian plane.

The Turtle object has the following methods or API (application programmer’s interface):

var turtle = new Turtle(x, y); // make a turtle at x, y, facing right, pen down
turtle.left(d);                // turn left by d degrees
turtle.right(d)                // turn right by d degrees
turtle.forward(p);             // move forward by p pixels
turtle.back(p);                // move back by p pixels
turtle.penDown();              // pen down
turtle.penUp();                // pen up
turtle.goto(x, y);             // go straight to this location
turtle.setColor(color);        // set the drawing color
turtle.setColor(color(r,g,b)); // can be used to set color with r, g, b, values
turtle.setWeight(w)            // set the line width to w
turtle.face(d);                // turn to this absolute direction in degrees
turtle.angleTo(x, y);          // what is the angle from my heading to location x, y?
turtle.turnToward(x, y, d);    // turn by d degrees toward location x, y
turtle.distanceTo(x, y);       // how far is it to location x, y?

And here is the actual Turtle Graphics implementation for p5.js:

//=======================================================
// TURTLE GRAPHICS IMPLEMENTATION
// Roger Dannenberg, 2015
//
// Turtle(x, y) -- make a turtle at x, y, facing right, pen down
// left(d) -- turn left by d degrees
// right(d) -- turn right by d degrees
// forward(p) -- move forward by p pixels
// back(p) -- move back by p pixels
// penDown() -- pen down
// penUp() -- pen up
// goto(x, y) -- go straight to this location
// setColor(color) -- set the drawing color
// setWeight(w) -- set line width to w
// face(d) -- turn to this absolute direction in degrees
// angleTo(x, y) -- what is the angle from my heading to location x, y?
// turnToward(x, y, d) -- turn by d degrees toward location x, y
// distanceTo(x, y) -- how far is it to location x, y?
//
function Turtle(x, y) {
  this.x = x;
  this.y = y;
  this.angle = 0.0;
  this.penIsDown = true;
  this.color = color(128);
  this.weight = 1;
 
  this.left = function(d) {
    this.angle -= d;
  };
  this.right = function(d) {
    this.angle += d;
  };
  this.forward = function(p) {
    var rad = radians(this.angle);
    var newx = this.x + cos(rad) * p;
    var newy = this.y + sin(rad) * p;
    this.goto(newx, newy);
  };
  this.back = function(p) {
    this.forward(-p);
  };
  this.penDown = function() {
    this.penIsDown = true;
  };
  this.penUp = function() {
    this.penIsDown = false;
  };
  this.goto = function(x, y) {
    if (this.penIsDown) {
      stroke(this.color);
      strokeWeight(this.weight);
      line(this.x, this.y, x, y);
    }
    this.x = x;
    this.y = y;
  };
  this.distanceTo = function(x, y) {
    return sqrt(sq(this.x - x) + sq(this.y - y));
  };
  this.angleTo = function(x, y) {
    var absAngle = degrees(atan2(y - this.y, x - this.x));
    var angle = ((absAngle - this.angle) + 360) % 360.0;
    return angle;
  };
  this.turnToward = function(x, y, d) {
    var angle = this.angleTo(x, y);
    if (angle < 180) {
      this.angle += d;
    } else {
      this.angle -= d;
    }
  };
  this.setColor = function(c) {
    this.color = c;
  };
  this.setWeight = function(w) {
    this.weight = w;
  };
  this.face = function(angle) {
    this.angle = angle;
  }
}

Turtle Example 1

Here is an example using Turtle Graphics. Note that in order to post such code on WordPress, the entire Turtle object code must be included into your p5.js sketch file. Note that the Turtle code has been “minified” to save space.

turtle-ex1

// for posting on WordPress, I think we need everything in one file, so here's the Turtle
// code in compact form followed by my program.

function Turtle(x,y){this.x=x;this.y=y;this.angle=0.0;this.penIsDown=true;this.color=color(128);this.weight=1;this.left=function(d){this.angle-=d};this.right=function(d){this.angle+=d};this.forward=function(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;var newy=this.y+sin(rad)*p;this.goto(newx,newy)};this.back=function(p){this.forward(-p)};this.penDown=function(){this.penIsDown=true};this.penUp=function(){this.penIsDown=false};this.goto=function(x,y){if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);line(this.x,this.y,x,y)};this.x=x;this.y=y};this.distanceTo=function(x,y){return sqrt(sq(this.x-x)+sq(this.y-y))};this.angleTo=function(x,y){var absAngle=degrees(atan2(y-this.y,x-this.x));var angle=((absAngle-this.angle)+360)%360.0;return angle};this.turnToward=function(x,y,d){var angle=this.angleTo(x,y);if(angle<180){this.angle+=d}else{this.angle-=d}};this.setColor=function(c){this.color=c};this.setWeight=function(w){this.weight=w};this.face=function(angle){this.angle=angle}}


function setup() {
    createCanvas(400, 400);
    background(0);
    var turtle = new Turtle(130, 80);
    turtle.penDown();
    turtle.setColor(255);
    for (var i = 0; i < 1000; i++) {
        turtle.forward(150);
        turtle.right(141.5);
        turtle.forward(60);
        if (i % 20 === 0) {
            turtle.forward(70);
        }
    }
    noLoop();
}

function draw() {
}

  


Turtle Example 2

If you want to see animated turtles, you can issue turtle commands in draw() without erasing (calling background()). In this case, draw becomes your loop. To get a turtle whose behavior changes over time, you would need to give it commands whose values were based on things like the millis(), random(), frameCount, or other progressively-modified global variables.

turtle-spiral

var myTurtle;
var startFrame;

function setup() {
    createCanvas(600, 600);
    background(0);
    myTurtle = new Turtle(width/2, height/2);
    myTurtle.setColor(color(255,200,200));
    myTurtle.setWeight(2); 
    myTurtle.penDown();
    resetCanvas();
}

function draw() {
    var step = (frameCount - startFrame)/30.0;
    myTurtle.forward(step);
    myTurtle.left(6.0);
    if (myTurtle.y > height) resetCanvas();
}

function resetCanvas() {
    background(0);
    startFrame = frameCount;
    myTurtle.penUp();
    myTurtle.goto(width/2, height/2);
    myTurtle.penDown();
}


//=======================================================
// TURTLE API
function Turtle(x, y) {
    this.x = x;
    this.y = y;
    this.angle = 0.0;
    this.penIsDown = true;
    this.color = color(128);
    this.weight = 1;

    this.left = function(d) {
        this.angle -= d;
    };
    this.right = function(d) {
        this.angle += d;
    };
    this.forward = function(p) {
        var rad = radians(this.angle);
        var newx = this.x + cos(rad) * p;
        var newy = this.y + sin(rad) * p;
        this.goto(newx, newy);
    };
    this.back = function(p) {
        this.forward(-p);
    };
    this.penDown = function() {
        this.penIsDown = true;
    };
    this.penUp = function() {
        this.penIsDown = false;
    };
    this.goto = function(x, y) {
        if (this.penIsDown) {
            stroke(this.color);
            strokeWeight(this.weight);
            line(this.x, this.y, x, y);
        }
        this.x = x;
        this.y = y;
    };
    this.distanceTo = function(x, y) {
        return sqrt(sq(this.x - x) + sq(this.y - y));
    };
    this.angleTo = function(x, y) {
        var absAngle = degrees(atan2(y - this.y, x - this.x));
        var angle = ((absAngle - this.angle) + 360) % 360.0;
        return angle;
    };
    this.turnToward = function(x, y, d) {
        var angle = this.angleTo(x, y);
        if (angle < 180) {
            this.angle += d;
        } else {
            this.angle -= d;
        }
    };
    this.setColor = function(c) {
        this.color = c;
    };
    this.setWeight = function(w) {
        this.weight = w;
    };
    this.face = function(angle) {
        this.angle = angle;
    }
}


Turtle Example 3

Here’s an example of three Turtles (red, green and blue) chasing a gray “target”, whose location is based on Perlin noise.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var t1, t2, t3;
function setup() {
    createCanvas(600, 600);
    background(0);
    t1 = new Turtle(width/2 + random(-100, 100), height/2 + random(-100, 100));
    t2 = new Turtle(width/2 + random(-100, 100), height/2 + random(-100, 100));
    t3 = new Turtle(width/2 + random(-100, 100), height/2 + random(-100, 100));
    t1.penDown();
    t1.setColor(color(255, 0, 0));
    t1.setWeight(3);
    t2.penDown();
    t2.setColor(color(0, 255, 0));
    t2.setWeight(3);
    t3.penDown();
    t3.setColor(color(100, 100, 255));
    t3.setWeight(3);
}
 
function draw() {
    t1.forward(1);
    t2.forward(2);
    t3.forward(3);
    var targetX = width * noise(frameCount / 1000);
    var targetY = height * noise(100 + frameCount / 1000);
    strokeWeight(1);
    stroke(128);
    point(targetX, targetY);
    t1.turnToward(targetX, targetY, 1);
    t2.turnToward(targetX, targetY, 1);
    t3.turnToward(targetX, targetY, 1);
    t1.left(random(-5, 5));
    t2.left(random(-5, 5));
    t3.left(random(-5, 5));
}