Add pathfinding garbagio
This commit is contained in:
parent
c5cad47762
commit
a9fba17943
|
@ -27,6 +27,8 @@ type Game struct {
|
||||||
cellX, cellY int
|
cellX, cellY int
|
||||||
fromX, fromY int
|
fromX, fromY int
|
||||||
toX, toY int
|
toX, toY int
|
||||||
|
path []sauce.Node
|
||||||
|
pathSuccess bool
|
||||||
whichFromTo bool
|
whichFromTo bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +37,10 @@ func NewGame() *Game {
|
||||||
g.world = sauce.NewWorld(3, 3)
|
g.world = sauce.NewWorld(3, 3)
|
||||||
g.world.HueristicLine(10, 0, 10, 10, 1)
|
g.world.HueristicLine(10, 0, 10, 10, 1)
|
||||||
g.world.HueristicLine(10, 13, 10, 30, 1)
|
g.world.HueristicLine(10, 13, 10, 30, 1)
|
||||||
|
g.fromX = -1
|
||||||
|
g.fromY = -1
|
||||||
|
g.toX = -1
|
||||||
|
g.toY = -1
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,10 +68,13 @@ func (g *Game) Update() error {
|
||||||
g.cellX = cursorX / CellSize
|
g.cellX = cursorX / CellSize
|
||||||
g.cellY = cursorY / CellSize
|
g.cellY = cursorY / CellSize
|
||||||
if cell := g.world.At(g.cellX, g.cellY); cell != nil {
|
if cell := g.world.At(g.cellX, g.cellY); cell != nil {
|
||||||
|
var reroll bool
|
||||||
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
|
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
|
||||||
cell.Hueristic++
|
cell.Hueristic++
|
||||||
|
reroll = true
|
||||||
} else if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonRight) {
|
} else if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonRight) {
|
||||||
cell.Hueristic--
|
cell.Hueristic--
|
||||||
|
reroll = true
|
||||||
} else if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonMiddle) {
|
} else if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonMiddle) {
|
||||||
if !g.whichFromTo {
|
if !g.whichFromTo {
|
||||||
g.fromX, g.fromY = g.cellX, g.cellY
|
g.fromX, g.fromY = g.cellX, g.cellY
|
||||||
|
@ -73,6 +82,13 @@ func (g *Game) Update() error {
|
||||||
g.toX, g.toY = g.cellX, g.cellY
|
g.toX, g.toY = g.cellX, g.cellY
|
||||||
}
|
}
|
||||||
g.whichFromTo = !g.whichFromTo
|
g.whichFromTo = !g.whichFromTo
|
||||||
|
reroll = true
|
||||||
|
}
|
||||||
|
if reroll {
|
||||||
|
if g.fromX != -1 && g.fromY != -1 && g.toX != -1 && g.toY != -1 {
|
||||||
|
g.path, g.pathSuccess = sauce.FindPath(g.world, g.fromX, g.fromY, g.toX, g.toY)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -117,6 +133,18 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Draw path dots overtop.
|
||||||
|
for _, node := range g.path {
|
||||||
|
x := node.X*CellSize + CellSize/2
|
||||||
|
y := node.Y*CellSize + CellSize/2
|
||||||
|
|
||||||
|
c := color.RGBA{0, 255, 0, 255}
|
||||||
|
if !g.pathSuccess {
|
||||||
|
c = color.RGBA{255, 0, 0, 255}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector.DrawFilledCircle(screen, float32(x), float32(y), 5, c, false)
|
||||||
|
}
|
||||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f\nFPS: %0.2f", ebiten.ActualTPS(), ebiten.ActualFPS()))
|
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f\nFPS: %0.2f", ebiten.ActualTPS(), ebiten.ActualFPS()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
127
sauce/astar.go
127
sauce/astar.go
|
@ -1,85 +1,100 @@
|
||||||
package sauce
|
package sauce
|
||||||
|
|
||||||
type Node struct {
|
import (
|
||||||
parent *Node
|
"math"
|
||||||
x, y int
|
)
|
||||||
f, g, h int
|
|
||||||
|
type Coord struct {
|
||||||
|
X, Y int16
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindPath(w *World, fromX, fromY int, toX, toY int) []Node {
|
type Node struct {
|
||||||
openList := make([]*Node, 0)
|
Coord
|
||||||
closedList := make([]*Node, 0)
|
parent *Node
|
||||||
|
g int
|
||||||
|
f int
|
||||||
|
d int
|
||||||
|
}
|
||||||
|
|
||||||
startNode := &Node{x: fromX, y: fromY}
|
type Nodes map[Coord]*Node
|
||||||
endNode := &Node{x: toX, y: toY}
|
|
||||||
|
|
||||||
openList = append(openList, startNode)
|
func FindPath(w *World, fromX, fromY int, toX, toY int) ([]Node, bool) {
|
||||||
|
var open []*Node
|
||||||
|
visited := make(Nodes)
|
||||||
|
|
||||||
for len(openList) > 0 {
|
open = append(open, &Node{Coord: Coord{int16(fromX), int16(fromY)}})
|
||||||
var cnode *Node
|
|
||||||
var cindex int
|
for len(open) > 0 {
|
||||||
for i, node := range openList {
|
var current *Node
|
||||||
if cnode == nil || node.f < cnode.f {
|
var currentI int
|
||||||
cnode = node
|
// Set current to lowest f in open
|
||||||
cindex = i
|
for i, n := range open {
|
||||||
|
if current == nil || n.f < current.f {
|
||||||
|
current = n
|
||||||
|
currentI = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
openList = append(openList[:cindex], openList[cindex+1:]...)
|
|
||||||
closedList = append(closedList, cnode)
|
|
||||||
|
|
||||||
if cnode.x == endNode.x && cnode.y == endNode.y {
|
// Return reconstructed path if current is the destination.
|
||||||
path := make([]Node, 0)
|
if current.X == int16(toX) && current.Y == int16(toY) {
|
||||||
for cnode != nil {
|
var path []Node
|
||||||
path = append(path, *cnode)
|
for current.parent != nil {
|
||||||
cnode = cnode.parent
|
path = append(path, *current)
|
||||||
|
current = current.parent
|
||||||
}
|
}
|
||||||
return path
|
return path, true
|
||||||
}
|
}
|
||||||
|
// Remove current from the open set.
|
||||||
|
open = append(open[:currentI], open[currentI+1:]...)
|
||||||
|
|
||||||
var neighbors []Node
|
// Get neighbors.
|
||||||
|
var neighbors []*Node
|
||||||
for x := -1; x <= 1; x++ {
|
for x := -1; x <= 1; x++ {
|
||||||
for y := -1; y <= 1; y++ {
|
for y := -1; y <= 1; y++ {
|
||||||
if x == 0 && y == 0 {
|
if x == 0 && y == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if x != 0 && y != 0 {
|
coord := Coord{current.X + int16(x), current.Y + int16(y)}
|
||||||
|
if cell := w.At(int(coord.X), int(coord.Y)); cell == nil || cell.Hueristic == 255 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if cell := w.At(cnode.x+x, cnode.y+y); cell != nil {
|
neighbors = append(neighbors, &Node{Coord: coord, parent: current, g: math.MaxUint16, f: math.MaxUint16})
|
||||||
neighbors = append(neighbors, Node{x: cnode.x + x, y: cnode.y + y, parent: cnode})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterate over neighbors.
|
||||||
for _, neighbor := range neighbors {
|
for _, neighbor := range neighbors {
|
||||||
exists := false
|
tentativeG := current.g + 1
|
||||||
for _, node := range closedList {
|
distance := int(math.Abs(float64(neighbor.X)-float64(toX)) + math.Abs(float64(neighbor.Y)-float64(toY)))
|
||||||
if node.x == neighbor.x && node.y == neighbor.y {
|
tentativeF := tentativeG + distance
|
||||||
exists = true
|
|
||||||
break
|
var node *Node
|
||||||
|
if node = visited[neighbor.Coord]; node == nil || tentativeF < node.f {
|
||||||
|
if node == nil {
|
||||||
|
node = neighbor
|
||||||
}
|
}
|
||||||
|
node.g = tentativeG
|
||||||
|
node.f = tentativeF
|
||||||
|
node.d = distance
|
||||||
|
visited[node.Coord] = node
|
||||||
|
open = append(open, node)
|
||||||
}
|
}
|
||||||
if exists {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
exists = false
|
|
||||||
for _, node := range openList {
|
|
||||||
if node.x == neighbor.x && node.y == neighbor.y {
|
|
||||||
exists = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if exists {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
neighbor.g = cnode.g + 1 // this value potentially should be a float and modified if a diagonal.
|
|
||||||
neighbor.h = (toX - neighbor.x) + (toY - neighbor.y) // Maybe should be calculated differently.
|
|
||||||
neighbor.f = neighbor.g + neighbor.h
|
|
||||||
|
|
||||||
openList = append(openList, &neighbor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
var current *Node
|
||||||
|
// Set current to lowest f in open
|
||||||
|
for _, n := range visited {
|
||||||
|
if current == nil || n.d < current.d {
|
||||||
|
current = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return reconstructed path if current is the destination.
|
||||||
|
var path []Node
|
||||||
|
for current != nil && current.parent != nil {
|
||||||
|
path = append(path, *current)
|
||||||
|
current = current.parent
|
||||||
|
}
|
||||||
|
return path, false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user