W1511 Walking Turtles

From Coder Merlin
Within these castle walls be forged Mavens of Computer Science ...
— Merlin, The Coder
Turtle Graphics Spiral

Prerequisites[edit]

Research[edit]

Background[edit]

Igis supports traditional turtle graphics. For turtle graphics, the coordinate system is different from the more standard graphics coordinate system used throughout the rest of Igis. In this coordinate system, the center of the canvas is labeled as the origin (0,0), and is termed home. When the turtle is in the home position, it is oriented up. Rotating to the right rotates the turtle clockwise from north the specified number of degrees, rotating left rotates the turtle counter-clockwise the specified number of degrees. The turtle can also move forwards or backwards a specified number of steps in the direction in which it is currently pointed.

Note: It's OK to mix objects and turtle graphics.

Experiment[edit]

Getting Started[edit]

Breathe-document-new

Begin a new project


Create an Igis shell project within your "project" directory.

cd ~/projects
git clone https://github.com/TangoGolfDigital/IgisShell IgisShell-Turtle

Enter into the Sources directory of the new project.

cd IgisShell-Turtle/Sources/IgisShell/

Build the project. (This may take some time.)

swift build
Start button green arrow

Run the project.

swift run

Open a browser (or use a new tab on an already-open browser). Go to the URL: http://www.codermerlin.com/users/user-name/dyn/index.html

NOTE: You MUST change user-name to your actual user name. For example, http://www.codermerlin.com/users/john-williams/dyn/index.html

You'll know your successful if you see the title bar change to "Coder Merlin: IGIS". (The browser window will be blank because we haven't added any graphics yet.)

First Steps[edit]

Lissemys punctata

Imagine a turtle, perhaps Lissemys punctata. Our turtle has a pen attached to his tail, so as he moves he leaves a trail of ink on the canvas. (Note: No actual turtle has been harmed in this tutorial.) Our turtle is very obedient and he'll always do exactly what we tell him to do. He begins in his home position, facing up (north) at the center of the canvas. He doesn't know anything about coordinate systems and is very limited in his abilities. Nonetheless, we'll soon learn that there's great power in simplicity.

Let's start by telling our turtle to move forward 50 steps. Edit the setup function so it appears as follows:

emacs main.swift

Edit the file by finding the definition of the Painter class. Before the init constructor, add the following property:

    var didDraw = false

This will enable us to keep track of whether or not the turtle completed its drawing mission.

Now, add an update method as follows:

    override func update(canvas:Canvas) {
        if let canvasSize = canvas.canvasSize, !didDraw {

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            canvas.paint(turtle)

            didDraw = true
        }
    }

The conditional that we added will evaluate to true only if the size of the canvas is available and we didn't yet draw with the turtle. If the consequent is executed, the very last statement will set the flag didDraw to true, ensuring that the consequent executes only once.

The guts (pardon the pun) of the method create a new Turtle. We then:

  1. Tell the turtle to move forward 50 steps

Because the turtle is facing up (north) initially, our turtle draws a line from the center of the canvas upwards for fifty steps.

Start button green arrow

Run the project. View the results in the browser as you did earlier.


Hang a Left[edit]

Let's tell our turtle to make a left turn of 135°. (Remember that the turtle measures rotation in degrees, not radians.) Find the update method and edit so it appears as follows:

Now, add an update method as follows:

    override func update(canvas:Canvas) {
        if let canvasSize = canvas.canvasSize, !didDraw {

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            turtle.left(degrees:135) // NEW LINE  
            canvas.paint(turtle)

            didDraw = true
        }
    }
Start button green arrow

Run the project. View the results in the browser as you did earlier. What changed? Did this match your expectations?


We didn't see any difference because the turtle itself isn't visible, only its trail. Because we didn't move after rotating, there's no evidence of the rotation.

Let's move forward 70 steps. Find the update method and edit so it appears as follows:

    override func update(canvas:Canvas) {
        if let canvasSize = canvas.canvasSize, !didDraw {

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            turtle.left(degrees:135)
            turtle.forward(steps:70) // NEW LINE
            canvas.paint(turtle)

            didDraw = true
        }
    }
Start button green arrow

Run the project. View the results in the browser as you did earlier.


The body (pardon the pun) of the method creates a new Turtle. We then:

  1. Tell the turtle to move forward 50 steps
  2. Tell the turtle to turn left 135°
  3. Tell the turtle to move forward 70 steps

It looks like we now have the beginnings of a triangle. Let's complete it by turning again to the left, and then moving forward to our starting point. Find the update method and edit so it appears as follows:

    override func update(canvas:Canvas) {
        if let canvasSize = canvas.canvasSize, !didDraw {

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            turtle.left(degrees:135)
            turtle.forward(steps:70)
            turtle.left(degrees:135) // NEW LINE
            turtle.forward(steps:50) // NEW LINE
            canvas.paint(turtle)

            didDraw = true
        }
    }
Start button green arrow

Run the project. View the results in the browser as you did earlier.


The body (pardon the pun) of the method creates a new Turtle. We then:

  1. Tell the turtle to move forward 50 steps
  2. Tell the turtle to turn left 135°
  3. Tell the turtle to move forward 70 steps
  4. Tell the turtle to turn left 135°
  5. Tell the turtle to move forward 50 steps

Squares are Shapes Too[edit]

Let's draw a square using the turtle. We'll turn to the right this time. Find the update method and edit so it appears as follows:

    override func update(canvas:Canvas) {
        if let canvasSize = canvas.canvasSize, !didDraw {

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            canvas.paint(turtle)
            didDraw = true
        }
    }
Start button green arrow

Run the project. View the results in the browser as you did earlier.


Turtles CAN Lift Their Tails[edit]

Well, they can at least lift their pens. Let's draw a rectangle but leave gaps on the top and bottom. Find the update method and edit so it appears as follows:

    override func update(canvas:Canvas) {
        if let canvasSize = canvas.canvasSize, !didDraw {

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            turtle.penUp()            // NEW LINE
            turtle.forward(steps:25)  // NEW LINE
            turtle.penDown()          // NEW LINE
            turtle.forward(steps:50)  // NEW LINE
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            turtle.penUp()            // NEW LINE
            turtle.forward(steps:25)  // NEW LINE
            turtle.penDown()          // NEW LINE
            turtle.forward(steps:50)  // NEW LINE
            canvas.paint(turtle)

            didDraw = true
        }
    }
Start button green arrow

Run the project. View the results in the browser as you did earlier.



Exercises[edit]

  1. Draw a pentagon
  2. Draw an octagon
  3. Create a function to draw an n-gon (a polygon with n sides) where sides is a parameter to the function specifying the number of sides and length is a parameter to the function specifying the length of each side. Use your function to draw at least three n-gons, each with no fewer than eight sides. All n-gons should appear on the same canvas at the same time.
  4. Create another function that draws a house. The house must have at least two windows and one door. This should be drawn on another location on your canvas and be visible at the same time as the n-gons.