turtle

package module
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Feb 9, 2024 License: Apache-2.0 Imports: 11 Imported by: 1

README

Turtle

Go Reference Go CI Go Report Card Coverage Badge

A Turtle Graphics System for Golang

Based on the python turtle, this Go package provides an environment to learn Go programming while getting instant feedback. The screen is updated in real time using the Ebitengine.

Using Turtle is super easy and beginner-friendly. This is a good tool to use for an introduction to programming.

There is very little boilerplate needed to do simple things. Below is an example to draw a triangle.

func drawTriangle(window turtle.Window) {
	t := window.NewTurtle()
	t.ShowTurtle()
	t.PenDown()

	t.Forward(100)
	t.Left(120)
	t.Forward(100)
	t.Left(120)
	t.Forward(100)
}
Angle Modes

Three angle modes are supported:

  • DegreesMode: (default). 0 is in the x direction, positive counterclockwise
  • RadiansMode: 0 is in the x direction, positive counterclockwise
  • CompassMode: 0 is North, or up, and positive clockwise
    • Can be used for solving orienteering problems
Turtle Sprite

The turtle sprite can be hidden(default) or show. Its shape can be changed to an arrow or to a user provided image.Image. The scale of the sprite can also be adjusted.

Install

Go 1.21 or later is required.
Ebitengine is the main dependency. Check here for the system specific instructions.

Examples

5 Turtles At Once
go run github.com/GaryBrownEEngr/turtle/examples/fiveturtles@latest

Golang Turtle drawing with 5 individually controlled turtles

Go Gopher

Converted from the python script seen in this youtube video.

go run github.com/GaryBrownEEngr/turtle/examples/gogopher@latest

Golang Turtle drawing the go gopher

Recursive Tree

Golang Turtle drawing a recursive tree

Basic Example Program

go run github.com/GaryBrownEEngr/turtle/examples/spiralweb@latest
package main

import (
	"image/color"

	"github.com/GaryBrownEEngr/turtle"
)

func main() {
	params := turtle.Params{Width: 500, Height: 500}
	turtle.Start(params, drawFunc)
}

// drawFunc is started as a goroutine.
func drawFunc(window turtle.Window) {
	window.GetCanvas().ClearScreen(turtle.Black)
	t := window.NewTurtle()
	t.ShowTurtle()
	t.Speed(1000)
	t.PenDown()

	colors := []color.Color{turtle.Red, turtle.Yellow, turtle.Green, turtle.Purple, turtle.Blue, turtle.Orange}
	for x := 1; x < 200; x++ {
		t.Color(colors[x%6])        // setting color
		t.Size(float64(x)/75.0 + 1) // setting width
		t.Forward(float64(x))       // moving forward
		t.Left(59)                  // Turn left
	}
}

Golang Turtle drawing spiral web

Turtle Controls

When a new turtle is created, it is given a Canvas interface. The turtle itself fulfills the Turtle interface seen below. Which means each turtle created can perform this exact list of actions.

type Turtle interface {
	Forward(distance float64)
	F(distance float64) // Forward alias
	Backward(distance float64)
	B(distance float64) // Backward alias
	PanRightward(distance float64)
	PanR(distance float64) // PanRightward alias
	PanLeftward(distance float64)
	PanL(distance float64) // PanLeftward alias

	GoTo(x, y float64)      // Cartesian (x,y). Center in the middle of the window
	GetPos() (x, y float64) // Cartesian (x,y). Center in the middle of the window

	Left(angle float64)
	L(angle float64) // Turn Left alias
	Right(angle float64)
	R(angle float64) // Turn Right alias
	Angle(angle float64)
	GetAngle() float64
	PointToward(x, y float64)

	DegreesMode() // Default is degrees mode.
	RadiansMode()
	CompassMode() // Make it so North is 0 degrees, East is 90...
	GetAngleMode() AngleMode

	Speed(PixelsPerSecond float64)
	GetSpeed() float64

	PenUp()
	PU()  // Pen Up alias
	Off() // Pen Up alias
	PenDown()
	PD() // Pen Down alias
	On() // Pen Down alias
	IsPenDown() bool
	Color(c color.Color)
	GetColor() color.Color
	Size(size float64)
	GetSize() float64
	Dot(size float64)
	Fill(c color.Color)

	// Draw a circle with given radius. The center is radius units left of the turtle; angleAmountToDraw determines
	// which part of the circle is drawn. If angleAmountToDraw is not a full circle, one endpoint of the arc is
	// the current pen position. Draw the arc in counterclockwise direction if radius is positive,
	// otherwise in clockwise direction. Finally the direction of the turtle is changed by the amount of angleAmountToDraw.
	//
	// As the circle is approximated by an inscribed regular polygon, steps determines the number of steps to use.
	// May be used to draw regular polygons.
	Circle(radius, angleAmountToDraw float64, steps int)

	ShowTurtle()
	HideTurtle()    // Default
	ShapeAsTurtle() // Default
	ShapeAsArrow()
	ShapeAsImage(in image.Image)
	ShapeScale(scale float64) // Default = 0.35

	Clone() Turtle // Create a clone of the turtle
}

