All posts by auntiemyrtle

One-A-Day: Qtips

Today’s example is short but sweet. It creates a design made out of a bunch of qtip-like ‘sticks’ with balls on the ends.

It is a design made out of ‘almost squares’ (four sides each at an 85 degree angle to each other). The turtle then turns right 5 degrees, and slides left 20 before continuing to the next almost-square.

Each side of the almost-square is coloured based on its iteration in the almost-square loop, and the fill colour of the balls is set to match. Also, each iteration is raised an amount relative to its iteration, creating a pleasing 3D effect.

Click here to open the project in the viewer or open it in the webLogo IDE

TO qtips
  repeat 24 [
    repeat 4 [
      setz repcount * 3 
      ;raise up the turtle based on the loop count
      setpencolor 10 + repcount
      ;set the pen color based on the loop count
      setfillcolor pencolor 
      ;for the spheres
      icosphere 2 
      rope 100 
      ;a rope is a cylinder-based line
      icosphere 2 
      right 85
    right 5 
    slideleft 20 

New WebAssembly Build of turtleSpaces Logo Now Available

To make turtleSpaces more accessible to our users, we’ve created a WebAssembly build of turtleSpaces and paired it with a new Javascript front-end UI that renders turtleSpaces output natively in the browser, and has a code editor with syntax highlighting.

It comes with a number of built-in examples, and a fairly complete set of features: loading from the local machine, saving to the local machine, exporting STL, exporting PNG (high-resolution), and sharing using the turtleSpaces model viewer (which unlike STL is in full color).

Obviously execution in the web interface is slower than if you download the native turtleSpaces binary for your operating system, but our webLogo still provides most of the functionality of turtleSpaces while making it available for other platforms such as Chromebooks, Raspberry Pi 4 and so forth (anything that can run a Chromium-based browser).

And, because it is 3D, and has dozens of shape primitives, our webLogo still offers far more creative opportunities than other Logos.

Check out the webLogo here!

turtleSpaces Model Web Viewer

On our journey to porting turtleSpaces to the Web (yes, that’s coming!), we’ve added a primitive, SHAREVECTORS “description (or |description|) that allows users to share their creations to the web. SHAREVECTORS will return a link to the turtleSpaces website where you can view a static model, as it was in turtleSpaces when you executed the SHAREVECTORS command.

Note that the camera in the web viewer is currently fixed to the Y axis and is oriented upward, and so you need to ensure your models are oriented that way (they should look correct if you issue a CAM:CS to return the camera turtle to its home position).

You can also embed the viewer (and your creation) into your own web page if you use the following bit of code:

<iframe src="" frameBorder="0" width="720" height="512" scrolling="no">

replacing YourSceneHere with the ID of your scene (the bit in the share URL after pict= and before the ” that follows it) which looks something like 8970c41a0c9a35553e6a2613f8b0516c67381e9a556beb647de84c09

Note: Due to limitations with WebGL, pen width is not currently supported.

You can click and drag to rotate the model, or use the scroll wheel to zoom in and out.

Here’s a few embedded examples:

Logo Fireworks

This Logo program uses hatchlings to create simple 2D fireworks. The turtle’s model is changed into an icosphere to simulate a launching firework, and then more hatchlings are used to create the starburst. The trails are merged back into the main turtle ‘track’ and the hatchlings are terminated, leaving the rendered drawing on-screen at the conclusion of the program.

Read through the code (and pay particular attention to the ;comments) to see how the program works. It is made up of two procedures: fireworks, and burst.

TO fireworks
  ;simple 2D fireworks
  repeat 5 + random 10 [
    ;launch at least 5 but not more
    ;than 14 fireworks
    ;pull up the turtle's pen
    ;return to [0 0 0]
    raise repcount
    ;raise the turtle so its lines
    ;don't overlap
    sety -100
    ;set the turtle's y position to
    hatch [left -60 + random 121 burst]
    ;hatch a new turtle, turn that
    ;turtle left some random value
    ;between -60 (same as right 60)
    ;and 60 degrees, then execute the
    ;burst procedure
    wait 30 + random 31
    ;wait between one half and one
    ;second before launching the next
  ;repeat until all fireworks launched

TO burst
  ;a single firework 'burst'
  ;originally called 'firwork' but
  ;that was a little confusing!
  penup hideturtle
  newmodel "firework [icosphere 1]
  setmodel "firework
  ;create and use a simple model
  ;made from a single icosphere
  ;set a random fill color
  ;models inherit the fill color
  ;if not otherwise set inside
  ;the model
  repeat 100 + random 601 [
    ;travel between 200 and 700
    ;turtle steps
    forward 1 - 0.002 * repcount
    ;move forward 1 step minus
    ;a fraction based on the current
    ;loop iteration. This has the
    ;effect of slowing us down
    ;over time (reduce velocity)
    sety ypos - 0.0005 * repcount
    ;change the y position of the
    ;turtle a fraction based on the
    ;current loop iteration, simulating
    ;very simple gravity
    sleep 2
    ;take a little nap
  ;repeat until finished travelling
  setpencolor fillcolor
  ;set the pen color to the fill color
  repeat 20 + random 21 [
    ;create between 20 and 40 fragments
    raise 0.01
    ;ensures seperation between
    ;overlapping lines
    hatch [
      ;draw lines
      right random 360
      ;turn right between 0 and 359
      make "steps 30 + random 71
      repeat :steps [
        ;travel between 30 and 100
        ;turtle steps
        ;setpenshade -15 + repcount / 5
        setpenshade -15 + 30 * (repcount / :steps)
        ;set the pen shade based on the
        ;loop iterations
        fd 1 - 0.002 * repcount
        ;move forward minus "drag"
        sety ypos - 0.01 * repcount
        ;apply fake gravity
      ;merge the hatchling's track
      ;(output) into the track of its
      ;permanent ancestor, in this case
    ;done with hatchling
  ;repeat until finished

turtleArt Thumbtack String Corkboard

This commented Logo source code creates a thumbtack, a cork board, and then draws random string art using them.

Read the ;comments to learn more about what the primitives do and what their shortcuts are.

Try some of the primitives out in turtleSpaces interactive mode (the myrtle prompt) and see what they do!

You can drag-select the source code and then paste it into the turtleSpaces editor (which you enter by typing ed and Enter or pressing control-shift-E) using control-shift-V (paste)

Then exit back to interactive mode using control-shift-O (save) and then type stringart and Enter to execute it.

Change elements of the code and see what happens!

TO tack
  ;create a thumbtack, or pushpin
  setfillcolor pick without 5 without 10 range [1 15]
  ;pick a number between 1 and 15 except 5 and 10
  cylinder 4 2 20
  ;cylinder takes width depth sides
  lower 2
  ;lowers the turtle eg moves beneath it
  cutcone 2 3 7 20
  ;cutcone takes topwidth bottomwidth depth sides
  lo 7
  ;lo is shortcut for lower
  cylinder 4 2 20
  lo 2
  setfc pick [5 10]
  ;setfc is shortcut for setfillcolor, the color
  ;used for painting shapes
  cylinder 1 5 8
  lo 5
  cone 1 1 8
  raise 16
  ;raises the turtle, eg moves above it
  ;all done!

TO corkboard
  ;create a corkboard to push our pins into
  setpos [-205 -116]
  setfillcolor 8 setfillshade -4
  ;setfillshade takes a range of -15 to 15
  forward 5 lo 3 slideright 5
  voxeloid 400 222 4
  ;voxeloid takes width height depth
  ;this creates the surface of our corkboard
  slideleft 5 ra 3 back 5
  setfs 6
  ; setfs is shortcut for setfillshade
  voxeloid 10 232 10
  ;this and subsequent voxeloids
  ;create the frame
  right 90
  sl 10
  ;sl is shortcut for slideleft
  voxeloid 10 410 10
  fd 400
  ;fd is shortcut for forward
  left 90
  bk 10
  ;bk is shortcut for back
  voxeloid 10 232 10
  fd 222 lt 90 bk 10
  ;lt is shortcut for left
  voxeloid 10 410 10
  ;that's all folks!

TO stringart
  ;resets the workspace
  snappy:run pick [
    [pullout 10]
    [pullout 30 orbitdown 70]
    [orbitleft 20 orbitdown 45 rollright 10 pullout 60 rr 10 sl 25 lo 40]
    ;rr is shortcut for rollright
    [orbitright 20 orbitdown 45 rollleft 10 pullout 60 rl 10 sr 25 lo 40]
    ;rl is shortcut for rollleft
  ;pick a camera sequence and execute it as
  ;snappy, the camera turtle
  ;if we need snappy to do more sophisticated
  ;things, we can store procedures inside him
  ;logo is all about having the freedom to do
  ;things in multiple ways!
  setpenwidth 1 + random 5
  ;sets the 'width' of the pen, from 1 to 5
  ;randps and randfs (aka randompenshade and randomfillshade)
  ;set a random shade between -12 and 12
  ;execute corkboard procedure
  repeat 20 + random 20  [
    ;do the following 20 + 0-19 times:
    ;shortcut for randompencolor
    setpos {-190 + random 380 -100 + random 200}
    ;move to a random position
    ;pu is shortcut for penup
    ;save the turtle state on the 'stack'
    ;you can have multiple states on the stack
    raise 10 + random 4 up -10 + random 20 rr -10 + random 20
    ;move into a semi-random position
    ;to give our tacks a more natural-looking
    ;moving in negative values moves the opposite
    ;direction, eg left -90 turns right 90 degrees
    ;execute tack procedure
    ;(create a tack)
    ;load the turtle state from the 'stack'
    ;this puts it back where and how it was when
    ;we pushed it
    ;pd is shortcut for pendown
    ;this will cause us to create a line to the
    ;next random position
  ;repeat the above however many times
  ;specified by 20 + random 20
  ;ta da!
  ;for extra credit, get some tacks, a corkboard, and some
  ;colored string and make some string art of your own!
  ;consider the angles the turtle would need to turn to travel
  ;along the line of string created between all the pins
  ;were the turtle to travel the string like driving
  ;down a road


Solar System Simulation

This Solar System simulation features the ability to add orbiting moons to the planets, a few of which are already defined. It is not entirely to scale (the planets are larger than they are in reality).

Use the scrollwheel or finger-scroll to zoom in and out, and drag the mouse to rotate around the sun!

TO solarsystem
  cam:pullin 100
  ;pull in the camera turtle
  ;make a starfield in the distance:
  setfillcolor 5
  repeat 200 [
    home randomvectors
    forward 2500 + random 100
    up 90
    spot 1 + random 5
  ;define planetary parameter lists:
  make "distance [0 39 72 100 152 520 953 1918 3006 3953]
  ;the distance of the planets from the sun in 100ths of an AU
  ;The first value is the sun itself, which is at the home position
  make "size [100 3 7.5 7.9 4.2 88.7 74.6 32.6 30.2 1.41]
  ;the planets are in scale relative to each other but not the sun,
  ;which is much larger than the value we have given it here
  make "color [13 8 9 7 1 14 11 7 2 10]
  ;each planet's color (and the sun)
  make "tilt [0 7 3.3 0 1.85 1.31 2.49 0.77 1.77 17.14]
  ;ecliptical tilt
  make "speed [0 4.1 1.62 1 0.53 0.084 0.034 0.011 0.006 0.004]
  ;speed of orbit
  ;define moons:
  make "moon [0 0 0 1 2 0 0 0 0 0]
  ;how many moons?
  make "mooncolor [[][][][5][8 9][][][][][]]
  make "moondistance [[][][][3][2 3][][][][][]]
  make "moonsize [[][][][2.1][1.12 0.62][][][][][]]
  make "moontilt [[][][][0][1 2][][][][][]]
  make "moonspeed [[][][][30][40 30][][][][][]]
  ;moon parameters, similar to planets
  ;only earth and mars are populated here,
  ;add the others as you like!
  ;create the sun and planets:
  repeat 10 [
    make "planet repcount
    ;store the current planet for use inside hatch
    newmodel repcount {"setfc item :planet :color "ico 0.1 * item :planet :size}
    ;create a new turtle model using the data from the :color and :size lists
    ;we use a 'soft list' {} to create 'hard data' for use by newmodel
    ;as the turtle model is rendered each frame
    hatch [
      ;create a new hatchling
      setmodel :planet
      ;set the turtle model
      ;set the orbit (anchor) point to the current position
      pullout 0.5 * item :planet :distance
      ;pull away from the anchor the distance specified in the :distance list
      orbitright random 360
      ;orbit around a random amount
      orbitup item :planet :tilt
      ;orbit up (tilt) the amount specified in the :tilt list
      ;hatchlings are not visible by default
      if 0 < item :planet :moon [ ;are there any moons? foreach "moon item :planet :mooncolor [ ;for each moon, let's create it the same way we did planets: make "moonnumber loopcount make "moonmodel word :planet loopcount newmodel :moonmodel {"setfc :moon "ico 0.1 * item :moonnumber item :planet :moonsize} make "parent turtle ;define the 'parent' turtle for use by the moon hatchling hatch [ ;hatch the moon setmodel :moonmodel dropanchor right random 360 pullout item :moonnumber item :planet :moondistance orbitup item :moonnumber item :planet :moontilt showturtle forever [ fixate query :parent [position] ;keep 'fixated' (look at and set the anchor point to) ;the parent turtle's position. if orbitdistance > item :moonnumber item :planet :moondistance [
                pullin orbitdistance - (item :moonnumber item :planet :moondistance)
              ;if it's getting away from us, try and catch up!
              orbitright 0.1 * item :moonnumber item :planet :moonspeed
              ;orbit the planet based on the :moonspeed
              sleep 6.25
              ;take a little nap
      forever [
        orbitright 0.05 * item :planet :speed
        sleep 25
      ;orbit the sun (we're back to the planet now) based on the value
      ;from the :speed list. Then take a little nap (wait 1)
  ;hide Myrtle, although she would be sitting in the sun

One-a-Day: Space Tube Ride using TUBE and TUBEARC

Myrtle creates a 3D space tube ride for her to fly through…

Sometimes Myrtle needs to take a break and have a little fun! One of the things she can do is make a space tube and fly through it, using the TUBE and TUBEARC primitives:

TUBE makes a straight tube, and takes the parameters <radius> <depth> and <sides>. So, tube 20 10 10 makes a tube with a radius of 20 turtle units, a depth of 10 turtle units and 10 sides.

TUBEARC creates a curved tube, and takes the parameters <thickness> (the radius of the tube itself) <radius> (the radius of the arc itself) <sides> <totalsegments> and <arcsegments> – the last two are the total segments that would make up a complete torus, or donut, and the number of segments we actually want to create. So values of 20 and 10 will create a half-donut: tubearc 10 20 20 20 10

There are four procedures to our space tube program: createcourse, drawcourse, followcourse and spacetube.

createcourse generates the data that represents the tube’s course. It creates a course made up of 100 segments, represented by a word made up of a series of numbers between 0 and 4, where 0 represents a straight section of tube, and 1 to 4 represent four directions of turn. We use dountil to ensure we don’t repeat the same direction of turn more than once and end up looping back on ourself. Although, createcourse is not perfect and it is still possible for the course to cross over itself – but it’s a good thing tube walls aren’t solid!

drawcourse creates the graphical representation of the contents of the :course container we generated using createcourse. We use the twosided primitive to generate reflective “normals” on both sides of the shapes we generate from that point forward, and we use randfc to set a random ‘fill color’ or shape color for each segment as we create them.

We use foreach to step through each segment listed in the :course container, creating either a tube or a tubearc where appropriate.

While tubes are created directly under Myrtle, tubearcs are created around her, and so this means we need to do a bit of calisthenics to position the tubearcs where they need to go. Follow them through one command at a time to see how they work! We wait 2 / 60ths of a second between each segment creation so we can follow it.

followcourse causes Myrtle to fly through the created course, once again iterating through the :course container using foreach. fluid causes Myrtle to move forward smoothly, and to turn through the arcs we use a repeat. sleep is another form of wait, which takes milliseconds as a parameter instead of wait‘s 60ths of a second.

setpremodel allows us to ‘prepend’ commands to the turtle’s model, allowing us to make Myrtle look like she’s turning the appropriate way as she moves through the course.

Finally, spacetube puts it all together and is the procedure we execute to create the maze and fly through it. spacetube performs a reset, turns off the text layer, tells Snappy (the camera turtle) to pull away from Myrtle 1000 turtle units, tells Snappy to ‘follow’ Myrtle (turn to face her when she disappears from his view), then executes the createcourse procedure, the drawcourse procedure, sets the view (camera) turtle to Myrtle, turns Myrtle’s ‘light’ on (so we can see properly inside the tubes), turns Snappy’s light off, sets the camera ‘view point’ of Myrtle a bit up and behind her, and then executes followcourse.

TO spacetube
  snappy:pullout 1000
  snappy:follow "myrtle
  setview "myrtle
  setlight 1
  snappy:setlight 0
  setviewpoint [0 10 -30]

TO createcourse
  make "course empty
  make "last 5
  repeat 100 [
    dountil :last != :segment [make "segment random 5]
    make "course word :course :segment
    if :segment != 0 [make "last :segment]

TO drawcourse
  pu twosided
  foreach "segment :course [
    if :segment = 0 [tube 50 200 20 lo 200]
    else [rt :segment * 90
      dn 90 rr 90 sl 100 tubearc 50 100 20 20 5 fd 100 rr 90 lt 180 + :segment * 90]
    wait 2

TO followcourse
  dn 90
  foreach "segment :course [
    if :segment = 0 [fd 200]
    if :segment = 1 [setpremodel [rt 22.5] repeat 90 [fd 1.75 rt 1 sleep 1] setpremodel []]
    if :segment = 2 [setpremodel [dn 22.5] repeat 90 [fd 1.75 dn 1 sleep 1] setpremodel []]
    if :segment = 3 [setpremodel [lt 22.5] repeat 90 [fd 1.75 lt 1 sleep 1] setpremodel []]
    if :segment = 4 [setpremodel [up 22.5] repeat 90 [fd 1.75 up 1 sleep 1] setpremodel []]

Release Notes: New SKEW* and TRAPE* shape primitives + SAVEPNG high-res export

We’ve added a number of new 3D shape primitives in the latest release:


These allow you to “skew” (or slant) the created shape and / or compress or expand one “end” of it (trape, or trapezoidal). This allows for a large increase in the number of possible shapes you can create in turtleSpaces.

Also, you can export an arbitrarily-sized render of the current scene using the new SAVEPNG primitive:

SAVEPNG [width height] “filename.png

Note that if you specify a really large size (> 10000 pixels per side) you can cause the application and even your operating system to crash! This is because the rasterisation needs to be done in memory.

The image is saved in the current “working directory”, usually a turtleSpace TSP folder inside of your user folder (inside of the turtleSpaces folder in your home directory).

We’ve also created a lot of short-hand primitives for shapes. You can find them listed in the shapes and graphics reference.

One-a-Day: Amiga Ball Bounce

The Commodore Amiga computer had a famous ‘bouncing ball’ demonstration program, a checkered bouncing ball. It was a bit different than this, but this is certainly reminiscent of it.

We love the Amiga demo so much that we created a special checkered ball primitive, AMIGABALL, and a second ‘oid’ primitive, AMIGABALLOID, which is used to create the ‘compressed’ ball.

Rather than turning the turtle into a ball (one method), this method ‘cleans’ the ‘turtle track’ after rendering each frame of the animation (which we wait for using the NEXTFRAME primitive).

The background voxel is actually an ‘inverted’ voxel, a voxel that is created using a negative size value. Due to the nature of OpenGL, only the insides of negative voxels are visible, which is why we can see inside it, and not see the face directly in front of us. Because we clean the ball each frame, we need to use a HATCHLING to create and hold the voxel in place. The hatchling just sleeps while the program runs.

The CAM: prefix directs the current view turtle (usually ‘Snappy’) to do things. You could also use SNAPPY: in this case but CAM: is shorter.

DOUNTIL PENCOLOR != FILLCOLOR [RANDFC] ensures that the ball has two different colors. The Amigaball(oid) uses both the pen and the fill colors in its construction, the only 3D primitive to do so.

To stop the ball from bouncing, press the Escape key.

TO bounce
  reset fs
  penup lower 120 slideright 120 fd 120
  hatch [randomfillcolor voxel -240 forever [wait 10]]
  ;create the cube, using a hatchling so it persists
  cam:run [oup 10 ra 5]
  setspheroidaxis 1
  ;stretch the spheroid on the vertical, default is horizontal
  dn 90 rr 10
  randpc dountil pencolor != fillcolor [randfc]
  ;set random pen and fill colors
  forever [
    repeat 14 [
      amigaball 50 10 20
      setx xpos - 1 lo 4 lt 2
      nextframe clean
    ;move down
    repeat 11 [
      amigaballoid 50 10 20 1 - repcount / 20
      lo 2 lt 2 nextframe clean
    ;compress ball
    randpc dountil pencolor != fillcolor [randfc]
    ;change colors
    repeat 11 [
      amigaballoid 50 10 20 0.375 + repcount / 20
      ra 2 lt 2 nextframe clean
    ;expand ball
    repeat 28 [
      amigaball 50 10 20
      setx xpos + 1 ra 4 lt 2
      nextframe clean
    ;move up
    repeat 11 [
      amigaballoid 50 10 20 1 - repcount / 20
      ra 2 lt 2 nextframe clean
    ;compress ball
    randpc dountil pencolor != fillcolor [randfc]
    ;change colors
    repeat 11 [
      amigaballoid 50 10 20 0.375 + repcount / 20
      lo 2 lt 2 nextframe clean
    ;expand ball
    repeat 14 [
      amigaball 50 10 20 setx xpos - 1
      lo 4 lt 2 nextframe clean
    ;move back to center



One-a-Day: FRAG

The FRAG primitive creates a filled shape out of the current turtle position and her last two positions. For example:

FD 100 RT 90 FD 100 FRAG

will create a triangle.

While turtleSpaces has a variety of shape primitives, sometimes you need to create an arbitrary shape, and FRAG aids you in this.

Take this example, which draws a star:

TO star
  repeat 4 [
    forward 100
    right 170
    forward 86
    left 70
    forward 86
    right 170
    forward 100
    right 180

We can change the number of sides the star has by changing the number of repeats and fiddling with the values a bit:

TO star2
  repeat 5 [
    fd 100 rt 170
    fd 86 frag
    lt 88 fd 86
    rt 170 fd 100
    frag rt 180

First, let’s change our star procedures so they can take a :size parameter, like so:

TO star1 :size
  repeat 4 [
    fd 100 * :size
    rt 170
    fd 86 * :size
    lt 70
    fd 86 * :size
    rt 170
    fd 100 * :size
    rt 180

In this case, :size is a ratio, that is, 0.5 will make a star half the size, and 2 will make a star twice the size of the default.

You can change the color of the star using the SETFILLCOLOR primitive, or set a random fill color with RANDFC.

The following procedures create a sky full of stars:

TO star1 :size
  repeat 4 [
    fd 100 * :size
    rt 170
    fd 86 * :size
    lt 70
    fd 86 * :size
    rt 170
    fd 100 * :size
    rt 180

TO star2 :size
  repeat 5 [fd 100 * :size rt 170 fd 86 * :size frag lt 88 fd 86 * :size rt 170 fd 100 * :size frag rt 180]

TO star3 :size
  repeat 6 [fd 100 * :size rt 170 fd 86 * :size frag lt 100 fd 86 * :size rt 170 fd 100 * :size frag rt 180]

TO star4 :size
  repeat 7 [fd 100 * :size rt 170 fd 86 * :size frag lt 108.625 fd 86 * :size rt 170 fd 100 * :size frag rt 180]

TO star5 :size
  repeat 8 [fd 100 * :size rt 170 fd 86 * :size frag lt 115 fd 86 * :size rt 170 fd 100 * :size frag rt 180]

TO stars
  reset cam:setposition [0 0 0]
  cam:fixate [0 0 0]
  cam:setviewpoint [0 0 0]
  cam:newworker [forever [up 0.1 lt 0.1 rr 0.1 wait 1]]
  repeat 200 [
    pu home randori fd 400 + random 1000 up 90
    lt random 60 pd randpc randfc randfs randps
    make "size (10 + random 90) / 100
    run {pick [star1 star2 star3 star4 star5] :size}

Type STARS and press Enter to see the stars!

FRAG’s sister, SHARD creates a three-dimensional FRAG with depth beneath it. This depth is supplied as a parameter, in turtle-units, eg. SHARD 5. Try replacing FRAG with SHARD 5 in one of your star procedures and see what happens! (You’ll need to drag the camera around to see the sides of the star)