Category talk:Wren-turtle

From Rosetta Code

Source code

/* Module "turtle.wren" */

import "graphics" for Canvas, Color
import "math" for Math, Point

/* Pen represents a Turtle object's pen */
class Pen {
    // Constructs a new Pen object.
    construct new(down, color, width) {
        if (down.type != Bool) Fiber.abort("Down must be true or false.")
        if (color.type != Color) Fiber.abort("Color must be a Canvas.Color object.")
        if (width.type != Num || !width.isInteger || width < 1) {
            Fiber.abort("Width must be a positive integer.")
        }
        _down  = down   // whether down (activated) or up (not activated)
        _color = color  // drawing color
        _width = width  // line width in pixels
    }

    // Property getters.
    down  { _down  }
    up    { !_down }
    color { _color }
    width { _width }

    // Property setters.
    down=(d)  {
        if (down.type != Bool) Fiber.abort("Argument must be true or false.")
        _down  = d
    }

    color=(c) {
        if (color.type != Color) Fiber.abort("Argument must be a Canvas.Color object.")
        _color = c
    }

    width=(w) {
        if (width.type != Num || !width.isInteger || width < 1) {
            Fiber.abort("Argument must be a positive integer.")
        }
        _width = w
    }
}

/* Turtle represents a turtle graphics drawing object. */
class Turtle {
    // Constructs a new Turtle object.
    construct new(x, y, dir, pen) {
        if (x.type != Num || y.type != Num || dir.type != Num) {
            Fiber.abort("The first three arguments must be numbers.")
        }
        if (pen.type != Pen) Fiber.abort("The fourth argument must be a Pen object.")
        _x = x       // x coordinate
        _y = y       // y coordinate
        _dir = dir   // facing direction in degrees
        _pen = pen   // Pen object
    }

    // Convenience method to construct a Turtle object with default arguments.
    static new() { new(0, 0, 0, Pen.new(true, Color.black, 1)) }

    // Property getters.
    x   { _x   }
    y   { _y   }
    dir { _dir }
    pen { _pen }
    pos { Point.new(_x, _y) }  // returns position as a Point object

    // Property setters.
    x=(x)    { _x = x   }
    y=(y)    { _y = y   }
    dir=(d)  { _dir = d }

    pen=(p)  {
        if (p.type != Pen) Fiber.abort("The argument must be a Pen object.") 
        _pen = p 
    }

    pos=(p)  {                 // sets position from a Point object
        _x = p.x
        _y = p.y
    }

    // Moves the current instance to coordinates x, y.
    goto(x, y) {
        _x = x
        _y = y
    }

    // Moves the current instance to the origin 0, 0.
    home() { goto(0, 0) }

    // Moves forward 'dist' pixels.
    walk(dist) {
        if (dist.type != Num || !dist.isInteger) Fiber.abort("Argument must be an integer.")
        var newX = _x + dist * Math.cos(_dir * Num.pi / 180)
        var newY = _y + dist * Math.sin(_dir * Num.pi / 180)
        if (_pen.down) Canvas.line(_x, _y, newX, newY, _pen.color, _pen.width)
        _x = newX
        _y = newY
    }

    // Moves backward 'dist' pixels.
    back(dist) { walk(-dist) }

    // Turns the current instance 'angle' degrees to the right.
    right(angle) { _dir = _dir + angle }

    // Turns the current instance 'angle' degrees to the left.
    left(angle)  { _dir = _dir - angle }

    // Draws a rectangle with top left vertex at 'x', 'y', width 'w' and height 'h' pixels.
    drawRect(x, y, w, h) {
        goto(x, y)
        _dir = 0
        walk(w)
        right(90)       
        walk(h)
        right(90)
        walk(w)
        right(90)
        walk(h)
    }     
}