Canvas

The pen that implements the Turtle interface is able to implement all of required methods using the just the Canvas interface.

type Canvas interface {
	CreateNewSprite() Sprite
	SetCartesianPixel(x, y int, c color.Color) // Cartesian (x,y). Center in the middle of the window
	SetPixel(x, y int, c color.Color)          // Computer graphics (x,y). So x=0, y=0 is the top-left of the window, positive down-right.
	Fill(x, y int, c color.Color)              // Cartesian (x,y). Center in the middle of the window
	ClearScreen(c color.Color)
	GetScreenshot() image.Image

	GetWidth() int
	GetHeight() int

	PressedUserInput() *UserInput
	SubscribeToJustPressedUserInput() chan *UserInput
	UnSubscribeToJustPressedUserInput(in chan *UserInput)

	Exit()
}

A user can also create their own Pen if desired. Or they can interact with the canvas directly. This can be seen in the randomblue example.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Black to white
	Black     color.RGBA = color.RGBA{0x00, 0x00, 0x00, 0xFF} // #000000
	DarkGray  color.RGBA = color.RGBA{0x26, 0x26, 0x26, 0xFF} // #262626
	Gray      color.RGBA = color.RGBA{0x80, 0x80, 0x80, 0xFF} // #808080
	LightGray color.RGBA = color.RGBA{0xD3, 0xD3, 0xD3, 0xFF} // #D3D3D3
	White     color.RGBA = color.RGBA{0xFF, 0xFF, 0xFF, 0xFF} // #FFFFFF

	// Primary Colors
	Red  color.RGBA = color.RGBA{0xFF, 0x00, 0x00, 0xFF} // #FF0000
	Lime color.RGBA = color.RGBA{0x00, 0xFF, 0x00, 0xFF} // #00FF00
	Blue color.RGBA = color.RGBA{0x00, 0x00, 0xFF, 0xFF} // #0000FF

	// half strength primary colors
	Maroon   color.RGBA = color.RGBA{0x80, 0x00, 0x00, 0xFF} // #800000
	Green    color.RGBA = color.RGBA{0x00, 0x80, 0x00, 0xFF} // #008000
	NavyBlue color.RGBA = color.RGBA{0x00, 0x00, 0x80, 0xFF} // #000080

	// full strength primary mixes
	Yellow  color.RGBA = color.RGBA{0xFF, 0xFF, 0x00, 0xFF} // #FFFF00
	Aqua    color.RGBA = color.RGBA{0x00, 0xFF, 0xFF, 0xFF} // #00FFFF
	Cyan               = Aqua                               // #00FFFF
	Magenta color.RGBA = color.RGBA{0xFF, 0x00, 0xFF, 0xFF} // #FF00FF
	Fuchsia            = Magenta                            // #FF00FF

	// half strength primary mixes
	Olive  color.RGBA = color.RGBA{0x80, 0x80, 0x00, 0xFF} // #808000
	Purple color.RGBA = color.RGBA{0x80, 0x00, 0x80, 0xFF} // #800080
	Teal   color.RGBA = color.RGBA{0x00, 0x80, 0x80, 0xFF} // #008080

	// Other interesting colors
	Orange      color.RGBA = color.RGBA{0xFF, 0xA5, 0x00, 0xFF} // #FFA500
	Indigo      color.RGBA = color.RGBA{0x4B, 0x00, 0x82, 0xFF} // #4B0082
	Violet      color.RGBA = color.RGBA{0xEE, 0x82, 0xEE, 0xFF} // #EE82EE
	Gold        color.RGBA = color.RGBA{0xFF, 0xD7, 0x00, 0xFF} // #FFD700
	SkyBlue     color.RGBA = color.RGBA{0x87, 0xCE, 0xEB, 0xFF} // #87CEEB
	SaddleBrown color.RGBA = color.RGBA{0x8B, 0x45, 0x13, 0xFF} // #8B4513
	Tan         color.RGBA = color.RGBA{0xD2, 0xB4, 0x8C, 0xFF} // #D2B48C
	Crimson     color.RGBA = color.RGBA{0xDC, 0x14, 0x3C, 0xFF} // #DC143C
	Pink        color.RGBA = color.RGBA{0xFF, 0xC0, 0xCB, 0xFF} // #FFC0CB
	Salmon      color.RGBA = color.RGBA{0xFA, 0x80, 0x72, 0xFF} // #FA8072
	Turquoise   color.RGBA = color.RGBA{0x40, 0xE0, 0xD0, 0xFF} // #40E0D0
)

