turtle

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 6, 2021 License: MIT Imports: 7 Imported by: 0

README

go-turtle

Turtle graphics in Go.

A couple of small showcase scripts are in the samples folder.

Moving around:

sample world

A conveniently 4K shaped image:

hilbert curve times 19

Turtle

A minimal Turtle agent, moving on a cartesian plane.

The orientation is in degrees. Right rotates clockwise, Left counter-clockwise.

Use it to simulate the movements of the turtle without the drawing overhead.

// create a new turtle
t := turtle.New()

// move it just like you expect
t.Forward(5)
t.Left(45)
t.Forward(5)
t.Right(45)
t.Backward(5)

// get the X, Y, Deg data as needed
fmt.Println(t.X, t.Y, t.Deg)
// 3.5355339059327378 3.5355339059327373 0

// teleport around
t.SetPos(4, 4)
t.SetHeading(120)

// vaguely nice printing
fmt.Println("T:", t)
// T: (   4.0000,    4.0000) ^  120.0000

TurtleDraw

Has the same interface of Turtle, but draws. Each TurtleDraw is attached to a World.

Create a new world to draw in:

w := turtle.NewWorld(900, 600)

When creating a World with NewWorld, an uniform image of the requested size (width, height) with SoftBlack background is generated.

An existing image can be used as base:

img := image.NewRGBA(image.Rect(0, 0, 900, 600))
draw.Draw(img, img.Bounds(), &image.Uniform{turtle.Cyan}, image.Point{0, 0}, draw.Src)
wi := turtle.NewWorldImage(img)

Create a TurtleDraw attached to the World:

// create a turtle attached to w
td := turtle.NewTurtleDraw(w)

// position/orientation
td.SetPos(100, 300)
td.SetHeading(turtle.North + 80)

// line style
td.SetColor(turtle.Blue)
td.SetSize(4)

// start drawing
td.PenDown()

// same interface as Turtle
td.Forward(100)
td.Left(160)
td.Forward(100)

Save the current image:

err := w.SaveImage("world.png")
if err != nil {
    fmt.Println("Could not save the image: ", err)
}

Close the world (there are two open internal channels).

w.Close()

// this is an error: the turtle tries to send the line
// to the world input channel that has been closed
// td.Forward(50)

You can create as many turtles as you want. When drawing, a turtle sends the line to the world on a channel and blocks until it is done.

Constants

A few standard colors:

Black     = color.RGBA{0, 0, 0, 255}
SoftBlack = color.RGBA{10, 10, 10, 255}
White     = color.RGBA{255, 255, 255, 255}

Red   = color.RGBA{255, 0, 0, 255}
Green = color.RGBA{0, 255, 0, 255}
Blue  = color.RGBA{0, 0, 255, 255}

Cyan    = color.RGBA{0, 255, 255, 255}
Magenta = color.RGBA{255, 0, 255, 255}
Yellow  = color.RGBA{255, 255, 0, 255}

DarkOrange = color.RGBA{150, 75, 0, 255} // It's just so warm and relaxing

Cardinal directions:

East  = 0.0
North = 90.0
West  = 180.0
South = 270.0

Implementation notes

Note on float64

A lot of inputs to the API are actually float64, so when using a variable instead of an untyped const the compiler will complain if the var is int.

So this works as the var has type float:

segLen := 150.0
td.Forward(segLen)

and this does not:

segLen := 150
td.Forward(segLen)
// cannot use segLen (variable of type int) as float64 value
// in argument to td.Forward (compile)

This works magically because in Go constants are neat.

td.Forward(150)
Drawing pixels

When drawing points of odd size, the square is centered on the position. When drawing points of even size, the square is shifted to the top and right. The red points are drawn with y=0, along the bottom border of the image.

drawing pixels of even size

To draw a single point, just call forward with 0 dist:

td.Forward(0)
Channels and line drawing

The world draws the Line it receives on the DrawLineCh channel, so you can technically draw a line directly with that skipping the turtles altogether, and everything should work.

TODO - Ideas

  • Hilbert sample!
  • More colors!

Contributing

This was a side project to another one I was doing to learn Go, so all improvements and suggestions for a better code are welcome.

Documentation

Index

Constants

View Source
const (
	East  = 0.0
	North = 90.0
	West  = 180.0
	South = 270.0
)

Standard directions.

Variables

