/* 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)
}
}