pi

package module
v0.26.0 Latest Latest
Warning

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

Go to latest
Published: Oct 21, 2023 License: MIT Imports: 11 Imported by: 2

README

pi

Go Reference codecov

The retro game development engine for Go, inspired by Pico-8 and powered by Ebitengine.

Hello World example Controller example Keyboard example Palette swapping example

FAQ

Is this a new fantasy console?

No, it's not. It's rather a game development library with dev-tools which make it simple (and fun!) to write retro games in Go.

What is a retro game?

It's a game that resembles old 8-bit/16-bit games. This usually means:

  • (extremely) Low resolution (like 128x128 pixels)
  • Limited number of colors (like 16)
  • Very small number of assets (like 256 sprites, map having up to 8K tiles)
  • Small number lines of code (thousands rather than millions)
  • Sound effects and music made using predefined synth instruments and effects
What similarities does Pi have with Pico-8?
  • Most concepts are similar: game loop, drawing sprites and shapes, printing text, clipping, camera, palette swapping, handling user input. Some functions have even same names.
  • Screen resolution is small, and the number of colors is limited. Although in Pi you can change the resolution and palette.
  • You have one small sprite sheet.
Why would I use it?

Because it's the easiest way to write a game in Go. IMHO ;)

Is Pi ready to use?

Pi is under development. Only limited functionality is provided. API is not stable. See ROADMAP for details.

How to get started?

  1. Install dependencies
  2. Try examples from examples directory.
  3. Create a new game using provided Github template.
  4. Read the documentation.
How to edit PNG files like sprite-sheet.png and custom-font.png?
  • Use a pixel-art editor which supports indexed color mode, such as Aseprite or LibreSprite.
  • Palette for the game is stored inside sprite-sheet.png.

Attributions

Documentation

Overview

Package pi provides API to develop retro games.

Like other game development engines, Pi runs your game in a loop:

for {
  pi.Update()
  pi.Draw()
  sleep() // sleep until next frame (30 frames per second)
 }

Both pi.Update and pi.Draw functions are provided by you. By default, they do nothing. You can set them by using:

pi.Draw = func() {
  pi.Print("HELLO WORLD", 40, 60, 7)
}

To run the game please use the ebitengine back-end by calling ebitengine.Run or ebitengine.MustRun.

During development, you might want to use dev-tools which provide tools for screen inspection and REPL terminal, where you can write Go code live when your game is running. To start the game with dev-tools please use:

devtools.MustRun(ebitengine.Run)

Please note that the entire pi package is not concurrency-safe. This means that it is unsafe to run functions and access package variables from go-routines started by your code.

Index

Constants

View Source
const (
	SpriteHeight = 8
	SpriteWidth  = 8
)

Variables

View Source
var (
	// Update is a user provided function executed each frame (30 times per second).
	//
	// The purpose of this function is to handle user input, perform calculations, update
	// game state etc. Typically, this function does not draw on screen.
	Update func()

	// Draw is a user provided function executed at most each frame (up to 30 times per second).
	// π may skip calling this function if previous frame took too long.
	//
	// The purpose of this function is to draw on screen.
	Draw func()
)

Game-loop function callbacks

View Source
var Controllers [8]Controller // 0th element is for Player 0, 1st for Player 1 etc.
View Source
var GameLoopStopped bool
View Source
var Palette [256]image.RGB = defaultPalette

Palette has all colors available in the game. Up to 256. Palette is taken from loaded sprite sheet (which must be a PNG file with indexed color mode). If sprite-sheet.png was not found, then default 16 color palette is used.

Can be freely read and updated when the game is running. Changes will be visible immediately.

View Source
var Time float64

Time returns the amount of time since game was run, as a (fractional) number of seconds

Time is updated each frame.

Functions

func Atan2

func Atan2(dx, dy float64) float64

Atan2 converts DX, DY into an angle from 0..1

Similar to Cos and Sin, angle is taken to run anticlockwise in screenspace. For example:

atan(0,-1)  // returns 0.25

func Btn added in v0.6.0

func Btn(button Button) bool

Btn returns true if a controller button is being pressed at this moment by player 0.

func BtnBits added in v0.6.0

func BtnBits() int

BtnBits returns the state of all controller buttons for players 0 and 1 as bitset.

