W1511 Walking Turtles

From Coder Merlin
Revision as of 19:56, 13 March 2022 by Onangwatgo-siqiniq (talk | contribs) (→‎Exercises)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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.

Prepare[edit]

Create a new Scenes shell project within your Experiences directory:

ty-cam@codermerlin:~$  cd ~/Experiences

ty-cam@codermerlin:~/Experiences$  git clone https://github.com/TheCoderMerlin/ScenesShellBasic W1511


Enter the Sources/ScenesShell directory of the new project:

ty-cam@codermerlin:~/Experiences$  cd W1511/Sources/ScenesShell/


Start button green arrow
Run the program.

ty-cam@codermerlin:~/Experiences/W1511/Sources/ScenesShell$  run


Ensure that you are logged on to the wiki. Then, click on the Tools menu followed by right-clicking on IGIS and selecting the menu item Open in New Window or Open in New Tab.

You'll know you're 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.)

Hint.pngHelpful Hint
It's useful to bookmark this page in your browser.

Experiment[edit]

Stop button red ex
Stop the running program.

Return to the console and press CONTROL-C

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.

Open the file Background.swift in emacs.

Add a new property to the Background class:

class Background : RenderableEntity {

    var didDraw = false

    init() {
        // Using a meaningful name can be helpful for debugging
        super.init(name:"Background")
    }
}

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

Add a new method (below init) as follows:

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

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            canvas.render(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 creates 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.

Remember to save the file, then suspend emacs.

Start button green arrow
Run the program and view in a browser before continuing.

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 render method and edit so it appears as follows:

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

            let turtle = Turtle(canvasSize:canvasSize)
            turtle.forward(steps:50)
            turtle.left(degrees:135) 
            canvas.render(turtle)

            didDraw = true
        }
    }
Start button green arrow
Run the program and view in a browser before continuing.


ObserveObserveIcon.png
Observe, Ponder, and Journal: : Section 1
  1. What changed?
  2. 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 render method and edit so it appears as follows:

    override func render(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) 
            canvas.render(turtle)

            didDraw = true
        }
    }
Start button green arrow
Run the program and view in a browser before continuing.

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 render method and edit so it appears as follows:

    override func render(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) 
            turtle.forward(steps:50) 
            canvas.render(turtle)

            didDraw = true
        }
    }
Start button green arrow
Run the program and view in a browser before continuing.

The body 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 render method and edit so it appears as follows:

    override func render(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.render(turtle)

            didDraw = true
        }
    }
Start button green arrow
Run the program and view in a browser before continuing.

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 render method and edit so it appears as follows:

    override func render(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()            
            turtle.forward(steps:25)  
            turtle.penDown()          
            turtle.forward(steps:50)  
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            turtle.right(degrees:90)
            turtle.forward(steps:50)
            turtle.penUp()            
            turtle.forward(steps:25)  
            turtle.penDown()          
            turtle.forward(steps:50)  
            canvas.render(turtle)

            didDraw = true
        }
    }
Start button green arrow
Run the program and view in a browser before continuing.

Key Concepts[edit]

Key ConceptsKeyConceptsIcon.png
  • A turtle's coordinate system differs from the standard graphic coordinate system in that:
    • The origin is located at the canvas's center rather than the top-left corner of the canvas
    • A turtle moves along a vector rather than to a point on a Cartesian plane
  • The turtle's initial position is termed home
    • Home is located at the origin
    • Starting from home, the turtle's direction is up (north)
  • The turtle's direction can be changed by rotating the turtle
    • Rotation can be either to the left or to the right
    • A change in direction is always specified relative to the turtle's current rotation
    • The change is specified in degrees (rather than in radians, as is the case with the other graphic systems that we've practiced)
    • Rotating to the right is the same as rotating clockwise
    • Rotating to the left is the same as rotating counter-clockwise
  • The turtle's constructor requires the size of the canvas
    • Because the size of the canvas isn't available during the setup event, we use the render event which is invoked at regular intervals
    • Because the size might not be available the canvasSize property is an optional type:
      • We use the if-let syntax to assign the canvasSize property to a constant only if it is non-nil
  • Because this is a static image, we draw the image only once
    • We define a property, didDraw, and assign it the initial value of false (because we haven't yet drawn)
    • We test this property in our if-let conditional and only continue if the value is false
    • After drawing, we set the property to true
  • The basic strategy when using turtles involves the following operations
    • Moving forward with turtle.forward(steps:s)
    • Moving backward with turtle.backward(steps:s)
    • Rotating right a certain number of degrees with turtle.right(degrees:d)
    • Rotating left a certain number of degrees with turtle.left(degrees:d)
  • A more advanced strategy may involve moving the turtle without drawing
    • Lifting the pen with turtle.penUp(). Subsequent turtle movements will not leave a trail of ink.
    • Dropping the pen with turtle.penDown(). Subsequent turtle movements will leave a trail of ink.

Exercises[edit]

ExercisesExercisesIcon.png
  •  J1511  Create a journal and answer all questions. Be sure to include all sections of the journal, properly formatted.
  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.
  5. Draw a "circle"
  •  M1511-28  Complete  Merlin Mission Manager  Mission M1511-28.