A basic set of colors based on the colors found here: https://www.w3schools.com/colors/colors_names.asp

Functions

func CreateGif added in v0.7.0

func CreateGif(
	window Window,
	delayBetweenScreenshots time.Duration,
	delayBetweenGifFrames time.Duration,
	outputGifFilePath string,
	frameCount int,
)

Start this as a go routine to create a GIF of your creation. The 256 most common colors will be found and used. The length of the captured video will be delayBetweenScreenshots * frameCount The length of the gif will be delayBetweenGifFrames * frameCount

func CreateGifDithered added in v0.8.0

func CreateGifDithered(
	window Window,
	delayBetweenScreenshots time.Duration,
	delayBetweenGifFrames time.Duration,
	outputGifFilePath string,
	frameCount int,
)

Start this as a go routine to create a GIF of your creation. Dithering will be used to achieve more colors, but images artifacts are introduced. This is best for images with lots of shading. The length of the captured video will be delayBetweenScreenshots * frameCount The length of the gif will be delayBetweenGifFrames * frameCount

func CreateGifNearestPlan9 added in v0.9.0

func CreateGifNearestPlan9(
	window Window,
	delayBetweenScreenshots time.Duration,
	delayBetweenGifFrames time.Duration,
	outputGifFilePath string,
	frameCount int,
)

Start this as a go routine to create a GIF of your creation. This uses the nearest color in the Plan9 palette. So it is best for images with blocks of solid colors. The length of the captured video will be delayBetweenScreenshots * frameCount The length of the gif will be delayBetweenGifFrames * frameCount

func GetNewestJustPressedFromChan added in v0.5.0

func GetNewestJustPressedFromChan(justPressedChan chan *turtlemodel.UserInput) *turtlemodel.UserInput

Get the newest keyboard/mouse just pressed event from the given channel. This returns nil if there is no new data. This will throw away all but the newest set of data available. So this should be called faster that the game update rate (60Hz), otherwise sim.PressedUserInput() should be used instead.

func Lerp added in v0.6.0

func Lerp[T constraints.Integer | constraints.Float](a, b T, ratio float64) T

Linearly interpolate between any two numbers of the same type using a ratio. The ratio is capped between 0 and 1

func LerpColor added in v0.6.0

func LerpColor(a, b color.RGBA, ratio float64) color.RGBA

Creates a color between the given a and b. 0 means a is given, 1 means b is given, .5 is a color half way between. The ratio is capped between 0 and 1 Currently the function floors the number instead of rounding to nearest.

func LoadSpriteFile added in v0.6.0

func LoadSpriteFile(path string) (image.Image, error)

Load an image file and covert it to an image.Image. For decode to work on file type, it must be registered by including the codec specific package.

func Start

func Start(params Params, drawFunc func(Window))

Wrap the starting of ebitencanvas inside something that implements the Window interface so that most of the time a user will only need one import statement from this repo to make a turtle graphic. But the actual game, drawing, and sprite implementations can still be separated nicely into packages.

func TakeScreenshot added in v0.7.0

func TakeScreenshot(window Window, outputPNGPath string) error

Take an image of the turtle program window's contents and save it as a PNG.

func TakeScreenshotVideo added in v0.8.0

func TakeScreenshotVideo(
	window Window,
	delayBetweenScreenshots time.Duration,
	frameCount int,
) []image.Image

Take a set of screenshots of the turtle program window's content and return a slice of images. The length of the captured video will be delayBetweenScreenshots * frameCount

Types

type Params

type Params struct {
	Width   int  // pixels
	Height  int  // pixels
	ShowFPS bool // Show frame per second and other info in the top left corner.
}

Turtle Window creation parameters

type Window

type Window interface {
	GetCanvas() turtlemodel.Canvas
	NewTurtle() turtlemodel.Turtle
}

Top level interface that most users of the turtle package will exclusively use.

Jump to

Keyboard shortcuts

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