The first byte contains the button states for player 0 (bits 0 through 5, bits 6 and 7 are unused). The second byte contains the button states for player 1 (bits 8 through 13).

Bit 0 is Left, 1 is Right, bit 5 is the X button.

A bit of 1 means the button is pressed.

func BtnPlayer added in v0.6.0

func BtnPlayer(button Button, player int) bool

BtnPlayer returns true if a controller button is being pressed at this moment by specific player. The player can be 0..7.

func Btnp added in v0.6.0

func Btnp(button Button) bool

Btnp returns true when the controller button has just been pressed. It also returns true after the next 15 frames, and then every 4 frames. This simulates keyboard-like repeating.

func BtnpBits added in v0.6.0

func BtnpBits() int

BtnpBits returns the state of all controller buttons for players 0 and 1 as bitset.

The first byte contains the button states for player 0 (bits 0 through 5, bits 6 and 7 are unused). The second byte contains the button states for player 1 (bits 8 through 13).

Bit 0 is Left, 1 is Right, bit 5 is the X button.

A bit of 1 means the button has just been pressed.

func BtnpPlayer added in v0.6.0

func BtnpPlayer(button Button, player int) bool

BtnpPlayer returns true when the controller button has just been pressed. It also returns true after the next 15 frames, and then every 4 frames. This simulates keyboard-like repeating. The player can be 0..7.

func Circ added in v0.10.0

func Circ(centerX, centerY, radius int, color byte)

Circ draws a circle on screen.

Circ takes into account camera position, clipping region and draw palette.

func CircFill added in v0.10.0

func CircFill(centerX, centerY, radius int, color byte)

CircFill draws a filled circle

CircFill takes into account camera position, clipping region and draw palette.

func Clip

func Clip(x, y, w, h int) (prevX, prevY, prevW, prevH int)

Clip sets the clipping region in the form of rectangle. All screen drawing operations will not affect any pixels outside the region.

Clip returns previous clipping region. Alternatively, to get the previous clipping region as a struct you might want to use:

pi.Scr().Clip()

before running the pi.Clip.

func ClipReset

func ClipReset() (prevX, prevY, prevW, prevH int)

ClipReset resets the clipping region, which means that entire screen will be clipped.

func Cls

func Cls()

Cls cleans the entire screen with color 0. It does not take into account any global state such as clipping region or camera.

func ClsCol

func ClsCol(col byte)

ClsCol cleans the entire screen with specified color. It does not take into account any global state such as clipping region or camera.

func Cos

func Cos(angle float64) float64

Cos returns the cosine of angle which is in the range of 0.0-1.0 measured clockwise.

If you want to use conventional radian-based function use math.Cos.

func Get added in v0.23.0

func Get(x, y int) byte

Get gets a pixel color on the screen.

func Line added in v0.9.0

func Line(x0, y0, x1, y1 int, color byte)

Line draws a line on screen between points x0,y0 and x1,y1 (inclusive).

Line takes into account camera position, clipping region and draw palette.

func Load added in v0.19.0

func Load(resources fs.ReadFileFS)

Load loads files: sprite-sheet.png, custom-font.png and audio.sfx from resources parameter.

Load looks for images with hard-coded names, eg for sprite-sheet it loads "sprite-sheet.png". Your file name must be exactly the same. And it cannot be inside subdirectory.

sprite-sheet.png file must have an indexed color mode. This means that pixels in the sprite-sheet file refers to an index of the color defined in a small palette, also attached to the file in a form of mapping: index number->RGB color. Image must have an indexed color mode, because Pi loads the palette from the sprite-sheet.png file itself. Please use a pixel-art editor which supports indexed color mode, such as Aseprite (paid) or LibreSprite (free). Sprite-sheet width and height must be multiplication of 8. Each sprite is 8x8 pixels. The maximum number of pixels is 65536 (64KB).

custom-font.png must also have an indexed color mode. Color with index 0 is treated as background. Any other color as foreground. The size of the image is fixed. It must be 128x128. Each char is 8x8. Char 0 is in the top-left corner. Char 1 to the right.

To acquire the resources object, the easiest way is to include the resources in the game binary by using go:embed directive:

package main

// go:embed sprite-sheet.png
var resources embed.FS

func MaxInt added in v0.20.0

func MaxInt[T Int](x, y T) T

MaxInt returns maximum of two integer numbers.

