Fix pathfinding

This commit is contained in:
Miroslav Vasilev 2024-05-13 01:01:39 +03:00
parent 28cf513b6d
commit 6396c63d73
6 changed files with 48 additions and 20 deletions

3
.gitignore vendored
View file

@ -1,2 +1,5 @@
last_light last_light
last_light.exe last_light.exe
*.prof
__debug_bin*

Binary file not shown.

View file

@ -1,7 +1,6 @@
package engine package engine
import ( import (
"math"
"slices" "slices"
) )
@ -10,14 +9,12 @@ type pathNode struct {
parent *pathNode parent *pathNode
g float64 // distance between current node and start node g int // distance between current node and start node
h float64 // heuristic - squared distance from current node to end node h int // heuristic - squared distance from current node to end node
f float64 // total cost of this node f int // total cost of this node
} }
func FindPath(from Position, to Position, maxDistance int, isPassable func(x, y int) bool) *Path { func FindPath(from Position, to Position, isPassable func(x, y int) bool) *Path {
maxDistanceSquared := math.Pow(float64(maxDistance), 2)
var openList = make([]*pathNode, 0) var openList = make([]*pathNode, 0)
var closedList = make([]*pathNode, 0) var closedList = make([]*pathNode, 0)
@ -32,6 +29,7 @@ func FindPath(from Position, to Position, maxDistance int, isPassable func(x, y
var lastNode *pathNode var lastNode *pathNode
for { for {
if len(openList) == 0 { if len(openList) == 0 {
break break
} }
@ -87,13 +85,8 @@ func FindPath(from Position, to Position, maxDistance int, isPassable func(x, y
} }
child.g = currentNode.g + 1 child.g = currentNode.g + 1
if child.g > maxDistanceSquared {
continue
}
child.h = to.DistanceSquared(child.pos) child.h = to.DistanceSquared(child.pos)
child.f = float64(child.g) + child.f child.f = child.g + child.h
// If child is already contained in openList, and has lower g // If child is already contained in openList, and has lower g
if slices.ContainsFunc(openList, func(el *pathNode) bool { return el.pos.Equals(child.pos) && child.g > el.g }) { if slices.ContainsFunc(openList, func(el *pathNode) bool { return el.pos.Equals(child.pos) && child.g > el.g }) {

View file

@ -0,0 +1,32 @@
package engine
import (
"log"
"testing"
)
func BenchmarkPathfinding(b *testing.B) {
path := FindPath(
PositionAt(0, 0),
PositionAt(16, 16),
func(x, y int) bool {
if x > 6 && x <= 16 && y == 10 {
return false
}
if x < 0 || y < 0 {
return false
}
if x > 16 || y > 16 {
return false
}
return true
},
)
if path == nil {
log.Fatalf("No path could be found")
}
}

View file

@ -44,12 +44,12 @@ func (p Position) XY() (int, int) {
return p.x, p.y return p.x, p.y
} }
func (p Position) DistanceSquared(pos Position) float64 { func (p Position) DistanceSquared(pos Position) int {
return float64((pos.x-p.x)*(pos.x-p.x) + (pos.y-p.y)*(pos.y-p.y)) return (pos.x-p.x)*(pos.x-p.x) + (pos.y-p.y)*(pos.y-p.y)
} }
func (p Position) Distance(pos Position) float64 { func (p Position) Distance(pos Position) int {
return math.Sqrt(p.DistanceSquared(pos)) return int(math.Floor(math.Sqrt(float64(p.DistanceSquared(pos)))))
} }
func (p Position) Equals(other Position) bool { func (p Position) Equals(other Position) bool {

View file

@ -181,14 +181,14 @@ func (ps *PlayingState) PickUpItemUnderPlayer() {
func (ps *PlayingState) CalcPathToPlayerAndMove() { func (ps *PlayingState) CalcPathToPlayerAndMove() {
distanceToPlayer := ps.someNPC.Position().Distance(ps.player.Position()) distanceToPlayer := ps.someNPC.Position().Distance(ps.player.Position())
if distanceToPlayer > 16 {
if distanceToPlayer > 20 {
return return
} }
pathToPlayer := engine.FindPath( pathToPlayer := engine.FindPath(
ps.someNPC.Position(), ps.someNPC.Position(),
ps.player.Position(), ps.player.Position(),
16,
func(x, y int) bool { func(x, y int) bool {
if x == ps.player.Position().X() && y == ps.player.Position().Y() { if x == ps.player.Position().X() && y == ps.player.Position().Y() {
return true return true