Press F1 or click here to show/hide this help
Type your commands at the prompt and see them faithfully executed by our eponymous turtle. Press F1 to toggle between the prompt and this help screen.
What's turtle graphics? From Wikipedia: "Turtle graphics is a term in computer graphics for a method of programming vector graphics using a relative cursor (the "turtle") upon a Cartesian plane. Turtle graphics is a key feature of the Logo programming language."
Here, you'll be programming in JavaScript instead of the Logo language, but you still get to watch a triangle race around the screen!
The interactive prompt below exposes the valiable t
, which is an instance of class Turtle
.
Here's a quick rundown of its methods.
method | description |
---|---|
t.fd(n) | Forward. Move ahead by n pixels. |
t.bk(n) | Back. Move in reverse by n pixels. |
t.rt(deg) | Right turn. Rotate deg clockwise. |
t.lt(deg) | Left turn. Rotate deg counter-clockwise. |
t.pu() | Pen up. Turtle no longer traces line along its path. |
t.pd() | Pen down. Turtle resumes tracing line along its path. |
t.circle(radius) | Make an empty circle with midpoint at turtle position, with given radius . |
t.disc(radius) | Make a solid disc with midpoint at turtle position, with given radius . |
t.clean(bgColor) | Erases all lines. If bgColor is provided, updates background color. |
t.home() | Revert turtle to center screen (0,0) and facing "north". |
t.clear() | Equivalent to clean() and home() together. |
t.reset() | Same as clear() , but also restores defaults. |
t.color(color) | Sets pen color. Accepts any CSS color. |
t.thickness(n) | Sets the width in px of the pen stroke. |
t.face(x, y) | Turtle faces toward the given absolute coordinate. |
t.butt(x, y) | Turtle faces away from the given absolute coordinate. |
t.xy(x, y) | Moves turtle to given absolute coords, where origin (0,0) is center of screen. |
t.x(x) | Moves turtle to given absolute X coord, leaving Y coord unchanged. |
t.y(y) | Moves turtle to given Y coord, leaving X coord unchanged. |
t.heading(deg) | Sets absolute turtle direction in degrees, with 0 being "north". |
The above methods all return this
, so they can be chained, e.g. t.fd(100).rt(90).fd(100)
.
You may also wish to query turtle state.
For that, we have the get
methods.
method | description |
---|---|
t.get.x() | Turtle's x position where origin (0,0) is center of screen. |
t.get.y() | Turtle's y position where origin (0,0) is center of screen. |
t.get.heading() | Turtle's orientation in degrees, where 0 is "north". |
t.get.pu() | true if pen is up, false otherwise. |
t.get.pd() | true if pen is down, false otherwise. |
t.get.color() | Pen color. |
t.get.background() | Background color. |
t.get.thickness() | Width in pixels of pen stroke. |
t.get.top() | Top boundary of screen. |
t.get.bottom() | Bottom boundary of screen. |
t.get.left() | Left boundary of screen. |
t.get.right() | Right boundary of screen. |
t.get.oob() | Returns true if the turtle has moved out of bounds of the screen. |
...and also some randomness functions for convenience.
method | description |
---|---|
t.rand.uni([lower, ]upper) | A uniform distribution between lower (or zero) and upper . |
t.rand.norm(mean, stdDev) | A normal distribution with the given mean and stdDev (standard deviation). |
t.rand.chance(odds) | Returns true with a probability of odds , where odds is between 0 and 1. |
JavaScript provides a number of ways to do loops, and you're certainly free to use them here. Alternatively, the turtle gives you a couple of its own ways to do things over and over again. This allows you to do loops the "turtle" way, which isn't necessarily better, just fitting with the rest of the API.
method | description |
---|---|
t.repeat(n, func) | Runs func until it returns false or until it runs n times, passing i as arg. |
t.forever(func) | Runs func until it returns false, passing i as arg. |
Colors can take any form accepted by CSS or canvas.
This includes "#fff"
, "#ffffff"
, "rgb(...)"
, "hsl(...)"
, and even "rgba(...)"
and "hsla(...)"
.
Some drawings finish quickly, while others take a long time. This is because the drawing is rendered sequentially, piece by piece, and sometimes there are lots of pieces. To speed things up, when the number of pieces gets quite long, more and more of them are batched together between renders. When the drawing approaches the end, this batching decreases and then stops. You'll see the turtle initially tear through the drawing at a high rate of speed, and then slow to a more leisurely pace at the end. Your machine is actually working harder at the beginning of the drawing than at the end.
Who am I? My name is Greg Reimer. I build web applications for fun and profit. Find me on github and LinkedIn. This turtle graphics project is also on github under the MIT license. If you write an awesome sample program that you think should be included here, send me a pull request!
t.reset() .color('rgba(255,255,255,0.15)') .repeat(720, function(i){ if(i%72 < 36){ t.fd(2000).bk(2000); } t.rt(.5); })
t.reset() .repeat(1000, function(i){ t.fd(i).rt(90.1) })
var phi = (Math.sqrt(5) + 1)/2; t.reset().color('rgba(255,255,255,0.2)') .repeat(987, function(){ t.fd(2000).pu().bk(2000).pd().rt(360*phi); });
t.reset() .color('rgba(255,255,255,0.1)') .repeat(200000, function(){ t.fd(3).rt(t.rand.uni(-10,10)) if (t.get.oob()) t.home().rt(t.rand.uni(360)) })
t.reset() .repeat(10, function(){ t.repeat(36, function(i){ t.color('hsla('+(i*10)+',50%,50%,0.3)') .repeat(36, function(){ t.fd(27).rt(10) }).rt(10); }).rt(1); });
var phi = (Math.sqrt(5) + 1)/2; t.reset().repeat(1000, function(i){ t.pu().rt(360*phi).fd(Math.log(i)*40).pd(); t.repeat(50, function(j){ t.color('hsla('+((360 * (i/1000))-120)+',50%,50%,'+ Math.pow(1.1,-j) +')').fd(2.5); }); t.pu().xy(0,0).pd(); });
var phi = (Math.sqrt(5) + 1)/2; t.reset().repeat(3000, function(i){ t.pu().rt(360*phi).fd(Math.log(i)*40).pd(); t.repeat(25, function(j){ t.color('hsla('+((360 * (i/3000))-120)+',50%,50%,'+ Math.pow(1.2,-j) +')').fd(5).lt(2); }); t.pu().xy(0,0).pd(); });
var circle = (function(){ function circ(size, steps, level) { t.repeat(2, function(){ if (level > 0) { circ(size/2, steps, level-1); } t.repeat(steps, function(){ t.fd((size/steps)*2).rt(180/steps); }); }); } return function(size, steps, level){ var r = (size/Math.PI)*2; t.pu().lt(90).fd(r).rt(90).pd().rt((180/steps)/2); circ(size, steps, level); t.lt((180/steps)/2).pu().rt(90).fd(r).lt(90).pd(); } })(); t.reset().color('rgba(255,255,255,0.5)'); circle(500, 20, 8);
function triangle(len, level){ if (level < 1) { t.repeat(3, function(){ t.fd(len).rt(120); }); } else { t.repeat(3, function(){ t.pd(); triangle(len/2, level-1); t.pu().fd(len).rt(120); }) } } t.reset().xy(-300, -200).rt(30).clean(); triangle(600, 7);
var triangle = (function(){ function frag(len, depth, left){ if (left === undefined) left = !(depth % 2); if (depth > 1) { frag(len/2, depth-1, !left); t[left?'lt':'rt'](60); frag(len/2, depth-1, left); t[left?'lt':'rt'](60); frag(len/2, depth-1, !left); } else { t.fd(len); } } return frag; })(); t.reset().pu().bk(250).rt(90).bk(350).pd().color('hsl(30, 100%, 70%)'); triangle(700, 8);
var koch = (function(){ function frag(len, depth){ if (depth > 1) { frag(len/3, depth-1); t.rt(60); frag(len/3, depth-1); t.lt(120); frag(len/3, depth-1); t.rt(60); frag(len/3, depth-1); } else { t.fd(len); } } return function(len, depth){ frag(len,depth); t.lt(120); frag(len,depth); t.lt(120); frag(len,depth); t.lt(120); } })(); t.reset().bk(300).clean().rt(30).color('#0f0'); koch(550, 6);
var kochRandom = (function(){ function frag(len, depth){ if (depth > 1) { var r = t.rand.chance(1/2); frag(len/3, depth-1); t[r?'rt':'lt'](60); frag(len/3, depth-1); t[r?'lt':'rt'](120); frag(len/3, depth-1); t[r?'rt':'lt'](60); frag(len/3, depth-1); } else { t.fd(len); } } return function(len, depth){ frag(len,depth); t.lt(120); frag(len,depth); t.lt(120); frag(len,depth); t.lt(120); } })(); t.reset().bk(300).clean().rt(30).color('#90f'); kochRandom(550, 6);
var kochRandom = (function(){ function frag(len, depth){ if (depth > 1) { var r = t.rand.chance(1/2); frag(len/3, depth-1); t[r?'rt':'lt'](60); frag(len/3, depth-1); t[r?'lt':'rt'](120); frag(len/3, depth-1); t[r?'rt':'lt'](60); frag(len/3, depth-1); } else { t.fd(len); } } return function(len, depth){ frag(len,depth); t.lt(120); frag(len,depth); t.lt(120); frag(len,depth); t.lt(120); } })(); t.reset().bk(300).clean().rt(30); t.repeat(60, function(i){ t.color('hsla('+i+',50%,50%,0.1)'); kochRandom(550, 6); });
function tree(length, branches, depth, origDepth){ if (origDepth === undefined) origDepth = depth; var l = t.rand.uni(length*.95,length*1.05); t.color('rgba(255,255,255,'+(depth+1)/origDepth+')').fd(l); var angle = 180/branches; if (depth > 0) { t.lt(90); for (var i=0; i<branches; i++){ t.rt((angle/2)); var angleJitter = t.rand.uni(-5,5); t.rt(angleJitter); tree(length*(3/4), branches, depth-1, origDepth); t.lt(angleJitter); t.rt(angle/2); } t.lt(90); } t.pu().bk(l).pd(); } t.reset().bk(280).clean(); tree(180,4,6);
function dragon(length, iters){ var d = [true]; for (var i=0; i<iters; i++) { var len = d.length; d.push(true); for (var j=len-1; j>=0; j--) { d.push(!d[j]); } length = Math.sqrt((length * length) / 2); } var c = 0; for (var i=0; i<d.length; i++) { c += .01; t.color('hsl('+c+',100%,70%)').fd(length)[d[i]?'rt':'lt'](90); } } t.reset().xy(250,170).clean().lt(95); dragon(470,15);
t.reset() .color('rgba(255,255,255,0.1)') .repeat(360, function(i){ t.pu().home().pd() .repeat(80, function(){ t.fd(20).rt(t.get.y()+i) }) })