func Mid added in v0.20.0

func Mid(x, y, z float64) float64

Mid returns the middle of three float64 numbers. Very useful for clamping. NaNs are always put at the beginning (are the smallest ones).

func MidInt added in v0.20.0

func MidInt[T Int](x, y, z T) T

MidInt returns the middle of three integer numbers. Very useful for clamping.

func MinInt added in v0.20.0

func MinInt[T Int](x, y T) T

MinInt returns minimum of two integer numbers.

func MouseBtn added in v0.11.0

func MouseBtn(b MouseButton) bool

MouseBtn returns true if the mouse button is being pressed at this moment.

func MouseBtnp added in v0.11.0

func MouseBtnp(b MouseButton) bool

MouseBtnp returns true when the mouse button has just been pressed. It also returns true after the next 15 frames, and then every 4 frames. This simulates keyboard-like repeating.

func Print added in v0.7.1

func Print(text string, x, y int, color byte) (rightMostX int)

Print prints text on the screen using system font. It takes into consideration clipping region and camera position.

Only unicode characters with code < 256 are supported. Unsupported chars are printed as question mark. The entire table of available chars can be found here: https://github.com/elgopher/pi/blob/master/internal/system-font.png

Print returns the right-most x position that occurred while printing.

func Rect added in v0.8.0

func Rect(x0, y0, x1, y1 int, color byte)

Rect draws a rectangle on screen between points x0,y0 and x1,y1 (inclusive).

Rect takes into account camera position, clipping region and draw palette.

func RectFill added in v0.8.0

func RectFill(x0, y0, x1, y1 int, color byte)

RectFill draws a filled rectangle on screen between points x0,y0 and x1,y1 (inclusive).

RectFill takes into account camera position, clipping region and draw palette.

func Reset

func Reset()

func Set added in v0.23.0

func Set(x, y int, color byte)

Set sets a pixel color on the screen. It takes into account camera and draw palette.

func SetCustomFontHeight added in v0.19.0

func SetCustomFontHeight(height int)

SetCustomFontHeight sets height of line (in pixels).

By default, height is 6.

func SetCustomFontSpecialWidth added in v0.19.0

func SetCustomFontSpecialWidth(w int)

SetCustomFontSpecialWidth sets width (in pixels) of all special characters (code>=128).

By default, width is 8. For SpecialWidth > 8 only 8 pixels are drawn.

func SetCustomFontWidth added in v0.19.0

func SetCustomFontWidth(w int)

SetCustomFontWidth sets width (in pixels) for all characters below 128.

By default, width is 4. For Width > 8 only 8 pixels are drawn.

func SetScreenSize added in v0.19.0

func SetScreenSize(width, height int)

SetScreenSize sets the screen size to specified resolution. The maximum number of pixels is 65536 (64KB). Will panic if screen size is too big or width/height are <= 0.

func Sin

func Sin(angle float64) float64

Sin returns the sine of angle which is in the range of 0.0-1.0 measured clockwise.

Sin returns an inverted result to suit screen space (where Y means "DOWN", as opposed to mathematical diagrams where Y typically means "UP"):

sin(0.25) // returns -1

If you want to use conventional radian-based function without the y inversion, use math.Sin.

func Spr

func Spr(n, x, y int)

Spr draws a sprite with specified number on the screen. Sprites are counted from left to right, top to bottom. Sprite 0 is on top-left corner, sprite 1 is to the right and so on.

func SprSize

func SprSize(n, x, y int, w, h float64)

SprSize draws a range of sprites on the screen.

n is a sprite number in the top-left corner.

Non-integer w or h may be used to draw partial sprites.

func SprSizeFlip

func SprSizeFlip(n, x, y int, w, h float64, flipX, flipY bool)

SprSizeFlip draws a range of sprites on the screen.

If flipX is true then sprite is flipped horizontally. If flipY is true then sprite is flipped vertically.

func Stop added in v0.2.0

func Stop()

Stop will stop the game loop after Update or Draw is finished. If you are using devtools, the game will be paused. Otherwise, the game will be closed.

func UseEmptySpriteSheet added in v0.19.0

func UseEmptySpriteSheet(w, h int)

UseEmptySpriteSheet initializes empty sprite-sheet with given size. Could be used when you don't have sprite-sheet.png in resources. The maximum number of pixels is 65536 (64KB).

Types

type Button added in v0.6.0

type Button int

Button is a virtual button on any game controller. The game controller can be a gamepad or a keyboard.

Button is used by Btn, Btnp, BtnPlayer, BtnpPlayer, BtnBits and BtnpBits.

const (
	Left  Button = 0
	Right Button = 1
	Up    Button = 2
	Down  Button = 3
	O     Button = 4 // O is a first fire button
	X     Button = 5 // X is a second fire button
)

Keyboard mappings:

player 0: [DPAD] - cursors  [O] - Z C N   [X] - X V M
player 1: [DPAD] - SFED     [O] - LSHIFT  [X] - TAB W Q A

First connected gamepad controller is player 0, second player 1 and so on. On XBox controller O is A and Y, X is B and X.

type Controller added in v0.19.0

type Controller struct {
	// BtnDuration is how many frames button was pressed:
	// Index of array is equal to Button constant
	BtnDuration [6]uint
}

type Font added in v0.7.1

type Font struct {
	// Data contains all 256 characters sorted by their ascii-like number.
	// Each character is 8 subsequent bytes, starting from the top.
	// Left-most pixel in a line is bit 0. Right-most pixel in a line is bit 7.
	//
	// The size of slice is always 8 * 256 = 2048.
	//
	// Can be freely read and updated. Changes will be visible immediately.
	Data []byte
	// Width in pixels for all characters below 128. For Width > 8 only 8 pixels are drawn.
	Width int
	// SpecialWidth is a width of all special characters (code>=128)
	// For SpecialWidth > 8 only 8 pixels are drawn.
	SpecialWidth int
	// Height of line
	Height int
}

Font contains all information about loaded font and provides method to Print the text.

func CustomFont added in v0.15.0

func CustomFont() Font

CustomFont returns Font instance which can be used for printing text on the screen. CustomFont is loaded from custom-font.png resource file.

func SystemFont added in v0.19.0

func SystemFont() Font

SystemFont returns Font instance for system font. System font cannot be changed.

func (Font) Print added in v0.15.0

func (f Font) Print(text string, x, y int, color byte) int

Print prints text on the screen at given coordinates. It takes into account clipping region and camera position.

Only unicode characters with code < 256 are supported. Unsupported chars are printed as question mark. The entire table of available chars can be found here: https://github.com/elgopher/pi/blob/master/internal/system-font.png

Print returns the right-most x position that occurred while printing.

func (Font) String added in v0.22.0

func (f Font) String() string

String returns Font as string for debugging purposes.

type Int added in v0.20.0

type Int interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}

Int is a generic type for all integer types

type MouseButton added in v0.11.0

type MouseButton int
const (
	MouseLeft   MouseButton = 0
	MouseMiddle MouseButton = 1
	MouseRight  MouseButton = 2
)

type PalMapping added in v0.23.0

type PalMapping [256]byte
var (
	// Pal (draw palette) contains mapping of colors used to replace color with
	// another one for all subsequent drawings. Affected functions are:
	// Set, Spr, SprSize, SprSizeFlip, Circ, CircFill, Line, Rect and RectFill.
	//
	// The index of array is original color, the value is the color replacement.
	// For example,
	//
	//	pi.Pal[7] = 0
	//
	// will change color 7 to 0.
	Pal PalMapping

	// Pald (display palette), a mapping of colors used to replace color with
	// another one for the entire screen, at the end of a frame.
	//
	// The index of array is original color, the value is color replacement.
	// For example,
	//
	//   pi.Pald[7] = 0
	//
	// will change color 7 to 0.
	Pald PalMapping
)

Palette swapping variables. Use them to generate new graphics by swapping colors.

func (*PalMapping) Reset added in v0.23.0

func (p *PalMapping) Reset()

Reset resets all swapped colors to defaults (no swapping).

type PixMap added in v0.20.0

type PixMap struct {
	// contains filtered or unexported fields
}

PixMap is a generic data structure for manipulating any kind of pixel data - screen, sprite-sheet etc. PixMap uses a single byte (8 bits) for storing single color/pixel. This means that max 256 colors can be used. PixMap can also be used for maps which not necessary contain pixel colors, such as world map (as long as only 256 different tiles are used).

To create PixMap please use either NewPixMap or NewPixMapWithPix function.

All PixMap functions (besides Clear and ClearCol) take into account the clipping region.

func NewPixMap added in v0.20.0

func NewPixMap(width, height int) PixMap

NewPixMap creates new instance of PixMap with specified size. Width and height cannot be negative.

func NewPixMapWithPix added in v0.24.0

func NewPixMapWithPix(pix []byte, lineWidth int) PixMap

NewPixMapWithPix creates new instance of PixMap using the slice of pixel colors as a source. pix slice contains colors for the entire PixMap. Pixels are organized from left to right, top to bottom. Slice element number 0 has pixel located in the top-left corner. Slice element number 1 has pixel color on the right, and so on.

The lineWidth is the width of PixMap. Height is calculated by dividing pixels by lineWith.

This function is handy when you already have a pix slice and want to create a PixMap out of it. This function does not allocate anything on the heap.

func Scr added in v0.19.0

func Scr() PixMap

Scr returns the Screen PixMap

func SprSheet added in v0.19.0

func SprSheet() PixMap

SprSheet returns the sprite-sheet PixMap

func (PixMap) Circ added in v0.20.0

func (p PixMap) Circ(centerX int, centerY int, radius int, color byte)

Circ draws a circle.

func (PixMap) CircFill added in v0.20.0

func (p PixMap) CircFill(centerX int, centerY int, radius int, color byte)

func (PixMap) Clear added in v0.20.0

func (p PixMap) Clear()

Clear clears the entire PixMap with color 0. It does not take into account the clipping region.

func (PixMap) ClearCol added in v0.20.0

func (p PixMap) ClearCol(col byte)

ClearCol clears the entire PixMap with specified color. It does not take into account the clipping region.

func (PixMap) Clip added in v0.20.0

func (p PixMap) Clip() Region

Clip returns the clipping region, which specifies which fragment of the PixMap can be accessed by its functions. By default, clipping region has a size of the entire PixMap (no clipping).

func (PixMap) Copy added in v0.20.0

func (p PixMap) Copy(x, y, w, h int, dst PixMap, dstX, dstY int)

Copy copies the region specified by x, y, w, h into dst PixMap at dstX,dstY position.

func (PixMap) Foreach added in v0.20.0

func (p PixMap) Foreach(x, y, w, h int, update func(x, y int, dst []byte))

Foreach runs the update function on PixMap fragment specified by x, y, w and h.

The update function accepts entire line to increase the performance.

func (PixMap) Get added in v0.20.0

func (p PixMap) Get(x, y int) byte

Get returns the pixel color at given position. If coordinates are outside clipping region than color 0 is returned.

func (PixMap) Height added in v0.20.0

func (p PixMap) Height() int

Height returns the height of PixMap, without taking into account the current clipping region.

func (PixMap) Line added in v0.20.0

func (p PixMap) Line(x0, y0, x1, y1 int, color byte)

Line draws a line between points x0,y0 and x1,y1 (inclusive).

func (PixMap) Merge added in v0.20.0

func (p PixMap) Merge(x, y, w, h int, dst PixMap, dstX, dstY int, merge func(dst, src []byte))

Merge merges destination with source by running merge operation for each destination line.

func (PixMap) Pix added in v0.20.0

func (p PixMap) Pix() []byte

Pix return pixel colors. Pixels are organized from left to right, top to bottom. Slice element number 0 has pixel located in the top-left corner. Slice element number 1 has pixel color on the right and so on.

Returned slice can be freely read and updated. Useful when you want to use your own functions for pixel manipulation.

func (PixMap) Pointer added in v0.20.0

func (p PixMap) Pointer(x, y, w, h int) (ptr Pointer, ok bool)

Pointer finds the index of (x,y) coordinates and returns a pointer to pixel data at this position in Pointer.Pix.

If the pixel is outside the clipping region, then the closest pixel to the bottom-right is returned. The difference in position is returned in Pointer.DeltaX and Pointer.DeltaY.

If the pixel is either below or right after the clipping region then ok=false and empty Pointer are returned.

func (PixMap) Rect added in v0.20.0

func (p PixMap) Rect(x0, y0, x1, y1 int, col byte)

Rect draws a rectangle between points x0,y0 and x1,y1 (inclusive).

func (PixMap) RectFill added in v0.20.0

func (p PixMap) RectFill(x0 int, y0 int, x1 int, y1 int, col byte)