View Source
var (
	Black     = color.RGBA{0, 0, 0, 255}
	SoftBlack = color.RGBA{10, 10, 10, 255}
	White     = color.RGBA{255, 255, 255, 255}

	Red   = color.RGBA{255, 0, 0, 255}
	Green = color.RGBA{0, 255, 0, 255}
	Blue  = color.RGBA{0, 0, 255, 255}

	Cyan    = color.RGBA{0, 255, 255, 255}
	Magenta = color.RGBA{255, 0, 255, 255}
	Yellow  = color.RGBA{255, 255, 0, 255}

	// I just love this one
	DarkOrange = color.RGBA{150, 75, 0, 255}
)

Standard colors.

Functions

func Deg2rad

func Deg2rad(deg float64) float64

Convert degrees to radians.

func Rad2deg

func Rad2deg(rad float64) float64

Convert radians to degrees.

Types

type Line

type Line struct {
	X0, Y0 float64
	X1, Y1 float64
	// contains filtered or unexported fields
}

A simple Line with a Pen to send around channels.

type Pen

type Pen struct {
	Color color.Color // Line color.
	Size  int         // Line width.
	On    bool        // State of the Pen.
}

A simple Pen.

func NewPen

func NewPen() *Pen

Create a new Pen.

func (*Pen) PenDown

func (p *Pen) PenDown()

Start writing.

func (*Pen) PenUp

func (p *Pen) PenUp()

Stop writing.

func (*Pen) SetColor

func (p *Pen) SetColor(c color.Color)

Change the Pen color.

func (*Pen) SetSize

func (p *Pen) SetSize(s int)

Change the Pen size.

func (*Pen) String

func (p *Pen) String() string

Write the Pen state.

type Turtle

type Turtle struct {
	X, Y float64 // Position.
	Deg  float64 // Orientation in degrees.
}

A minimal Turtle agent, moving on a cartesian plane.

https://en.wikipedia.org/wiki/Turtle_graphics

func New

func New() *Turtle

Create a new Turtle.

func (*Turtle) Backward

func (t *Turtle) Backward(dist float64)

Move the Turtle backward by dist.

func (*Turtle) Forward

func (t *Turtle) Forward(dist float64)

Move the Turtle forward by dist.

func (*Turtle) Left

func (t *Turtle) Left(deg float64)

Rotate the Turtle counter clockwise by deg degrees.

func (*Turtle) Right

func (t *Turtle) Right(deg float64)

Rotate the Turtle clockwise by deg degrees.

func (*Turtle) SetHeading

func (t *Turtle) SetHeading(deg float64)

Orient the Turtle towards deg.

func (*Turtle) SetPos

func (t *Turtle) SetPos(x, y float64)

Teleport the Turtle to (x, y).

func (*Turtle) String

func (t *Turtle) String() string

Write the Turtle state.

type TurtleDraw

type TurtleDraw struct {
	Turtle // Turtle agent to move around.
	Pen    // Pen used when drawing.

	W *World // World to draw on.
}

A drawing Turtle.

func NewTurtleDraw

func NewTurtleDraw(w *World) *TurtleDraw

Create a new TurtleDraw, attached to the World w.

func (*TurtleDraw) Backward

func (td *TurtleDraw) Backward(dist float64)

Move the turtle backward and draw the line if the Pen is On.

func (*TurtleDraw) Forward

func (td *TurtleDraw) Forward(dist float64)

Move the turtle forward and draw the line if the Pen is On.

func (*TurtleDraw) SetPos

func (td *TurtleDraw) SetPos(x, y float64)

Teleport the Turtle to (x, y) and draw the line if the Pen is On.

func (*TurtleDraw) String

func (td *TurtleDraw) String() string

Write the TurtleDraw state.

type World

type World struct {
	Image         *image.RGBA
	Width, Height int

	DrawLineCh chan Line
	// contains filtered or unexported fields
}

A world to draw on.

func NewWorld

func NewWorld(width, height int) *World

Create a new empty World.

func NewWorldImage

func NewWorldImage(img *image.RGBA) *World

Create a new World attached to the Image img, and start listening on w.DrawLineCh for lines to draw.

func (*World) Close

func (w *World) Close()

Close the world channels, and stop the listen goroutine.

func (*World) SaveImage

func (w *World) SaveImage(filePath string) error

Save output

Directories

Path Synopsis
samples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL