paths

package module
v0.0.0-...-13bace7 Latest Latest
Warning

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

Go to latest
Published: Jun 15, 2022 License: MIT Imports: 3 Imported by: 3

README

paths

paths

GoDocs

What is paths?

paths is a pathfinding library written in Golang created mainly for video games. Its main feature is simple best-first and shortest-cost path finding.

Why is it called that?

Because I finally learned how to spell.

Why did you create paths?

Because I needed to do pathfinding for a game and couldn't really find any pre-made Golang libraries that seemed to do this, so... Yet again, here we are.

How do I install it?

Just go get it:

go get github.com/SolarLune/paths

How do I use it?

paths is based around defining a Grid, which consists of a rectangular series of Cells. Each Cell occupies a single X and Y position in space, and has a couple of properties that influence pathfinding, which are Cost and Walkability. If a Cell isn't walkable, then it is considered an obstacle that paths generated must circumvent. All Cells default to a Cost of 1; pathfinding will prioritize lower-cost Cells.

import "github.com/SolarLune/paths"

func Init() {

    // This line creates a new Grid, comprised (internally) of Cells. The size is 10x10. Each Cell's 
    // "world" size is 16x16. By default, all Cells are walkable, have a cost of 1, and a blank rune 
    // of ' ' associated with them.
    firstMap = paths.NewGrid(10, 10, 16, 16)
    
    // You can also create the Grid from an array of strings (which are interpreted as arrays of runes), 
    // if you already have it:
    layout := []string{
        "xxxxxxxxxx",
        "x        x",
        "x xxxxxx x",
        "x xg   x x",
        "x xgxx x x",
        "x gggx x x",
        "x xxxx   x",
        "x  xgg x x",
        "xg ggx x x",
        "xxxxxxxxxx",
    }

    secondMap := paths.NewGridFromStringArrays(layout, 16, 16)

    // After creating the Grid, you can edit it using the Grid's functions. Note that here, we're using 'x' 
    // to get Cells that have the rune for the lowercase x character 'x', not the string "x".
    firstMap.SetWalkable('x', false)

    // You can also loop through them by using the `GetCells` functions thusly...
    for _, goop := range secondMap.GetCellsByRune('g') {
        goop.Cost = 5
    }

    // This gets a new Path from the Cell occupied by a starting position [24, 21], to another [99, 78]. The last boolean argument,
    // false, indicates whether moving diagonally is fine when creating the Path.
    firstPath := GameMap.GetPath(24, 21, 99, 78, false)

    // You can also get a path using references to the Cells directly.
    secondPath := GameMap.GetPathFromCell(GameMap.Get(1, 1), GameMap.Get(6, 3), false)

    // After that, you can use Path.Current() and Path.Next() to get the current and next Cells on the Path. When you determine that 
    // the pathfinding agent has reached that Cell, you can kick the Path forward with path.Advance().

    // And that's it!

}


And that's about it! If you want to see more info or examples, feel free to examine the main.go and world.go tests to see how the test is set up.

You can check out the GoDoc link here, as well.

You can also run the example by installing SDL with the instructions here and then:

$ cd ./example
$ go run ./

Dependencies?

For the actual package, there are no external dependencies.

For the tests, paths requires veandco's sdl2 port to create the window, handle input, and draw the shapes and text.

Shout-out Time!

Props to whoever made arcadepi.ttf! It's a nice font.

Thanks a lot to the SDL2 team for development.

Thanks to veandco for maintaining the Golang SDL2 port, as well!

Documentation

Overview

Package paths is a simple library written in Go made to handle 2D pathfinding for games. All you need to do is generate a Grid, specify which cells aren't walkable, optionally change the cost on specific cells, and finally get a path from one cell to another.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DiaganalDistance

func DiaganalDistance(start, dest *Cell) float64

DiaganalDistance heuristic for when diaganol movement is allowed.

func ManhattenDistance

func ManhattenDistance(start, dest *Cell) float64

ManhattenDistance heuristic for a simple four directional movement.

Types

type Cell

type Cell struct {
	X, Y     int
	Cost     float64
	Walkable bool
	Rune     rune
}

A Cell represents a point on a Grid map. It has an X and Y value for the position, a Cost, which influences which Cells are ideal for paths, Walkable, which indicates if the tile can be walked on or should be avoided, and a Rune, which indicates which rune character the Cell is represented by.

func (Cell) String

func (cell Cell) String() string

type Grid

type Grid struct {
	Data                  [][]*Cell
	CellWidth, CellHeight int
}

Grid represents a "map" composed of individual Cells at each point in the map. Data is a 2D array of Cells. CellWidth and CellHeight indicate the size of Cells for Cell Position <-> World Position translation.

func NewGrid

func NewGrid(gridWidth, gridHeight, cellWidth, cellHeight int) *Grid

NewGrid returns a new Grid of (gridWidth x gridHeight) size. cellWidth and cellHeight changes the size of each Cell in the Grid. This is used to translate world position to Cell positions (i.e. the Cell position [2, 5] with a CellWidth and CellHeight of [16, 16] would be the world positon [32, 80]).

func NewGridFromRuneArrays

func NewGridFromRuneArrays(arrays [][]rune, cellWidth, cellHeight int) *Grid

NewGridFromRuneArrays creates a Grid map from a 2D array of runes. Each individual Rune becomes a Cell in the resulting Grid. cellWidth and cellHeight changes the size of each Cell in the Grid. This is used to translate world position to Cell positions (i.e. the Cell position [2, 5] with a CellWidth and CellHeight of [16, 16] would be the world positon [32, 80]).

func NewGridFromStringArrays

func NewGridFromStringArrays(arrays []string, cellWidth, cellHeight int) *Grid

NewGridFromStringArrays creates a Grid map from a 1D array of strings. Each string becomes a row of Cells, each with one rune as its character. cellWidth and cellHeight changes the size of each Cell in the Grid. This is used to translate world position to Cell positions (i.e. the Cell position [2, 5] with a CellWidth and CellHeight of [16, 16] would be the world positon [32, 80]).

func (*Grid) AllCells

func (m *Grid) AllCells() []*Cell

AllCells returns a single slice of pointers to all Cells contained in the Grid's 2D Data array.

func (*Grid) CellsByCost

func (m *Grid) CellsByCost(cost float64) []*Cell

CellsByCost returns a slice of pointers to Cells that all have the Cost value provided.

func (*Grid) CellsByRune

func (m *Grid) CellsByRune(char rune) []*Cell

CellsByRune returns a slice of pointers to Cells that all have the character provided.

func (*Grid) CellsByWalkable

func (m *Grid) CellsByWalkable(walkable bool) []*Cell

CellsByWalkable returns a slice of pointers to Cells that all have the Cost value provided.

func (*Grid) DataAsRuneArrays

func (m *Grid) DataAsRuneArrays() [][]rune

DataAsRuneArrays returns a 2D array of runes for each Cell in the Grid. The first axis is the Y axis.

func (*Grid) DataAsStringArray

func (m *Grid) DataAsStringArray() []string

DataAsStringArray returns a 2D array of runes for each Cell in the Grid. The first axis is the Y axis.

func (*Grid) DataToString

func (m *Grid) DataToString() string

DataToString returns a string, used to easily identify the Grid map.

func (*Grid) Get

func (m *Grid) Get(x, y int) *Cell

Get returns a pointer to the Cell in the x and y position provided.

func (*Grid) GetPath

func (m *Grid) GetPath(startX, startY, endX, endY float64, diagonals bool, wallsBlockDiagonals bool) *Path

GetPath returns a Path, from the starting world X and Y position to the ending X and Y position. diagonals controls whether moving diagonally is acceptable when creating the Path. wallsBlockDiagonals indicates whether to allow diagonal movement "through" walls that are positioned diagonally. This is essentially just a smoother way to get a Path from GetPathFromCells().

func (*Grid) GetPathFromCells

func (m *Grid) GetPathFromCells(start, dest *Cell, diagonals, wallsBlockDiagonals bool) *Path

GetPathFromCells returns a Path, from the starting Cell to the destination Cell. diagonals controls whether moving diagonally is acceptable when creating the Path. wallsBlockDiagonals indicates whether to allow diagonal movement "through" walls that are positioned diagonally.

func (*Grid) GetPathFromCellsAStar

func (m *Grid) GetPathFromCellsAStar(start, dest *Cell, diagonals, wallsBlockDiagonals bool) *Path

GetPathFromCellsAStar returns a Path, from the starting Cell to the destination Cell. diagonals controls whether moving diagonally is acceptable when creating the Path. wallsBlockDiagonals indicates whether to allow diagonal movement "through" walls that are positioned diagonally.

func (*Grid) GridToWorld

func (m *Grid) GridToWorld(x, y int) (float64, float64)

GridToWorld converts from a grid position to world position, multiplying the value by the CellWidth and CellHeight of the Grid.

func (*Grid) Height

func (m *Grid) Height() int

Height returns the height of the Grid map.

func (*Grid) SetCost

func (m *Grid) SetCost(char rune, cost float64)

SetCost sets the movement cost across all cells in the Grid with the specified rune.

func (*Grid) SetWalkable

func (m *Grid) SetWalkable(char rune, walkable bool)

SetWalkable sets walkability across all cells in the Grid with the specified rune.

func (*Grid) Width

func (m *Grid) Width() int

Width returns the width of the Grid map.

func (*Grid) WorldToGrid

func (m *Grid) WorldToGrid(x, y float64) (int, int)

WorldToGrid converts from a grid position to world position, multiplying the value by the CellWidth and CellHeight of the Grid.

type Node

type Node struct {
	Cell   *Cell
	Parent *Node
	Cost   float64
	// contains filtered or unexported fields
}

Node represents the node a path, it contains the cell it represents. Also contains other information such as the parent and the cost.

type Path

type Path struct {
	Cells        []*Cell
	CurrentIndex int
}

A Path is a struct that represents a path, or sequence of Cells from point A to point B. The Cells list is the list of Cells contained in the Path, and the CurrentIndex value represents the current step on the Path. Using Path.Next() and Path.Prev() advances and walks back the Path by one step.

func (*Path) Advance

func (p *Path) Advance()

Advance advances the path by one cell.

func (*Path) AtEnd

func (p *Path) AtEnd() bool

AtEnd returns if the Path's current index is the last Cell in the Path.

func (*Path) AtStart

func (p *Path) AtStart() bool

AtStart returns if the Path's current index is 0, the first Cell in the Path.

func (*Path) Current

func (p *Path) Current() *Cell

Current returns the current Cell in the Path.

func (*Path) Get

func (p *Path) Get(index int) *Cell

Get returns the Cell of the specified index in the Path. If the index is outside of the length of the Path, it returns -1.

func (*Path) Index

func (p *Path) Index(cell *Cell) int

Index returns the index of the specified Cell in the Path. If the Cell isn't contained in the Path, it returns -1.

func (*Path) Length

func (p *Path) Length() int

Length returns the length of the Path (how many Cells are in the Path).

func (*Path) Next

func (p *Path) Next() *Cell

Next returns the next cell in the path. If the Path is at the end, Next() returns nil.

func (*Path) Prev

func (p *Path) Prev() *Cell

Prev returns the previous cell in the path. If the Path is at the start, Prev() returns nil.

func (*Path) Restart

func (p *Path) Restart()

Restart restarts the Path, so that calling path.Current() will now return the first Cell in the Path.

func (*Path) Reverse

func (p *Path) Reverse()

Reverse reverses the Cells in the Path.

func (*Path) Same

func (p *Path) Same(otherPath *Path) bool

Same returns if the Path shares the exact same cells as the other specified Path.

func (*Path) SetIndex

func (p *Path) SetIndex(index int)

SetIndex sets the index of the Path, allowing you to safely manually manipulate the Path as necessary. If the index exceeds the bounds of the Path, it will be clamped.

func (*Path) String

func (p *Path) String() string

AtEnd returns if the Path's current index is the last Cell in the Path.

func (*Path) TotalCost

func (p *Path) TotalCost() float64

TotalCost returns the total cost of the Path (i.e. is the sum of all of the Cells in the Path).

Jump to

Keyboard shortcuts

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