RectFill draws a filled rectangle between points x0,y0 and x1,y1 (inclusive).

func (PixMap) Set added in v0.20.0

func (p PixMap) Set(x, y int, col byte)

Set sets the pixel color at given position.

func (PixMap) String added in v0.22.0

func (p PixMap) String() string

String returns PixMap as string for debugging purposes.

func (PixMap) Width added in v0.20.0

func (p PixMap) Width() int

Width returns the width of PixMap (lineWidth), without taking into account the current clipping region.

func (PixMap) WithClip added in v0.20.0

func (p PixMap) WithClip(x, y, w, h int) PixMap

WithClip creates a new PixMap which has a different clipping region. The newly created PixMap still refers to the same pixels though.

type Pointer added in v0.20.0

type Pointer struct {
	// Pix is a slice of PixMap.Pix at the position specified when calling PixMap.Pointer function.
	Pix             []byte
	DeltaX, DeltaY  int
	RemainingPixels int // in line
	RemainingLines  int
}

Pointer is a low-level struct for fast pixel processing created by PixMap.Pointer function.

type Position added in v0.19.0

type Position struct {
	X, Y int
}
var (
	// MouseBtnDuration has how many frames in a row a mouse button was pressed:
	// Index of array is equal to MouseButton constant.
	MouseBtnDuration [3]uint

	// MousePos is the position of mouse in screen coordinates.
	MousePos Position
)
var Camera Position

Camera has camera offset used for all subsequent draw operations.

func (*Position) Reset added in v0.23.0

func (p *Position) Reset()

Reset resets the X and Y to origin (0,0).

func (*Position) Set added in v0.23.0

func (p *Position) Set(x, y int)

type Region added in v0.19.0

type Region struct {
	X, Y, W, H int
}

type Transparency added in v0.23.0

type Transparency [256]bool
var Palt Transparency = defaultTransparency

Palt contains information whether given color is transparent. If true then the color will not be drawn for next drawing operations. Color transparency is used by Spr, SprSize and SprSizeFlip.

The index of array is a color number. For example,

pi.Palt[7] = true

will make color 7 transparent.

func (*Transparency) Reset added in v0.23.0

func (p *Transparency) Reset()

Reset sets all transparent colors to false and makes color 0 transparent.

Directories

Path Synopsis
Package audio provides functions to play sound effects and music.
Package audio provides functions to play sound effects and music.
internal/lib
Package lib provides symbols to be used by Yaegi interpreter.
Package lib provides symbols to be used by Yaegi interpreter.
Package ebitengine uses Ebitengine technology to run the game.
Package ebitengine uses Ebitengine technology to run the game.
examples
controller
Example showing how to test pressed buttons of game controllers.
Example showing how to test pressed buttons of game controllers.
hello
Example animating HELLO WORLD text on screen.
Example animating HELLO WORLD text on screen.
keyboard
Example showing how to use virtual keyboard.
Example showing how to use virtual keyboard.
memory
Example showing how to directly modify screen memory.
Example showing how to directly modify screen memory.
pal
Example showing practical use of palette swapping.
Example showing practical use of palette swapping.
pixmap
Example showing how to use PixMap struct, which is used to store screen and sprite-sheet pixels.
Example showing how to use PixMap struct, which is used to store screen and sprite-sheet pixels.
print
Example showing how to print text to screen.
Example showing how to print text to screen.
resolution
Example showing how to change screen resolution and run π functions before game loop.
Example showing how to change screen resolution and run π functions before game loop.
scripting
DevTools Terminal lets you write and execute Go code live when your game is running.
DevTools Terminal lets you write and execute Go code live when your game is running.
shapes
Example showing how to draw shapes and use a mouse.
Example showing how to draw shapes and use a mouse.
state
Example showing how to save and load the state.
Example showing how to save and load the state.
trigonometry
Example plotting sin and cos on screen
Example plotting sin and cos on screen
Package image provides API for decoding images.
Package image provides API for decoding images.
internal
Package key provides functions for handling virtual keyboard input.
Package key provides functions for handling virtual keyboard input.
Package snap provides functions for taking screenshots.
Package snap provides functions for taking screenshots.
Package state provides functions for managing persistent game data.
Package state provides functions for managing persistent game data.

Jump to

Keyboard shortcuts

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