- Tasks
- Core Settings
- Turtle Attributes
- Miscellaneous
INTRODUCTION
Overview
Turtle Graphics is a Javascript implementation of the popular geometric drawing tools introduced in Logo, developed by Wally Feurzeig, Seymour Papert and Cynthia Solomon in 1967.
Imagine a robotic turtle starting at (0, 0) in the x-y plane. After creating a turtle, give
it the command turtle.forward(15)
, and it moves (on-screen!) 15 pixels in the direction it is
facing, drawing a line as it moves. Give it the command turtle.right(25)
, and it rotates in-place
25 degrees clockwise.
In this library, turtle graphics provides a representation of a physical “turtle” (a little robot with a pen) that draws on a sheet of paper on the floor.
Turtle drawing was originally created as an educational tool, to be used by teachers in the classroom. For the programmer who needs to produce some graphical output it can be a way to do that without the overhead of introducing more complex or external libraries into their work.
NOTE: This library is written entirely in Javascript and is not dependant on any other library. All examples use p5js as a simple application framework to demonstrate this library but users are free to choose an alternative if they wish.
INTRODUCTION
Creating our First Turtle
The first step is to create a turtle with the statement
let turtle = TG.getTurtle(400, 200);
The 2 parameters define the width and height of the graphics area the turtle can draw in. Although the turtle is not confined to this area anything drawn outside it will not be visible.
Once the turtle has been created we can command the turtle to move, turn, draw lines by adding tasks in the order that we want them to be performed. For instance the statement -
turtle.forward(20).right(25).forward(55).start();
will move the turtle 20 pixels in the direction it is facing, turn right 25° to the
right,
move forward 55 pixels all the time, drawing a line using the current pen color. The last task
start()
instructs the turtle to start performing the tasks in the specified order. If it is
included in the list of tasks turtle animation starts immediately. Alternatively we can add the tasks then
start the turtle at some later time.
There is no limit to the number of tasks that can be added to the turtle and the library includes over 40 unique tasks to choose from. They are all described in the Tasks section of this guide.
TASKS
Move and Draw
turtle.x(x, fill_gap = false)
turtle.y(y, fill_gap = false)
turtle.xy(x, y, fill_gap = false)
Move the turtle to an absolute position without drawing a line and without changing the turtle's heading. If currently filling, any existing fill shape will be filled before moving and a new fill shape will be started after moving.
This can be disabled with fill_gap = true
, which makes the
imaginary line traveled during movement part of the current fill shape.
The change of position is applied without any animation.
turtle.dxy(d_x, d_y, fill_gap = false)
Move the turtle to a position relative to the current poition without drawing a line and without changing the turtle's heading. If currently filling, any existing fill shape will be filled before moving and a new fill shape will be started after moving.
This can be disabled with fill_gap = true
, which makes the imaginary line traveled during
movement
part of the current fill shape.
The change of position is applied without any animation.
turtle.face(angle)
Change the turtle's forward direction so it faces the specified angle.
The change of angle is applied without any animation.
turtle.forward(distance)
turtle.fd(distance)
Move the turtle in the direction it is headed by the distance
pixels.
turtle.backward(distance)
turtle.back(distance)
turtle.bk(distance)
Move the turtle opposite to the direction it is headed by distance
pixels.
The turtle's heading is unchanged.
turtle.left(ang)
turtle.lt(ang)
Turn left by the specified angle. The default rotational unit is degrees (°) but chan be changed to radians.
turtle.right(ang)
turtle.rt(ang)
Turn right by the specified angle. The default rotational unit is degrees (°) but chan be changed to radians.
turtle.heading(angle)
turtle.head(angle)
Change the turtle's heading to this angle. The default rotational unit is degrees (°) but be changed to radians.
turtle.home()
Move the turtle to its home position [0, 0].
turtle.goto(x, y)
Move turtle to an absolute position. If the pen is down then a line is drawn. The the turtle's heading will be changed to match the direction moved.
turtle.goby(dx, dy)
Move turtle to a position relative to the current postion. If the pen is down then a line is drawn. The the turtle's heading will be changed to match the direction moved.
turtle.dot(size = 6, fill_color = 'current', bdr_weight = 0, bdr_color = 'current')
Draw a circular dot with specified radius.
- If
size
is ≤ 0 then the maximum ofpensize + 4
and2 * pensize
is used. - The default dot is borderless unless
bdr_weight
is ≥ 0. Ifbdr_weight
=0 then the current pensize is used. -
fill_color
the fill color to use. If not provided or ='current'
then the current fill color is used. -
bdr_color
the border color to use. If not provided or ='current'
then the current pen color is used.
turtle.arrow(size = 6, fill_color = 'current', bdr_weight = 0, bdr_color = 'current')
Draw an arrow head (triangle) so its tip is at the current pen position and it is facing the current heading.
-
size
= the side length of the arrow head. The default value is 6 - The default arrow is borderless unless
bdr_weight
is ≥0. Ifbdr_weight
=0 then the current pensize is used. -
fill_color
the fill color to use. If not provided or ='current'
then the current fill color is used. -
bdr_color
the border color to use. If not provided or ='current'
then the current pen color is used.
turtle.circle(rad_b, extent = 0, turnDir = RT, steps = 0)
turtle.oval(rad_a, rad_b, extent = 0, turnDir = RT, steps = 0)
Follow a circular or oval path. The path can be smooth or created from a number of straight lines, (chords)
![folllowing an oval path](ovals.png)
-
rad_a
is the radius in the current direction of travel (heading). -
rad_b
is the radius orthoganol to the current direction of travel (heading). -
extent
the angle to be subtended by the turtle. A full circle / oval is drawn if the extent is 360° or 2π radians. -
turnDir
must be eitherLT
orRT
and determines whether the turtle turns to the left or to the right. The actual visual effect depends on the turtle's mode. steps
if =0 then the path will be smooth. If >0 then each 'step' along the path is a chord or the circle / oval.
The turtle paths shown in the picture above were created with the following code -
turtle.rt(25).fd(55).arrow(6)
.oval(25, 15, 150, RT, 0).arrow(6)
.fd(130).arrow(6)
The curve drawn depends on the turtle's mode as shown in the image. The default mode is 'display'
turtle.sleep(duration)
Pause the turtle animation for duration
milliseconds.
turtle.write(text, align = 'left', move = false, font : optional)
Draw the string representation of text
at the current turtle position. This image shows the affect
of the parameter values passed to the task.
![shows text alignment options](writealign.png)
In the diagram the blue arrows indicate the position and heading of the turtle just before the
text is drawn. The text baseline (dashed line) is perpendicular to the tutle's heading. The text can be
aligned "left"
, "center"
or "right"
to this position. Once the text is
drawn the move
parameter determines whether the turtle is moved along the baseline to the end of
the text.
No matter which options are chosen the turtle's heading is unchanged and is shown by the red dashed line.
If no font descriptor is provided (font
) then the default font is used.
turtle.font(style)
Set the default font style for this turtle. This style will be used in future write
tasks until
changed.
TASKS
Pen Control
turtle.penup()
turtle.pu()
turtle.up()
Lift the pen up so there is no drawing when moving.
turtle.pendown()
turtle.pd()
turtle.down()
Put the pen down so there is drawing when moving.
turtle.pensize(width = 2)
Changes the line-width used when drawing.
turtle.dash(pattern[line_len, gap_size ...] : optional)
The parameter is an array of numbers representing the dash pattern to be used. The numbers are in pairs where the first is the line-length and the second the gap size, addition number pairs can be included to create more complex patterns.
![shows line dash examples](dash.png)
If pattern
is an empty array or is not provided then all subsequent lines will be solid until a
new dash pattern is specified.
turtle.pencap(cap)
turtle.cap(cap)
Changes the line-cap used at the end of a line. Valid options are BUTT, SQUARE or ROUND. The default value is ROUND.
![shows line caps options](linecaps.png)
turtle.pencolor(color)
Changes the color used to draw lines.
turtle.fillcolor(color)
Changes the color used to fill shapes created by the turtle.
turtle.push_pen()
Push (save) the current pen's position and style on the stack. This includes the following information :-
Pen position:-
- X coordinate
- Y coordinate
- heading
Pen style:-
- whether the pen is up or down
- the pen size, dash-style and color
- the line cap style
- the fill color
- whether to trace (animate) the movement
- whether the turtle cursor is visible or not
- tilt angle for the turtle cursor
- the pen's linear and rotational speeds
turtle.pop_pen(what = STYLE_POS)
Restore the pen status saved by the last push_pen()
statement. The parameter,
what
, determines which attributes are restored -
- STYLE : style attributes only
- POS : position and heading attributes only
- STYLE_POS : style, position and heading attributes (default value)
TASKS
Turtle Control
turtle.turtle(cursor)
This default cursor is called DART but the library has several predefined cursors to choose from they are :-
![library cursors](cursors.png)
To change the turtle cursor to a star then use turtle.turtle(STAR)
.
As well as the library cursors, this task will also accept user defined cursors.
turtle.showturtle()
turtle.st()
Show the turtle cursor.
turtle.hideturtle()
turtle.ht()
Hide the turtle cursor.
turtle.tilt(angle : optional)
If angle
is not provided then the turtle cursor is rotated to match the current forward direction
and the current tilt angle is ignored. If a value is provided then it is used to rotate the cursor
irrespective
of the turtle's heading.
turtle.speed(linear, angular)
This task can be used to change either or both the
- turtle's linear speed (pixels/s)
- turtle's rotational speed (°/s or radians/s)
If either parameter value is NaN
then the current value is unchanged. The
default rotational unit is degrees (°) but can be changed to
radians.
TASKS
Filling and Tracking
turtle.begin_fill()
Start remembering vertices for a shape that is to be filled later.
turtle.end_fill(close = false)
Fill the shape drawn after the last call to begin_fill() with the current fill-color. If close
is
true then a line is drawn to the start of the fill, closing ths shape.
Whether or not overlap regions for self-intersecting polygons or multiple shapes are filled depends on the operating system graphics, type of overlap, and number of overlaps.
turtle.begin_poly()
Start recording the vertices of a polygon. Current turtle position is first vertex of polygon.
turtle.end_poly(id)
Stop recording the vertices of a polygon keeping the current turtle position as the last vertex.
A unique identifier (id
) must be provided so the polygon vertices can be retrieved later with -
turtle.getPoly(id);
The polygon returned is an array of [x,y] tuples.
turtle.begin_record()
Start recording the tasks assigned to this turtle.
turtle.end_record(id)
Stop recording the tasks assigned to this turtle. A unique identifier (id
) must be provided so
the
task-list can be executed by this, or any other turtle using the do
task like this -
turtle.do(id);
any_other_turtle.do(id)
turtle.do(...action)
The parameter action
comprises one or more comma seperated values. The first value is either
- the id of a task-list created with
begin_record
andend_record
so if we recorded a task sequence with the id 'action` then we can replay theses tasks withturtle.do('record_id');
and additional parameters will be ignored. - a javascript function. The first parameter in this function will be the turtle followed by and additional
values will be passed to the
do
function. In this example the turtle's speed is changed by a user defined percentage.
turtle.do(change_speed, 25); // increase speed by 25%
The user defined function has two parameters, the first is the turtle calling this method and the second an array holding any additional parameter values passed to the
function change_speed(turtle, data){
let by = data[0] / 100;
let speed = turtle.getSpeed();
turtle.setSpeed(speed[0] * (i + by), speed[1] * (i + by));
}do
function. In this casedata = 25
TASKS
Graphics Control
turtle.animateon()
turtle.animateoff()
If animation is switched off then all tasks will be completed as fast as possible ignoring the current speed values. Switching it back on re-enables the turtle animation.
turtle.clear()
This will erase all graphics created by this turtle leaving a blank canvas. The turtle's position, heading and other attributes are unchanged.
turtle.reset()
As well as erasing the current canvas; the turtle's position, heading and all other attributes are returned to their initial values.
turtle.snapshot(id)
Store a copy of the current turtle-graphics image. A unique identifier (id
) must be provided so
the snapshot can be retrieved later with - turtle.getSnapshot(id);
CORE SETTINGS
Animation Control
turtle.start()
This will cause the turtle to immediately start processing any queued tasks. If there are no tasks to process then the turtle will wait and process new tasks as and when they are added to the task queue.
turtle.stop()
This will stop the turtle processing any queued tasks. To restart processing the start
method
should be executed manually with -
turtle.start();
CORE SETTINGS
Graphic Modes
This library supports 3 modes each having its own coordinate system they are DISPLAY, STANDARD and LOGO. The turtle's mode is specified by adding one of these options as a third parameter when creating the turtle e.g.
let turtle = TG.getTurtle(200, 200, STANDARD);
The standard and logo modes are included for compatability with earlier turtle graphic libraries. If the mode is not specified then the turtle uses the DISPLAY option.
![image showing 3 graphic modes available](modes.png)
Mode | X axis direction | Y axis direction | 0° direction | increasing angle |
---|---|---|---|---|
display | East | South | East | Clockwise |
standard | East | North | East | Counterclockwise |
logo | East | North | North | Clockwise |
Movement and rotation depends on the mode coordinate system for that turtle, Turning left or right is not dependant on the forward direction, instead right turns increase the heading angle and left turns decrease the heading angle.
turtle.degrees()
Set angle measurement units to degrees. This applies to all angles expected by and returned from the turtle functions. It is the default unit for new turtles.
turtle.radians()
Set angle measurement units to radians. This applies to all angles expected by and returned from the turtle functions.
turtle.getModeXY(x, y, cx = 0, cy = 0)
Convert the screen coordinates x
and y
to the equivalent position in mode space.
The
parameters cx
and cy
represent the screen position for the center of the turtle
graphics. The turtle position is unchanged.
The mode coordinates are returned as a tuple [mx, my]
.
turtle.getModeH(screenH)
Given a screen heading (screenA
) get the equivalent mode heading. The turtle heading is
unchanged.
turtle.getScreenXY(cx = 0, cy = 0)
Convert the current pen coordinates to the equivalent position on the screen. The parameters cx
and
cy
represent the screen position for the center of the turtle graphics.
The screen coordinates are returned as a tuple [sx, sy]
.
turtle.getScreenH()
Get the current pen heading after converting to the equivalent screen angle.
TURTLE ATTRIBUTES
About
Unlike tasks which are queued and then performed in sequence later, these functions are used to set the turtles's attributes with immediate effect; although most have a matching task which can be used instead.
These methods support the creation of user defined tasks based on the current state of
the turtle. Assume we want a task that doubles the pensize and halves its speed, there is no
task
that does this but it is possible to solve this problem. In this example we create a task called
foo_task
that does just that.
function foo_task(turtle, data){
let psize = turtle.getPensize();
let speed = turtle.getSpeed();
turtle.setPensize(psize * 2);
turtle.setSpeed(speed[0] / 2, speed[1] / 2);
}
turtle.do(foo_task, 25); // perform our user defined task
TURTLE ATTRIBUTES
Position and Heading
turtle.getX()
Return the turtle's x position.
turtle.setX(x)
Sets the turtle's x position.
turtle.getY()
Return the turtle's y position.
turtle.setY(y)
Sets both the turtle's y position.
turtle.getXY()
Return the turtle's position as a tupple:- [x, y]
.
turtle.setXY(x, y)
Sets both the turtle's x and y position.
turtle.getHeading()
turtle.getH()
Return the turtle's heading.
turtle.setHeading(angle)
turtle.setH(angle)
Set the turtle's heading to this angle. The default rotational unit is degrees (°) but be changed to radians.
TURTLE ATTRIBUTES
Pen Control
turtle.getPenSize()
Return the turtle's pen size.
turtle.setPenSize(size)
Sets the turtle's pen size.
turtle.getPenColor()
Return the color used for drawing lines.
turtle.setPenColor(color)
Sets the color used to draw lines.
turtle.getDash()
Return the current dash pattern as an array. (see setDash below for details)
turtle.setDash(pattern[line_len, gap_size ...] : optional)
The parameter is an array of numbers representing the dash pattern to be used. The numbers are in pairs where the first is the line-length and the second the gap size, addition number pairs can be included to create more complex patterns.
![shows line dash examples](dash.png)
If pattern
is an empty array or is not provided then all subsequent lines will be solid until a
new
dash pattern is specified.
turtle.getCap()
Return the current line-end style.
turtle.setCap(style)
Sets the line-cap used at the end of a line. Valid options are BUTT, SQUARE or ROUND.
![shows line caps options](linecaps.png)
turtle.getFillColor()
Return the color used for filling shapes.
turtle.setFillColor(color)
Sets the color used to fill shapes.
TURTLE ATTRIBUTES
Turtle Control
turtle.getSpeed()
Return the turtle's position as a tupple:- [x, y]
.
turtle.setSpeed(linear, angular)
Sets either or both the
- turtle's linear speed (pixels/s)
- turtle's rotational speed (°/s or radians/s)
If either parameter value is NaN
then the current value is unchanged.
The default rotational unit is degrees (°) but chan be changed to radians.
turtle.setTurtle()
turtle.setCursor()
Change the turtle's cursor. The parameter cursor
can be a library or user
defined cursor.
![library cursors](cursors.png)
TURTLE ATTRIBUTES
Graphics Control
turtle.getPoly(id)
Get the vertices for a recorded polygon with the specified id
. The points will
be
transformed to DISPLAY mode coordinates irrespective of the turtle's mode so they correspond to the
vertex
positions as displayed on the computer screen.
The vertices are are stored in an array of tuples:-
[ [x0, y0], [x1, y1], [x2, y2], ... ]
If this turtle has no polygon named id
then this function returns
undefined
turtle.getSnapshot(id)
Get the saved image with the specified id
. The returned image will be of type
OffscreenCanvas
.
If this turtle has no image named id
then this function returns
undefined
turtle.getImageFromOsc(osc, p)
A p5js helper function to convert a OffscreenCanvas (osc
) image to a Processing
image. The second parameter, p
, is a reference to the Processing sketch.
The returned image will be of type p5.Image
TURTLE ATTRIBUTES
Cursors
Modified library cursors
![library cursors](cursors.png)
It is possible to create new cursors based on these shapes but with user defined size and colors.
// modified TURTLE shape
cursor = csrTURTLE(size, skin_col, shell_col, sw, scol);
// all other shapes (replace ??? by library cursor name e.g. ARROW)
cursor = csr???(size, fcol, sw, scol);
Where -
-
size
is the desired size of the cursor. -
skin_col
the color used fo the legs and head of the turtle. -
shell_col
the color used fo the shell of the turtle. -
sw
the width of the border highlight. The hide the border set this parameter to 0 (zero). -
scol
The border highlight color.
To change the turtle cursor to a white star with a strong red border use -
cursor = csrSTAR(30, 'white', 2, 'red');
turtle.turtle(cursor);
From JS OffsceenCanvas
A cursor can be created from any predefined image (of type OffscreenCanvas
)
using
the function
cursor = new Cursor(osc, fx, fy);
Where -
-
osc
is the predefined image. -
fx
the normalised horizontal position of the cursor hit position. -
fy
the normalised vertical position of the cursor hit position.
The values fx
and fy
are in the range 0.0 to 1.0 and if multiplied
by the image width and height respectively gives the pixel position of the hit spot.
From p5js image
A p5js helper function to create a cursor from any predefined image (of type
p5.Image
).
cursor = getCursorFromImage(p5image, fx, fy);
Where -
-
p5image
is the predefined p5js image. -
fx
the normalised horizontal position of the cursor hit position. -
fy
the normalised vertical position of the cursor hit position.
The values fx
and fy
are in the range 0.0 to 1.0 and if multiplied
by the image width and height respectively gives the pixel position of the hit spot.
TURTLE ATTRIBUTES
Fonts
Font descriptors
The font descriptor is a string variable which contains either 3 or 4 font attributes. The format is
"WEIGHT STYLE SIZE FAMILY_NAME"
WEIGHT - any value in the range 1 and 1000 inclusive is valid but it is usually a multiple of 100. Normal weight is 400 and bold 700.
STYLE - If not included in the descriptor then plain text is used. Valid values include 'italic' and ' oblique' both have the effect of making the text lean to the right.
SIZE - This is the font size, examples include 12px 40em ...
FAMILY_NAME - There are two types of font family names:
- family-family such as "times", "courier", "arial", etc.
- generic-family the 5 generic families are called "serif", "sans-serif", "cursive", "fantasy" and "monospace".
Font descriptor examples include:
- '400 italic 12px fantasy'
- '700 16px Arial'
- '100 20px "Gill Sans MT"'
For more information about CSS fonts clck here.
TURTLE ATTRIBUTES
Colors
Color descriptors
In this library there are several tasks that expect color-values to be passed as string parameters. Based on CSS guidelines these strings can be named-colors, color-functions or hex-coded.
Named colors:
CSS defines a large set of named colors, so that common colors can be written and read more
easily. Apart from the expected 'white'
, 'black'
, 'yellow'
there are
over
160 named colors which you can see here. There is also a named color 'transparent'
.
Color functions (modern syntax):
The functions for three common color spaces are described here -
- sRGB : red, green blue with optional alpha.
- sHSL : hue, saturation, luminance with optional alpha.
- sHWB : hue, whiteness, blackness with optional alpha.
'rgb(r g b)'
'rgb(r g b / a)'
'rgb(h s l)'
'rgb(h s l / a)'
'hwb(h w b)'
'hwb(h w b / a)'
Parameters | Valid ranges (inclusive) |
---|---|
r g b | 0 -> 255 or 0% -> 100% |
h | 0 -> 360 |
s l w b | 0 -> 100 or 0% -> 100% |
a | 0.0 -> 1.0 or 0% -> 100% |
Note that the parameters are separated by whitespace and the optional alpha term is separated by a solidus ("/").
Valid examples of color descriptors include 'rgb(90% 95% 10%)'
,
'hsl(330 50 90 / 0.5)'
, 'hwb(270 20 35 / 30%)'
RGB hexadecimal coded:
A color value is created by specifying each channel as a hexadecimal number in the range 00 to FF (0 to 255 in decimal) then concatenating them into a string preceeded with a hash (#) i.e. '#RRGGBB'. To include the channel its hexadecimal value must alse be concatenateed i.e. '#RRGGBBAA'
'#FF00FF'
: red (255), green (0), blue(255) - purple.'#FF00FF20'
: red (255), green (0), blue(255), alpha (32) - translucent purple.
A full description of RGB hexadecimal code values can be found here.
TURTLE ATTRIBUTES
Properties (getters)
turtle.mode
Returns the mode type - DISPLAY, STANDARD, LOGO
.
turtle.mode$
Returns the mode type as a string - "DISPLAY", "STANDARD", "LOGO".
turtle.hasTasks
Returns true
if the turtle still has tasks to complete.
turtle.nbrTasks
Returns the number of tasks still to complete.
turtle.isActive
Returns true
if the turtle is still being updated.
turtle.isAnimating
Returns true
if animation is turned on.
turtle.isVisible
Returns true
if the turtle cursor is visible.
turtle.isPenDown
Returns true
if the pen is down and drawing lines.
turtle.nbrStyles
Returns the number of styles remaining on the stack.
MISCCELLANEOUS
Methods
turtle.doClear()
This will erase all graphics created by this turtle leaving a blank canvas. The turtle's position, heading and other attributes are unchanged.
turtle.doReset()
As well as erasing the current canvas; the turtle's position, heading and all other attributes are returned to their initial values.
turtle.setUpdateInterval()
The turtle's state is updated every 25 milliseconds (default value). In most cases this is perfectly adequate but if the application has a lot of turtles it may improve performance if the interval is increased.
The animation speed is independant of the update interval but my appear jerky at high intervals.
turtle.spawn()
Returns a duplicate of this turtle.