mirror of
https://github.com/mvvasilev/last_light.git
synced 2025-04-19 12:49:52 +03:00
Fix pathfinding
This commit is contained in:
parent
28cf513b6d
commit
6396c63d73
6 changed files with 48 additions and 20 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,2 +1,5 @@
|
||||||
last_light
|
last_light
|
||||||
last_light.exe
|
last_light.exe
|
||||||
|
|
||||||
|
*.prof
|
||||||
|
__debug_bin*
|
Binary file not shown.
|
@ -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 }) {
|
||||||
|
|
32
engine/pathfinding_test.go
Normal file
32
engine/pathfinding_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue